From 71478004a83e2b09ba22d3d5a8a94ec6d986e66a Mon Sep 17 00:00:00 2001 From: Kartik Agaram Date: Fri, 21 Feb 2020 10:21:38 -0800 Subject: 6042 --- html/apps/factorial.mu.html | 68 +- html/apps/mu.subx.html | 16824 +++++++++++++++++++++--------------------- 2 files changed, 8477 insertions(+), 8415 deletions(-) (limited to 'html/apps') diff --git a/html/apps/factorial.mu.html b/html/apps/factorial.mu.html index 7e3cf43f..7a5d1583 100644 --- a/html/apps/factorial.mu.html +++ b/html/apps/factorial.mu.html @@ -56,11 +56,11 @@ if ('onhashchange' in window) { https://github.com/akkartik/mu/blob/master/apps/factorial.mu
- 1 # usage is finicky for now:
+ 1 # usage:
  2 #   ./translate_mu apps/factorial.mu
- 3 #   ./a.elf test  # any args? run tests
- 4 #   ./a.elf       # no args? run factorial(5)
- 5 fn main args: (addr array kernel-string) -> exit-status/ebx: int {
+ 3 #   ./a.elf test  # to run tests
+ 4 #   ./a.elf       # to run factorial(5)
+ 5 fn main args: (addr array kernel-string) -> exit-status/ebx: int {
  6   var a/eax: (addr array kernel-string) <- copy args
  7   var tmp/ecx: int <- length a
  8   $main-body: {
@@ -68,38 +68,42 @@ if ('onhashchange' in window) {
 10     # if (len(args) == 1) factorial(5)
 11     {
 12       break-if-!=
-13       var tmp/eax: int <- factorial 5
+13       var tmp/eax: int <- factorial 5
 14       exit-status <- copy tmp
 15       break $main-body
 16     }
-17     # if (len(args) != 1) run-tests()
-18     {
-19       break-if-=
-20       run-tests
-21       exit-status <- copy 0
-22     }
-23   }
-24 }
-25 
-26 fn factorial n: int -> result/eax: int {
-27   compare n 1
-28   {
-29     break-if->
-30     result <- copy 1
-31   }
+17     # if (args[1] == "test") run-tests()
+18     var tmp2/ecx: int <- copy 1  # we need this just because we don't yet support `index` on literals; requires some translation-time computation
+19     var tmp3/ecx: (addr kernel-string) <- index a, tmp2
+20     var tmp4/eax: boolean <- kernel-string-equal? *tmp3, "test"
+21     compare tmp4, 0
+22     {
+23       break-if-=
+24       run-tests
+25       exit-status <- copy 0  # TODO: get at Num-test-failures somehow
+26     }
+27   }
+28 }
+29 
+30 fn factorial n: int -> result/eax: int {
+31   compare n 1
 32   {
-33     break-if-<=
-34     var tmp/ecx: int <- copy n
-35     tmp <- decrement
-36     result <- factorial tmp
-37     result <- multiply n
-38   }
-39 }
-40 
-41 fn test-factorial {
-42   var result/eax: int <- factorial 5
-43   check-ints-equal result 0x78 "F - test-factorial"
-44 }
+33     break-if->
+34     result <- copy 1
+35   }
+36   {
+37     break-if-<=
+38     var tmp/ecx: int <- copy n
+39     tmp <- decrement
+40     result <- factorial tmp
+41     result <- multiply n
+42   }
+43 }
+44 
+45 fn test-factorial {
+46   var result/eax: int <- factorial 5
+47   check-ints-equal result 0x78 "F - test-factorial"
+48 }
 
diff --git a/html/apps/mu.subx.html b/html/apps/mu.subx.html index 97ded5df..36707012 100644 --- a/html/apps/mu.subx.html +++ b/html/apps/mu.subx.html @@ -94,3013 +94,3008 @@ if ('onhashchange' in window) { 32 # eax ecx edx ebx esi edi 33 # Variables in registers must be primitive 32-bit types. 34 # Variables not explicitly placed in a register are on the stack. - 35 # Variables in registers need not have a name; in that case you refer to them - 36 # directly by the register name. - 37 # - 38 # Function inputs are always passed in memory (on the stack), while outputs - 39 # are always returned in registers. + 35 # + 36 # Function inputs are always passed in memory (on the stack), while outputs + 37 # are always returned in registers. + 38 # + 39 # Blocks mostly consist of statements. 40 # - 41 # Blocks mostly consist of statements. + 41 # Statements mostly consist of a name, optional inputs and optional outputs. 42 # - 43 # Statements mostly consist of a name, optional inputs and optional outputs. - 44 # - 45 # Statement inputs are variables or literals. Variables need to specify type - 46 # (and storage) the first time they're mentioned but not later. + 43 # Statement inputs are variables or literals. Variables need to specify type + 44 # (and storage) the first time they're mentioned but not later. + 45 # + 46 # Statement outputs, like function outputs, must be variables in registers. 47 # - 48 # Statement outputs, like function outputs, must be variables in registers. + 48 # Statement names must be either primitives or user-defined functions. 49 # - 50 # Statement names must be either primitives or user-defined functions. - 51 # - 52 # Primitives can write to any register. - 53 # User-defined functions only write to hard-coded registers. Outputs of each - 54 # call must have the same registers as in the function definition. - 55 # - 56 # There are some other statement types: - 57 # - blocks. Multiple statements surrounded by '{...}' and optionally - 58 # prefixed with a label name and ':' - 59 # - { - 60 # ... - 61 # } - 62 # - foo: { - 63 # ... - 64 # } - 65 # - 66 # - variable definitions on the stack. E.g.: - 67 # - var foo: int - 68 # - var bar: (array int 3) - 69 # There's no initializer; variables are automatically initialized. - 70 # The type of a local variable is either word-length (4 bytes) or starts with 'ref'. - 71 # - 72 # - variables definitions in a register. E.g.: - 73 # - var foo/eax: int <- add bar 1 - 74 # The initializer is mandatory and must be a valid instruction that writes - 75 # a single output to the right register. In practice registers will - 76 # usually be either initialized by primitives or copied from eax. - 77 # - var eax: int <- foo bar quux - 78 # var floo/ecx: int <- copy eax - 79 # - 80 # Still todo: - 81 # global variables - 82 # heap allocations (planned name: 'handle') - 83 # user-defined types: 'type' for structs, 'choice' for unions - 84 # short-lived 'address' type for efficiently writing inside nested structs - 85 # - 86 # We don't have 'handle' types yet, but we try to distinguish 'ref', 'handle' - 87 # and 'address' in comments. Their definitions are in layer 50, but really you - 88 # can ignore the distinctions on a first reading of this program. - 89 # - 90 # Formal types: - 91 # A program is a linked list of functions - 92 # A function contains: - 93 # name: (handle array byte) - 94 # inouts: linked list of vars <-- 'inouts' is more precise than 'inputs' - 95 # data: (handle var) - 96 # next: (handle list) - 97 # outputs: linked list of vars - 98 # data: (handle var) - 99 # next: (handle list) - 100 # body: (handle block) - 101 # A var-type contains: - 102 # name: (handle array byte) - 103 # type: (handle tree type-id) - 104 # - 105 # A statement can be: - 106 # tag 0: a block - 107 # tag 1: a simple statement (stmt1) - 108 # tag 2: a variable defined on the stack - 109 # tag 3: a variable defined in a register - 110 # - 111 # A block contains: - 112 # tag: 0 - 113 # statements: (handle list statement) - 114 # name: (handle array byte) -- starting with '$' - 115 # - 116 # A regular statement contains: - 117 # tag: 1 - 118 # operation: (handle array byte) - 119 # inouts: (handle list operand) - 120 # outputs: (handle list var) - 121 # - 122 # A variable defined on the stack contains: - 123 # tag: 2 - 124 # name: (handle array byte) - 125 # type: (handle tree type-id) - 126 # - 127 # A variable defined in a register contains: - 128 # tag: 3 - 129 # name: (handle array byte) - 130 # type: (handle tree type-id) - 131 # reg: (handle array byte) - 132 - 133 # == Translation: managing the stack - 134 # Now that we know what the language looks like in the large, let's think - 135 # about how translation happens from the bottom up. One crucial piece of the - 136 # puzzle is how Mu will clean up variables defined on the stack for you. - 137 # - 138 # Assume that we maintain a 'functions' list while parsing source code. And a - 139 # 'primitives' list is a global constant. Both these contain enough information - 140 # to perform type-checking on function calls or primitive statements, respectively. - 141 # - 142 # Defining variables pushes them on a stack with the current block depth and - 143 # enough information about their location (stack offset or register). - 144 # Starting a block increments the current block id. - 145 # Each statement now has enough information to emit code for it. - 146 # Ending a block is where the magic happens: - 147 # pop all variables at the current block depth - 148 # emit code to restore all register variables introduced at the current depth - 149 # emit code to clean up all stack variables at the current depth (just increment esp) - 150 # decrement the current block depth - 151 # - 152 # Formal types: - 153 # live-vars: stack of vars - 154 # var: - 155 # name: (handle array byte) - 156 # type: (handle tree type-id) - 157 # block: int - 158 # stack-offset: int (added to ebp) - 159 # register: (handle array byte) - 160 # either usual register names - 161 # or '*' to indicate any register - 162 # At most one of stack-offset or register-index must be non-zero. - 163 # A register of '*' designates a variable _template_. Only legal in formal - 164 # parameters for primitives. - 165 - 166 # == Translating a single function call - 167 # This one's easy. Assuming we've already checked things, we just drop the - 168 # outputs (which use hard-coded registers) and emit inputs in a standard format. - 169 # - 170 # out1, out2, out3, ... <- name inout1, inout2, inout3, ... - 171 # => - 172 # (subx-name inout1 inout2 inout3) - 173 # - 174 # Formal types: - 175 # functions: linked list of info - 176 # name: (handle array byte) - 177 # inouts: linked list of vars - 178 # outputs: linked list of vars - 179 # body: block (singleton linked list) - 180 # subx-name: (handle array byte) - 181 - 182 # == Translating a single primitive instruction - 183 # A second crucial piece of the puzzle is how Mu converts fairly regular - 184 # primitives with their uniform syntax to SubX instructions with their gnarly - 185 # x86 details. - 186 # - 187 # Mu instructions have inputs and outputs. Primitives can have up to 2 of - 188 # them. - 189 # SubX instructions have rm32 and r32 operands. - 190 # The translation between them covers almost all the possibilities. - 191 # Instructions with 1 inout may turn into ones with 1 rm32 - 192 # (e.g. incrementing a var on the stack) - 193 # Instructions with 1 output may turn into ones with 1 rm32 - 194 # (e.g. incrementing a var in a register) - 195 # 1 inout and 1 output may turn into 1 rm32 and 1 r32 - 196 # (e.g. adding a var to a reg) - 197 # 2 inouts may turn into 1 rm32 and 1 r32 - 198 # (e.g. adding a reg to a var) - 199 # 1 inout and 1 literal may turn into 1 rm32 and 1 imm32 - 200 # (e.g. adding a constant to a var) - 201 # 1 output and 1 literal may turn into 1 rm32 and 1 imm32 - 202 # (e.g. adding a constant to a reg) - 203 # 2 outputs to hardcoded registers and 1 inout may turn into 1 rm32 - 204 # (special-case: divide edx:eax by a var or reg) - 205 # Observations: - 206 # We always emit rm32. It may be the first inout or the first output. - 207 # We may emit r32 or imm32 or neither. - 208 # When we emit r32 it may come from first inout or second inout or first output. - 209 # - 210 # Accordingly, the formal data structure for a primitive looks like this: - 211 # primitives: linked list of info - 212 # name: (handle array byte) - 213 # mu-inouts: linked list of vars to check - 214 # mu-outputs: linked list of vars to check; at most a singleton - 215 # subx-name: (handle array byte) - 216 # subx-rm32: enum arg-location - 217 # subx-r32: enum arg-location - 218 # subx-imm32: enum arg-location - 219 # subx-disp32: enum arg-location - 220 # output-is-write-only: boolean - 221 # arg-location: enum - 222 # 0 means none - 223 # 1 means first inout - 224 # 2 means second inout - 225 # 3 means first output - 226 - 227 # == Translating a block - 228 # Emit block name if necessary - 229 # Emit '{' - 230 # When you encounter a statement, emit it as above - 231 # When you encounter a variable declaration - 232 # emit any code needed for it (bzeros) - 233 # push it on the var stack - 234 # update register dict if necessary - 235 # When you encounter '}' - 236 # While popping variables off the var stack until block id changes - 237 # Emit code needed to clean up the stack - 238 # either increment esp - 239 # or pop into appropriate register + 50 # Primitives can write to any register. + 51 # User-defined functions only write to hard-coded registers. Outputs of each + 52 # call must have the same registers as in the function definition. + 53 # + 54 # There are some other statement types: + 55 # - blocks. Multiple statements surrounded by '{...}' and optionally + 56 # prefixed with a label name and ':' + 57 # - { + 58 # ... + 59 # } + 60 # - foo: { + 61 # ... + 62 # } + 63 # + 64 # - variable definitions on the stack. E.g.: + 65 # - var foo: int + 66 # - var bar: (array int 3) + 67 # There's no initializer; variables are automatically initialized. + 68 # The type of a local variable is either word-length (4 bytes) or starts with 'ref'. + 69 # + 70 # - variables definitions in a register. E.g.: + 71 # - var foo/eax: int <- add bar 1 + 72 # The initializer is mandatory and must be a valid instruction that writes + 73 # a single output to the right register. In practice registers will + 74 # usually be either initialized by primitives or copied from eax. + 75 # - var eax: int <- foo bar quux + 76 # var floo/ecx: int <- copy eax + 77 # + 78 # Still todo: + 79 # global variables + 80 # heap allocations (planned name: 'handle') + 81 # user-defined types: 'type' for structs, 'choice' for unions + 82 # short-lived 'address' type for efficiently writing inside nested structs + 83 # + 84 # We don't have 'handle' types yet, but we try to distinguish 'ref', 'handle' + 85 # and 'address' in comments. Their definitions are in layer 50, but really you + 86 # can ignore the distinctions on a first reading of this program. + 87 # + 88 # Formal types: + 89 # A program is a linked list of functions + 90 # A function contains: + 91 # name: (handle array byte) + 92 # inouts: linked list of vars <-- 'inouts' is more precise than 'inputs' + 93 # data: (handle var) + 94 # next: (handle list) + 95 # outputs: linked list of vars + 96 # data: (handle var) + 97 # next: (handle list) + 98 # body: (handle block) + 99 # A var-type contains: + 100 # name: (handle array byte) + 101 # type: (handle tree type-id) + 102 # + 103 # A statement can be: + 104 # tag 0: a block + 105 # tag 1: a simple statement (stmt1) + 106 # tag 2: a variable defined on the stack + 107 # tag 3: a variable defined in a register + 108 # + 109 # A block contains: + 110 # tag: 0 + 111 # statements: (handle list statement) + 112 # name: (handle array byte) -- starting with '$' + 113 # + 114 # A regular statement contains: + 115 # tag: 1 + 116 # operation: (handle array byte) + 117 # inouts: (handle list operand) + 118 # outputs: (handle list var) + 119 # + 120 # A variable defined on the stack contains: + 121 # tag: 2 + 122 # name: (handle array byte) + 123 # type: (handle tree type-id) + 124 # + 125 # A variable defined in a register contains: + 126 # tag: 3 + 127 # name: (handle array byte) + 128 # type: (handle tree type-id) + 129 # reg: (handle array byte) + 130 + 131 # == Translation: managing the stack + 132 # Now that we know what the language looks like in the large, let's think + 133 # about how translation happens from the bottom up. One crucial piece of the + 134 # puzzle is how Mu will clean up variables defined on the stack for you. + 135 # + 136 # Assume that we maintain a 'functions' list while parsing source code. And a + 137 # 'primitives' list is a global constant. Both these contain enough information + 138 # to perform type-checking on function calls or primitive statements, respectively. + 139 # + 140 # Defining variables pushes them on a stack with the current block depth and + 141 # enough information about their location (stack offset or register). + 142 # Starting a block increments the current block id. + 143 # Each statement now has enough information to emit code for it. + 144 # Ending a block is where the magic happens: + 145 # pop all variables at the current block depth + 146 # emit code to restore all register variables introduced at the current depth + 147 # emit code to clean up all stack variables at the current depth (just increment esp) + 148 # decrement the current block depth + 149 # + 150 # Formal types: + 151 # live-vars: stack of vars + 152 # var: + 153 # name: (handle array byte) + 154 # type: (handle tree type-id) + 155 # block: int + 156 # stack-offset: int (added to ebp) + 157 # register: (handle array byte) + 158 # either usual register names + 159 # or '*' to indicate any register + 160 # At most one of stack-offset or register-index must be non-zero. + 161 # A register of '*' designates a variable _template_. Only legal in formal + 162 # parameters for primitives. + 163 + 164 # == Translating a single function call + 165 # This one's easy. Assuming we've already checked things, we just drop the + 166 # outputs (which use hard-coded registers) and emit inputs in a standard format. + 167 # + 168 # out1, out2, out3, ... <- name inout1, inout2, inout3, ... + 169 # => + 170 # (subx-name inout1 inout2 inout3) + 171 # + 172 # Formal types: + 173 # functions: linked list of info + 174 # name: (handle array byte) + 175 # inouts: linked list of vars + 176 # outputs: linked list of vars + 177 # body: block (singleton linked list) + 178 # subx-name: (handle array byte) + 179 + 180 # == Translating a single primitive instruction + 181 # A second crucial piece of the puzzle is how Mu converts fairly regular + 182 # primitives with their uniform syntax to SubX instructions with their gnarly + 183 # x86 details. + 184 # + 185 # Mu instructions have inputs and outputs. Primitives can have up to 2 of + 186 # them. + 187 # SubX instructions have rm32 and r32 operands. + 188 # The translation between them covers almost all the possibilities. + 189 # Instructions with 1 inout may turn into ones with 1 rm32 + 190 # (e.g. incrementing a var on the stack) + 191 # Instructions with 1 output may turn into ones with 1 rm32 + 192 # (e.g. incrementing a var in a register) + 193 # 1 inout and 1 output may turn into 1 rm32 and 1 r32 + 194 # (e.g. adding a var to a reg) + 195 # 2 inouts may turn into 1 rm32 and 1 r32 + 196 # (e.g. adding a reg to a var) + 197 # 1 inout and 1 literal may turn into 1 rm32 and 1 imm32 + 198 # (e.g. adding a constant to a var) + 199 # 1 output and 1 literal may turn into 1 rm32 and 1 imm32 + 200 # (e.g. adding a constant to a reg) + 201 # 2 outputs to hardcoded registers and 1 inout may turn into 1 rm32 + 202 # (special-case: divide edx:eax by a var or reg) + 203 # Observations: + 204 # We always emit rm32. It may be the first inout or the first output. + 205 # We may emit r32 or imm32 or neither. + 206 # When we emit r32 it may come from first inout or second inout or first output. + 207 # + 208 # Accordingly, the formal data structure for a primitive looks like this: + 209 # primitives: linked list of info + 210 # name: (handle array byte) + 211 # mu-inouts: linked list of vars to check + 212 # mu-outputs: linked list of vars to check; at most a singleton + 213 # subx-name: (handle array byte) + 214 # subx-rm32: enum arg-location + 215 # subx-r32: enum arg-location + 216 # subx-imm32: enum arg-location + 217 # subx-disp32: enum arg-location + 218 # output-is-write-only: boolean + 219 # arg-location: enum + 220 # 0 means none + 221 # 1 means first inout + 222 # 2 means second inout + 223 # 3 means first output + 224 + 225 # == Translating a block + 226 # Emit block name if necessary + 227 # Emit '{' + 228 # When you encounter a statement, emit it as above + 229 # When you encounter a variable declaration + 230 # emit any code needed for it (bzeros) + 231 # push it on the var stack + 232 # update register dict if necessary + 233 # When you encounter '}' + 234 # While popping variables off the var stack until block id changes + 235 # Emit code needed to clean up the stack + 236 # either increment esp + 237 # or pop into appropriate register + 238 + 239 # The rest is straightforward. 240 - 241 # The rest is straightforward. + 241 == data 242 - 243 == data - 244 - 245 Program: # (handle function) - 246 0/imm32 - 247 - 248 Function-name: - 249 0/imm32 - 250 Function-subx-name: - 251 4/imm32 - 252 Function-inouts: # (handle list var) - 253 8/imm32 - 254 Function-outputs: # (handle list var) - 255 0xc/imm32 - 256 Function-body: # (handle block) - 257 0x10/imm32 - 258 Function-next: # (handle function) - 259 0x14/imm32 - 260 Function-size: # (addr int) - 261 0x18/imm32/24 - 262 - 263 Primitive-name: - 264 0/imm32 - 265 Primitive-inouts: # (handle list var) - 266 4/imm32 - 267 Primitive-outputs: # (handle list var) - 268 8/imm32 - 269 Primitive-subx-name: # (handle array byte) - 270 0xc/imm32 - 271 Primitive-subx-rm32: # enum arg-location - 272 0x10/imm32 - 273 Primitive-subx-r32: # enum arg-location - 274 0x14/imm32 - 275 Primitive-subx-imm32: # enum arg-location - 276 0x18/imm32 - 277 Primitive-subx-disp32: # enum arg-location -- only for branches - 278 0x1c/imm32 - 279 Primitive-output-is-write-only: # boolean - 280 0x20/imm32 - 281 Primitive-next: # (handle function) - 282 0x24/imm32 - 283 Primitive-size: # (addr int) - 284 0x28/imm32/36 - 285 - 286 Stmt-tag: - 287 0/imm32 - 288 - 289 Block-statements: # (handle list statement) - 290 4/imm32 - 291 Block-var: # (handle var) - 292 8/imm32 - 293 - 294 Stmt1-operation: # (handle array byte) - 295 4/imm32 - 296 Stmt1-inouts: # (handle stmt-var) - 297 8/imm32 - 298 Stmt1-outputs: # (handle stmt-var) - 299 0xc/imm32 - 300 - 301 Vardef-var: # (handle var) - 302 4/imm32 - 303 - 304 Regvardef-operation: # (handle array byte) - 305 4/imm32 - 306 Regvardef-inouts: # (handle stmt-var) - 307 8/imm32 - 308 Regvardef-outputs: # (handle stmt-var) # will have exactly one element - 309 0xc/imm32 - 310 - 311 Stmt-size: # (addr int) - 312 0x10/imm32 - 313 - 314 Var-name: - 315 0/imm32 - 316 Var-type: - 317 4/imm32 - 318 Var-block-depth: - 319 8/imm32 - 320 Var-stack-offset: - 321 0xc/imm32 - 322 Var-register: - 323 0x10/imm32 - 324 Var-size: # (addr int) - 325 0x14/imm32 - 326 - 327 Any-register: # wildcard - 328 # size - 329 1/imm32 - 330 # data - 331 2a/asterisk - 332 - 333 List-value: - 334 0/imm32 - 335 List-next: - 336 4/imm32 - 337 List-size: # (addr int) - 338 8/imm32 - 339 - 340 # A stmt-var is like a list of vars with call-site specific metadata - 341 Stmt-var-value: # (handle var) - 342 0/imm32 - 343 Stmt-var-next: # (handle stmt-var) - 344 4/imm32 - 345 Stmt-var-is-deref: # boolean - 346 8/imm32 - 347 Stmt-var-size: # (addr int) - 348 0xc/imm32 - 349 - 350 # Types are expressed as trees (s-expressions) of type-ids (ints). - 351 # However, there's no need for singletons, so we can assume (int) == int - 352 # - if x->right == nil, x is an atom - 353 # - x->left contains either a pointer to a pair, or an atomic type-id directly. - 354 # type ids will be less than 0x10000 (MAX_TYPE_ID). - 355 - 356 Tree-left: # either type-id or (addr tree type-id) - 357 0/imm32 - 358 Tree-right: # (addr tree type-id) - 359 4/imm32 - 360 Tree-size: # (addr int) - 361 8/imm32 - 362 - 363 Max-type-id: - 364 0x10000/imm32 + 243 Program: # (handle function) + 244 0/imm32 + 245 + 246 Function-name: + 247 0/imm32 + 248 Function-subx-name: + 249 4/imm32 + 250 Function-inouts: # (handle list var) + 251 8/imm32 + 252 Function-outputs: # (handle list var) + 253 0xc/imm32 + 254 Function-body: # (handle block) + 255 0x10/imm32 + 256 Function-next: # (handle function) + 257 0x14/imm32 + 258 Function-size: # (addr int) + 259 0x18/imm32/24 + 260 + 261 Primitive-name: + 262 0/imm32 + 263 Primitive-inouts: # (handle list var) + 264 4/imm32 + 265 Primitive-outputs: # (handle list var) + 266 8/imm32 + 267 Primitive-subx-name: # (handle array byte) + 268 0xc/imm32 + 269 Primitive-subx-rm32: # enum arg-location + 270 0x10/imm32 + 271 Primitive-subx-r32: # enum arg-location + 272 0x14/imm32 + 273 Primitive-subx-imm32: # enum arg-location + 274 0x18/imm32 + 275 Primitive-subx-disp32: # enum arg-location -- only for branches + 276 0x1c/imm32 + 277 Primitive-output-is-write-only: # boolean + 278 0x20/imm32 + 279 Primitive-next: # (handle function) + 280 0x24/imm32 + 281 Primitive-size: # (addr int) + 282 0x28/imm32/36 + 283 + 284 Stmt-tag: + 285 0/imm32 + 286 + 287 Block-statements: # (handle list statement) + 288 4/imm32 + 289 Block-var: # (handle var) + 290 8/imm32 + 291 + 292 Stmt1-operation: # (handle array byte) + 293 4/imm32 + 294 Stmt1-inouts: # (handle stmt-var) + 295 8/imm32 + 296 Stmt1-outputs: # (handle stmt-var) + 297 0xc/imm32 + 298 + 299 Vardef-var: # (handle var) + 300 4/imm32 + 301 + 302 Regvardef-operation: # (handle array byte) + 303 4/imm32 + 304 Regvardef-inouts: # (handle stmt-var) + 305 8/imm32 + 306 Regvardef-outputs: # (handle stmt-var) # will have exactly one element + 307 0xc/imm32 + 308 + 309 Stmt-size: # (addr int) + 310 0x10/imm32 + 311 + 312 Var-name: + 313 0/imm32 + 314 Var-type: + 315 4/imm32 + 316 Var-block-depth: + 317 8/imm32 + 318 Var-stack-offset: + 319 0xc/imm32 + 320 Var-register: + 321 0x10/imm32 + 322 Var-size: # (addr int) + 323 0x14/imm32 + 324 + 325 Any-register: # wildcard + 326 # size + 327 1/imm32 + 328 # data + 329 2a/asterisk + 330 + 331 List-value: + 332 0/imm32 + 333 List-next: + 334 4/imm32 + 335 List-size: # (addr int) + 336 8/imm32 + 337 + 338 # A stmt-var is like a list of vars with call-site specific metadata + 339 Stmt-var-value: # (handle var) + 340 0/imm32 + 341 Stmt-var-next: # (handle stmt-var) + 342 4/imm32 + 343 Stmt-var-is-deref: # boolean + 344 8/imm32 + 345 Stmt-var-size: # (addr int) + 346 0xc/imm32 + 347 + 348 # Types are expressed as trees (s-expressions) of type-ids (ints). + 349 # However, there's no need for singletons, so we can assume (int) == int + 350 # - if x->right == nil, x is an atom + 351 # - x->left contains either a pointer to a pair, or an atomic type-id directly. + 352 # type ids will be less than 0x10000 (MAX_TYPE_ID). + 353 + 354 Tree-left: # either type-id or (addr tree type-id) + 355 0/imm32 + 356 Tree-right: # (addr tree type-id) + 357 4/imm32 + 358 Tree-size: # (addr int) + 359 8/imm32 + 360 + 361 Max-type-id: + 362 0x10000/imm32 + 363 + 364 == code 365 - 366 == code - 367 - 368 Entry: - 369 # . prologue - 370 89/<- %ebp 4/r32/esp - 371 (new-segment *Heap-size Heap) - 372 # if (argv[1] == "test') run-tests() - 373 { - 374 # if (argc <= 1) break - 375 81 7/subop/compare *ebp 1/imm32 - 376 7e/jump-if-<= break/disp8 - 377 # if (argv[1] != "test") break - 378 (kernel-string-equal? *(ebp+8) "test") # => eax - 379 3d/compare-eax-and 0/imm32/false - 380 74/jump-if-= break/disp8 - 381 # - 382 (run-tests) - 383 # syscall(exit, *Num-test-failures) - 384 8b/-> *Num-test-failures 3/r32/ebx - 385 eb/jump $mu-main:end/disp8 - 386 } - 387 # otherwise convert Stdin - 388 (convert-mu Stdin Stdout) - 389 (flush Stdout) - 390 # syscall(exit, 0) - 391 bb/copy-to-ebx 0/imm32 - 392 $mu-main:end: - 393 b8/copy-to-eax 1/imm32/exit - 394 cd/syscall 0x80/imm8 - 395 - 396 convert-mu: # in: (addr buffered-file), out: (addr buffered-file) - 397 # . prologue - 398 55/push-ebp - 399 89/<- %ebp 4/r32/esp - 400 # - 401 (parse-mu *(ebp+8)) - 402 (check-mu-types) - 403 (emit-subx *(ebp+0xc)) - 404 $convert-mu:end: - 405 # . epilogue - 406 89/<- %esp 5/r32/ebp - 407 5d/pop-to-ebp - 408 c3/return - 409 - 410 test-convert-empty-input: - 411 # empty input => empty output - 412 # . prologue - 413 55/push-ebp - 414 89/<- %ebp 4/r32/esp - 415 # setup - 416 (clear-stream _test-input-stream) - 417 (clear-stream $_test-input-buffered-file->buffer) - 418 (clear-stream _test-output-stream) - 419 (clear-stream $_test-output-buffered-file->buffer) - 420 # - 421 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 422 (flush _test-output-buffered-file) - 423 (check-stream-equal _test-output-stream "" "F - test-convert-empty-input") - 424 # . epilogue - 425 89/<- %esp 5/r32/ebp - 426 5d/pop-to-ebp - 427 c3/return - 428 - 429 test-convert-function-skeleton: - 430 # . prologue - 431 55/push-ebp - 432 89/<- %ebp 4/r32/esp - 433 # setup - 434 (clear-stream _test-input-stream) - 435 (clear-stream $_test-input-buffered-file->buffer) - 436 (clear-stream _test-output-stream) - 437 (clear-stream $_test-output-buffered-file->buffer) - 438 # - 439 (write _test-input-stream "fn foo {\n") - 440 (write _test-input-stream "}\n") - 441 # convert - 442 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 443 (flush _test-output-buffered-file) - 444 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 450 # check output - 451 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-skeleton/0") - 452 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-skeleton/1") - 453 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-skeleton/2") - 454 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-skeleton/3") - 455 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-skeleton/4") - 456 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-skeleton/5") - 457 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-skeleton/6") - 458 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-skeleton/7") - 459 # . epilogue - 460 89/<- %esp 5/r32/ebp - 461 5d/pop-to-ebp - 462 c3/return - 463 - 464 test-convert-multiple-function-skeletons: - 465 # . prologue - 466 55/push-ebp - 467 89/<- %ebp 4/r32/esp - 468 # setup - 469 (clear-stream _test-input-stream) - 470 (clear-stream $_test-input-buffered-file->buffer) - 471 (clear-stream _test-output-stream) - 472 (clear-stream $_test-output-buffered-file->buffer) - 473 # - 474 (write _test-input-stream "fn foo {\n") + 366 Entry: + 367 # . prologue + 368 89/<- %ebp 4/r32/esp + 369 (new-segment *Heap-size Heap) + 370 # if (argv[1] == "test') run-tests() + 371 { + 372 # if (argc <= 1) break + 373 81 7/subop/compare *ebp 1/imm32 + 374 7e/jump-if-<= break/disp8 + 375 # if (argv[1] != "test") break + 376 (kernel-string-equal? *(ebp+8) "test") # => eax + 377 3d/compare-eax-and 0/imm32/false + 378 74/jump-if-= break/disp8 + 379 # + 380 (run-tests) + 381 # syscall(exit, *Num-test-failures) + 382 8b/-> *Num-test-failures 3/r32/ebx + 383 eb/jump $mu-main:end/disp8 + 384 } + 385 # otherwise convert Stdin + 386 (convert-mu Stdin Stdout) + 387 (flush Stdout) + 388 # syscall(exit, 0) + 389 bb/copy-to-ebx 0/imm32 + 390 $mu-main:end: + 391 b8/copy-to-eax 1/imm32/exit + 392 cd/syscall 0x80/imm8 + 393 + 394 convert-mu: # in: (addr buffered-file), out: (addr buffered-file) + 395 # . prologue + 396 55/push-ebp + 397 89/<- %ebp 4/r32/esp + 398 # + 399 (parse-mu *(ebp+8)) + 400 (check-mu-types) + 401 (emit-subx *(ebp+0xc)) + 402 $convert-mu:end: + 403 # . epilogue + 404 89/<- %esp 5/r32/ebp + 405 5d/pop-to-ebp + 406 c3/return + 407 + 408 test-convert-empty-input: + 409 # empty input => empty output + 410 # . prologue + 411 55/push-ebp + 412 89/<- %ebp 4/r32/esp + 413 # setup + 414 (clear-stream _test-input-stream) + 415 (clear-stream $_test-input-buffered-file->buffer) + 416 (clear-stream _test-output-stream) + 417 (clear-stream $_test-output-buffered-file->buffer) + 418 # + 419 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 420 (flush _test-output-buffered-file) + 421 (check-stream-equal _test-output-stream "" "F - test-convert-empty-input") + 422 # . epilogue + 423 89/<- %esp 5/r32/ebp + 424 5d/pop-to-ebp + 425 c3/return + 426 + 427 test-convert-function-skeleton: + 428 # . prologue + 429 55/push-ebp + 430 89/<- %ebp 4/r32/esp + 431 # setup + 432 (clear-stream _test-input-stream) + 433 (clear-stream $_test-input-buffered-file->buffer) + 434 (clear-stream _test-output-stream) + 435 (clear-stream $_test-output-buffered-file->buffer) + 436 # + 437 (write _test-input-stream "fn foo {\n") + 438 (write _test-input-stream "}\n") + 439 # convert + 440 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 441 (flush _test-output-buffered-file) + 442 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- + 448 # check output + 449 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-skeleton/0") + 450 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-skeleton/1") + 451 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-skeleton/2") + 452 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-skeleton/3") + 453 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-skeleton/4") + 454 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-skeleton/5") + 455 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-skeleton/6") + 456 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-skeleton/7") + 457 # . epilogue + 458 89/<- %esp 5/r32/ebp + 459 5d/pop-to-ebp + 460 c3/return + 461 + 462 test-convert-multiple-function-skeletons: + 463 # . prologue + 464 55/push-ebp + 465 89/<- %ebp 4/r32/esp + 466 # setup + 467 (clear-stream _test-input-stream) + 468 (clear-stream $_test-input-buffered-file->buffer) + 469 (clear-stream _test-output-stream) + 470 (clear-stream $_test-output-buffered-file->buffer) + 471 # + 472 (write _test-input-stream "fn foo {\n") + 473 (write _test-input-stream "}\n") + 474 (write _test-input-stream "fn bar {\n") 475 (write _test-input-stream "}\n") - 476 (write _test-input-stream "fn bar {\n") - 477 (write _test-input-stream "}\n") - 478 # convert - 479 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 480 (flush _test-output-buffered-file) - 481 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 487 # check first function - 488 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-multiple-function-skeletons/0") - 489 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-multiple-function-skeletons/1") - 490 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-multiple-function-skeletons/2") - 491 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-multiple-function-skeletons/3") - 492 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-multiple-function-skeletons/4") - 493 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-multiple-function-skeletons/5") - 494 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-multiple-function-skeletons/6") - 495 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-multiple-function-skeletons/7") - 496 # check second function - 497 (check-next-stream-line-equal _test-output-stream "bar:" "F - test-convert-multiple-function-skeletons/10") - 498 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-multiple-function-skeletons/11") - 499 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-multiple-function-skeletons/12") - 500 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-multiple-function-skeletons/13") - 501 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-multiple-function-skeletons/14") - 502 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-multiple-function-skeletons/15") - 503 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-multiple-function-skeletons/16") - 504 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-multiple-function-skeletons/17") - 505 # . epilogue - 506 89/<- %esp 5/r32/ebp - 507 5d/pop-to-ebp - 508 c3/return - 509 - 510 test-convert-function-with-arg: - 511 # . prologue - 512 55/push-ebp - 513 89/<- %ebp 4/r32/esp - 514 # setup - 515 (clear-stream _test-input-stream) - 516 (clear-stream $_test-input-buffered-file->buffer) - 517 (clear-stream _test-output-stream) - 518 (clear-stream $_test-output-buffered-file->buffer) - 519 # - 520 (write _test-input-stream "fn foo n: int {\n") - 521 (write _test-input-stream "}\n") - 522 # convert - 523 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 524 (flush _test-output-buffered-file) - 525 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 531 # check output - 532 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-arg/0") - 533 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-arg/1") - 534 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-arg/2") - 535 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-arg/3") - 536 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-arg/4") - 537 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-arg/5") - 538 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-arg/6") - 539 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-arg/7") - 540 # . epilogue - 541 89/<- %esp 5/r32/ebp - 542 5d/pop-to-ebp - 543 c3/return - 544 - 545 test-convert-function-with-arg-and-body: - 546 # . prologue - 547 55/push-ebp - 548 89/<- %ebp 4/r32/esp - 549 # setup - 550 (clear-stream _test-input-stream) - 551 (clear-stream $_test-input-buffered-file->buffer) - 552 (clear-stream _test-output-stream) - 553 (clear-stream $_test-output-buffered-file->buffer) - 554 c7 0/subop/copy *Next-block-index 1/imm32 - 555 # - 556 (write _test-input-stream "fn foo n: int {\n") - 557 (write _test-input-stream " increment n\n") - 558 (write _test-input-stream "}\n") - 559 # convert - 560 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 561 (flush _test-output-buffered-file) - 562 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 568 # check output - 569 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-arg-and-body/0") - 570 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-arg-and-body/1") - 571 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-arg-and-body/2") - 572 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-arg-and-body/3") - 573 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-arg-and-body/4") - 574 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-arg-and-body/5") - 575 (check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *(ebp+0x00000008)" "F - test-convert-function-with-arg-and-body/6") - 576 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-arg-and-body/7") - 577 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-arg-and-body/8") - 578 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-arg-and-body/9") - 579 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-arg-and-body/10") - 580 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-arg-and-body/11") - 581 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-arg-and-body/12") - 582 # . epilogue - 583 89/<- %esp 5/r32/ebp - 584 5d/pop-to-ebp - 585 c3/return - 586 - 587 test-convert-function-distinguishes-args: - 588 # . prologue - 589 55/push-ebp - 590 89/<- %ebp 4/r32/esp - 591 # setup - 592 (clear-stream _test-input-stream) - 593 (clear-stream $_test-input-buffered-file->buffer) - 594 (clear-stream _test-output-stream) - 595 (clear-stream $_test-output-buffered-file->buffer) - 596 c7 0/subop/copy *Next-block-index 1/imm32 - 597 # - 598 (write _test-input-stream "fn foo a: int, b: int {\n") - 599 (write _test-input-stream " increment b\n") - 600 (write _test-input-stream "}\n") - 601 # convert - 602 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 603 (flush _test-output-buffered-file) - 604 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 610 # check output - 611 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-distinguishes-args/0") - 612 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-distinguishes-args/1") - 613 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-distinguishes-args/2") - 614 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-distinguishes-args/3") - 615 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-distinguishes-args/4") - 616 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-distinguishes-args/5") - 617 (check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *(ebp+0x0000000c)" "F - test-convert-function-distinguishes-args/6") - 618 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-distinguishes-args/7") - 619 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-distinguishes-args/8") - 620 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-distinguishes-args/9") - 621 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-distinguishes-args/10") - 622 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-distinguishes-args/11") - 623 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-distinguishes-args/12") - 624 # . epilogue - 625 89/<- %esp 5/r32/ebp - 626 5d/pop-to-ebp - 627 c3/return - 628 - 629 test-convert-function-returns-result: - 630 # . prologue - 631 55/push-ebp - 632 89/<- %ebp 4/r32/esp - 633 # setup - 634 (clear-stream _test-input-stream) - 635 (clear-stream $_test-input-buffered-file->buffer) - 636 (clear-stream _test-output-stream) - 637 (clear-stream $_test-output-buffered-file->buffer) - 638 c7 0/subop/copy *Next-block-index 1/imm32 - 639 # - 640 (write _test-input-stream "fn foo a: int, b: int -> result/eax: int {\n") - 641 (write _test-input-stream " result <- copy a\n") - 642 (write _test-input-stream " result <- increment\n") - 643 (write _test-input-stream "}\n") - 644 # convert - 645 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 646 (flush _test-output-buffered-file) - 647 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 653 # check output - 654 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-returns-result/0") - 655 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-returns-result/1") - 656 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-returns-result/2") - 657 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-returns-result/3") - 658 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-returns-result/4") - 659 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-returns-result/5") - 660 (check-next-stream-line-equal _test-output-stream " 8b/copy-from *(ebp+0x00000008) 0x00000000/r32" "F - test-convert-function-returns-result/6") - 661 (check-next-stream-line-equal _test-output-stream " 40/increment-eax" "F - test-convert-function-returns-result/7") - 662 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-returns-result/8") - 663 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-returns-result/9") - 664 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-returns-result/10") - 665 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-returns-result/11") - 666 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-returns-result/12") - 667 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-returns-result/13") - 668 # . epilogue - 669 89/<- %esp 5/r32/ebp - 670 5d/pop-to-ebp - 671 c3/return - 672 - 673 test-convert-function-literal-arg: - 674 # . prologue - 675 55/push-ebp - 676 89/<- %ebp 4/r32/esp - 677 # setup - 678 (clear-stream _test-input-stream) - 679 (clear-stream $_test-input-buffered-file->buffer) - 680 (clear-stream _test-output-stream) - 681 (clear-stream $_test-output-buffered-file->buffer) - 682 c7 0/subop/copy *Next-block-index 1/imm32 - 683 # - 684 (write _test-input-stream "fn foo a: int, b: int -> result/eax: int {\n") - 685 (write _test-input-stream " result <- copy a\n") - 686 (write _test-input-stream " result <- add 1\n") - 687 (write _test-input-stream "}\n") - 688 # convert - 689 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 690 (flush _test-output-buffered-file) - 691 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 697 # check output - 698 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-literal-arg/0") - 699 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-literal-arg/1") - 700 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-literal-arg/2") - 701 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-literal-arg/3") - 702 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-literal-arg/4") - 703 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-literal-arg/5") - 704 (check-next-stream-line-equal _test-output-stream " 8b/copy-from *(ebp+0x00000008) 0x00000000/r32" "F - test-convert-function-literal-arg/6") - 705 (check-next-stream-line-equal _test-output-stream " 05/add-to-eax 1/imm32" "F - test-convert-function-literal-arg/7") - 706 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-literal-arg/8") - 707 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-literal-arg/9") - 708 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-literal-arg/10") - 709 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-literal-arg/11") - 710 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-literal-arg/12") - 711 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-literal-arg/13") - 712 # . epilogue - 713 89/<- %esp 5/r32/ebp - 714 5d/pop-to-ebp - 715 c3/return - 716 - 717 test-convert-function-literal-arg-2: - 718 # . prologue - 719 55/push-ebp - 720 89/<- %ebp 4/r32/esp - 721 # setup - 722 (clear-stream _test-input-stream) - 723 (clear-stream $_test-input-buffered-file->buffer) - 724 (clear-stream _test-output-stream) - 725 (clear-stream $_test-output-buffered-file->buffer) - 726 c7 0/subop/copy *Next-block-index 1/imm32 - 727 # - 728 (write _test-input-stream "fn foo a: int, b: int -> result/ebx: int {\n") - 729 (write _test-input-stream " result <- copy a\n") - 730 (write _test-input-stream " result <- add 1\n") - 731 (write _test-input-stream "}\n") - 732 # convert - 733 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 734 (flush _test-output-buffered-file) - 735 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 741 # check output - 742 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-literal-arg-2/0") - 743 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-literal-arg-2/1") - 744 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-literal-arg-2/2") - 745 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-literal-arg-2/3") - 746 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-literal-arg-2/4") - 747 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-literal-arg-2/5") - 748 (check-next-stream-line-equal _test-output-stream " 8b/copy-from *(ebp+0x00000008) 0x00000003/r32" "F - test-convert-function-literal-arg-2/6") - 749 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %ebx 1/imm32" "F - test-convert-function-literal-arg-2/7") - 750 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-literal-arg-2/8") - 751 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-literal-arg-2/9") - 752 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-literal-arg-2/10") - 753 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-literal-arg-2/11") - 754 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-literal-arg-2/12") - 755 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-literal-arg-2/13") - 756 # . epilogue - 757 89/<- %esp 5/r32/ebp - 758 5d/pop-to-ebp - 759 c3/return - 760 - 761 test-convert-function-call-with-literal-arg: - 762 # . prologue - 763 55/push-ebp - 764 89/<- %ebp 4/r32/esp - 765 # setup - 766 (clear-stream _test-input-stream) - 767 (clear-stream $_test-input-buffered-file->buffer) - 768 (clear-stream _test-output-stream) - 769 (clear-stream $_test-output-buffered-file->buffer) - 770 c7 0/subop/copy *Next-block-index 1/imm32 - 771 # - 772 (write _test-input-stream "fn main -> result/ebx: int {\n") - 773 (write _test-input-stream " result <- do-add 3 4\n") - 774 (write _test-input-stream "}\n") - 775 (write _test-input-stream "fn do-add a: int, b: int -> result/ebx: int {\n") - 776 (write _test-input-stream " result <- copy a\n") - 777 (write _test-input-stream " result <- add b\n") - 778 (write _test-input-stream "}\n") - 779 # convert - 780 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 781 (flush _test-output-buffered-file) - 782 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 788 # check output - 789 (check-next-stream-line-equal _test-output-stream "main:" "F - test-convert-function-call-with-literal-arg/0") - 790 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-call-with-literal-arg/1") - 791 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-call-with-literal-arg/2") - 792 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-call-with-literal-arg/3") - 793 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-call-with-literal-arg/4") - 794 (check-next-stream-line-equal _test-output-stream "$main:0x00000001:loop:" "F - test-convert-function-call-with-literal-arg/5") - 795 (check-next-stream-line-equal _test-output-stream " (do-add 3 4)" "F - test-convert-function-call-with-literal-arg/6") - 796 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-call-with-literal-arg/7") - 797 (check-next-stream-line-equal _test-output-stream "$main:0x00000001:break:" "F - test-convert-function-call-with-literal-arg/8") - 798 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-call-with-literal-arg/9") - 799 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-call-with-literal-arg/10") - 800 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-call-with-literal-arg/11") - 801 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-call-with-literal-arg/12") - 802 (check-next-stream-line-equal _test-output-stream "do-add:" "F - test-convert-function-call-with-literal-arg/13") - 803 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-call-with-literal-arg/14") - 804 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-call-with-literal-arg/15") - 805 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-call-with-literal-arg/16") - 806 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-call-with-literal-arg/17") - 807 (check-next-stream-line-equal _test-output-stream "$do-add:0x00000002:loop:" "F - test-convert-function-call-with-literal-arg/18") - 808 (check-next-stream-line-equal _test-output-stream " 8b/copy-from *(ebp+0x00000008) 0x00000003/r32" "F - test-convert-function-call-with-literal-arg/19") - 809 (check-next-stream-line-equal _test-output-stream " 03/add *(ebp+0x0000000c) 0x00000003/r32" "F - test-convert-function-call-with-literal-arg/20") - 810 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-call-with-literal-arg/21") - 811 (check-next-stream-line-equal _test-output-stream "$do-add:0x00000002:break:" "F - test-convert-function-call-with-literal-arg/22") - 812 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-call-with-literal-arg/23") - 813 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-call-with-literal-arg/24") - 814 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-call-with-literal-arg/25") - 815 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-call-with-literal-arg/26") - 816 # . epilogue - 817 89/<- %esp 5/r32/ebp - 818 5d/pop-to-ebp - 819 c3/return - 820 - 821 test-convert-function-with-local-var-in-mem: - 822 # . prologue - 823 55/push-ebp - 824 89/<- %ebp 4/r32/esp - 825 # setup - 826 (clear-stream _test-input-stream) - 827 (clear-stream $_test-input-buffered-file->buffer) - 828 (clear-stream _test-output-stream) - 829 (clear-stream $_test-output-buffered-file->buffer) - 830 c7 0/subop/copy *Next-block-index 1/imm32 - 831 # - 832 (write _test-input-stream "fn foo {\n") - 833 (write _test-input-stream " var x: int\n") - 834 (write _test-input-stream " increment x\n") - 835 (write _test-input-stream "}\n") - 836 # convert - 837 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 838 (flush _test-output-buffered-file) - 839 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 845 # check output - 846 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-local-var-in-mem/0") - 847 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-local-var-in-mem/1") - 848 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-local-var-in-mem/2") - 849 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-local-var-in-mem/3") - 850 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-local-var-in-mem/4") - 851 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-local-var-in-mem/5") - 852 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-local-var-in-mem/6") - 853 (check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *(ebp+0xfffffffc)" "F - test-convert-function-with-local-var-in-mem/7") - 854 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-local-var-in-mem/8") - 855 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-local-var-in-mem/9") - 856 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-local-var-in-mem/10") - 857 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-local-var-in-mem/11") - 858 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-local-var-in-mem/12") - 859 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-local-var-in-mem/13") - 860 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-local-var-in-mem/14") - 861 # . epilogue - 862 89/<- %esp 5/r32/ebp - 863 5d/pop-to-ebp - 864 c3/return - 865 - 866 test-convert-function-with-local-var-in-reg: - 867 # . prologue - 868 55/push-ebp - 869 89/<- %ebp 4/r32/esp - 870 # setup - 871 (clear-stream _test-input-stream) - 872 (clear-stream $_test-input-buffered-file->buffer) - 873 (clear-stream _test-output-stream) - 874 (clear-stream $_test-output-buffered-file->buffer) - 875 c7 0/subop/copy *Next-block-index 1/imm32 - 876 # - 877 (write _test-input-stream "fn foo {\n") - 878 (write _test-input-stream " var x/ecx: int <- copy 3\n") - 879 (write _test-input-stream " x <- increment\n") - 880 (write _test-input-stream "}\n") - 881 # convert - 882 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 883 (flush _test-output-buffered-file) - 884 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 890 # check output - 891 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-local-var-in-reg/0") - 892 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-local-var-in-reg/1") - 893 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-local-var-in-reg/2") - 894 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-local-var-in-reg/3") - 895 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-local-var-in-reg/4") - 896 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-local-var-in-reg/5") - 897 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-convert-function-with-local-var-in-reg/6") - 898 (check-next-stream-line-equal _test-output-stream " b9/copy-to-ecx 3/imm32" "F - test-convert-function-with-local-var-in-reg/7") - 899 (check-next-stream-line-equal _test-output-stream " 41/increment-ecx" "F - test-convert-function-with-local-var-in-reg/8") - 900 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-convert-function-with-local-var-in-reg/9") - 901 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-local-var-in-reg/10") - 902 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-local-var-in-reg/11") - 903 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-local-var-in-reg/12") - 904 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-local-var-in-reg/13") - 905 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-local-var-in-reg/14") - 906 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-local-var-in-reg/15") - 907 # . epilogue - 908 89/<- %esp 5/r32/ebp - 909 5d/pop-to-ebp - 910 c3/return - 911 - 912 test-convert-function-with-local-var-dereferenced: - 913 # . prologue - 914 55/push-ebp - 915 89/<- %ebp 4/r32/esp - 916 # setup - 917 (clear-stream _test-input-stream) - 918 (clear-stream $_test-input-buffered-file->buffer) - 919 (clear-stream _test-output-stream) - 920 (clear-stream $_test-output-buffered-file->buffer) - 921 c7 0/subop/copy *Next-block-index 1/imm32 - 922 # - 923 (write _test-input-stream "fn foo {\n") - 924 (write _test-input-stream " var x/ecx: (addr int) <- copy 0\n") - 925 (write _test-input-stream " increment *x\n") - 926 (write _test-input-stream "}\n") - 927 # convert - 928 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 929 (flush _test-output-buffered-file) - 930 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 936 # check output - 937 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-local-var-dereferenced/0") - 938 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-local-var-dereferenced/1") - 939 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-local-var-dereferenced/2") - 940 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-local-var-dereferenced/3") - 941 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-local-var-dereferenced/4") - 942 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-local-var-dereferenced/5") - 943 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-convert-function-with-local-var-dereferenced/6") - 944 (check-next-stream-line-equal _test-output-stream " b9/copy-to-ecx 0/imm32" "F - test-convert-function-with-local-var-dereferenced/7") - 945 (check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *ecx" "F - test-convert-function-with-local-var-dereferenced/8") - 946 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-convert-function-with-local-var-dereferenced/9") - 947 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-local-var-dereferenced/10") - 948 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-local-var-dereferenced/11") - 949 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-local-var-dereferenced/12") - 950 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-local-var-dereferenced/13") - 951 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-local-var-dereferenced/14") - 952 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-local-var-dereferenced/15") - 953 # . epilogue - 954 89/<- %esp 5/r32/ebp - 955 5d/pop-to-ebp - 956 c3/return - 957 - 958 test-convert-function-with-local-var-in-block: - 959 # . prologue - 960 55/push-ebp - 961 89/<- %ebp 4/r32/esp - 962 # setup - 963 (clear-stream _test-input-stream) - 964 (clear-stream $_test-input-buffered-file->buffer) - 965 (clear-stream _test-output-stream) - 966 (clear-stream $_test-output-buffered-file->buffer) - 967 c7 0/subop/copy *Next-block-index 1/imm32 - 968 # - 969 (write _test-input-stream "fn foo {\n") - 970 (write _test-input-stream " {\n") - 971 (write _test-input-stream " var x: int\n") - 972 (write _test-input-stream " increment x\n") - 973 (write _test-input-stream " }\n") - 974 (write _test-input-stream "}\n") - 975 # convert - 976 (convert-mu _test-input-buffered-file _test-output-buffered-file) - 977 (flush _test-output-buffered-file) - 978 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- - 984 # check output - 985 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-local-var-in-block/0") - 986 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-local-var-in-block/1") - 987 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-local-var-in-block/2") - 988 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-local-var-in-block/3") - 989 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-local-var-in-block/4") - 990 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-local-var-in-block/5") - 991 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-local-var-in-block/6") - 992 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:" "F - test-convert-function-with-local-var-in-block/7") - 993 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-local-var-in-block/8") - 994 (check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *(ebp+0xfffffffc)" "F - test-convert-function-with-local-var-in-block/9") - 995 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-local-var-in-block/10") - 996 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-local-var-in-block/11") - 997 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:" "F - test-convert-function-with-local-var-in-block/12") - 998 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-local-var-in-block/13") - 999 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-local-var-in-block/14") -1000 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-local-var-in-block/15") -1001 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-local-var-in-block/16") -1002 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-local-var-in-block/17") -1003 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-local-var-in-block/18") -1004 # . epilogue -1005 89/<- %esp 5/r32/ebp -1006 5d/pop-to-ebp -1007 c3/return -1008 -1009 test-convert-function-with-local-var-in-named-block: -1010 # . prologue -1011 55/push-ebp -1012 89/<- %ebp 4/r32/esp -1013 # setup -1014 (clear-stream _test-input-stream) -1015 (clear-stream $_test-input-buffered-file->buffer) -1016 (clear-stream _test-output-stream) -1017 (clear-stream $_test-output-buffered-file->buffer) -1018 c7 0/subop/copy *Next-block-index 1/imm32 -1019 # -1020 (write _test-input-stream "fn foo {\n") -1021 (write _test-input-stream " $bar: {\n") -1022 (write _test-input-stream " var x: int\n") -1023 (write _test-input-stream " increment x\n") -1024 (write _test-input-stream " }\n") -1025 (write _test-input-stream "}\n") -1026 # convert -1027 (convert-mu _test-input-buffered-file _test-output-buffered-file) -1028 (flush _test-output-buffered-file) -1029 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -1035 # check output -1036 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-local-var-in-named-block/0") -1037 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-local-var-in-named-block/1") -1038 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-local-var-in-named-block/2") -1039 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-local-var-in-named-block/3") -1040 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-local-var-in-named-block/4") -1041 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-local-var-in-named-block/5") -1042 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-local-var-in-named-block/6") -1043 (check-next-stream-line-equal _test-output-stream "$bar:loop:" "F - test-convert-function-with-local-var-in-named-block/7") -1044 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-local-var-in-named-block/8") -1045 (check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *(ebp+0xfffffffc)" "F - test-convert-function-with-local-var-in-named-block/9") -1046 (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/10") -1047 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-local-var-in-named-block/11") -1048 (check-next-stream-line-equal _test-output-stream "$bar:break:" "F - test-convert-function-with-local-var-in-named-block/12") -1049 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-local-var-in-named-block/13") -1050 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-local-var-in-named-block/14") -1051 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-local-var-in-named-block/15") -1052 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-local-var-in-named-block/16") -1053 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-local-var-in-named-block/17") -1054 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-local-var-in-named-block/18") -1055 # . epilogue -1056 89/<- %esp 5/r32/ebp -1057 5d/pop-to-ebp -1058 c3/return -1059 -1060 test-convert-function-with-branches-in-block: -1061 # . prologue -1062 55/push-ebp -1063 89/<- %ebp 4/r32/esp -1064 # setup -1065 (clear-stream _test-input-stream) -1066 (clear-stream $_test-input-buffered-file->buffer) -1067 (clear-stream _test-output-stream) -1068 (clear-stream $_test-output-buffered-file->buffer) -1069 c7 0/subop/copy *Next-block-index 1/imm32 -1070 # -1071 (write _test-input-stream "fn foo x: int {\n") -1072 (write _test-input-stream " {\n") -1073 (write _test-input-stream " break-if->=\n") -1074 (write _test-input-stream " loop-if-addr<\n") -1075 (write _test-input-stream " increment x\n") -1076 (write _test-input-stream " loop\n") -1077 (write _test-input-stream " }\n") -1078 (write _test-input-stream "}\n") -1079 # convert -1080 (convert-mu _test-input-buffered-file _test-output-buffered-file) -1081 (flush _test-output-buffered-file) -1082 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -1088 # check output -1089 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-branches-in-block/0") -1090 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-branches-in-block/1") -1091 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-branches-in-block/2") -1092 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-branches-in-block/3") -1093 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-branches-in-block/4") -1094 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-branches-in-block/5") -1095 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-branches-in-block/6") -1096 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:" "F - test-convert-function-with-branches-in-block/7") -1097 (check-next-stream-line-equal _test-output-stream " 0f 8d/jump-if->= break/disp32" "F - test-convert-function-with-branches-in-block/8") -1098 (check-next-stream-line-equal _test-output-stream " 0f 82/jump-if-addr< loop/disp32" "F - test-convert-function-with-branches-in-block/9") -1099 (check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *(ebp+0x00000008)" "F - test-convert-function-with-branches-in-block/10") -1100 (check-next-stream-line-equal _test-output-stream " e9/jump loop/disp32" "F - test-convert-function-with-branches-in-block/11") -1101 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-branches-in-block/12") -1102 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:" "F - test-convert-function-with-branches-in-block/13") -1103 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-branches-in-block/14") -1104 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-branches-in-block/15") -1105 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-branches-in-block/16") -1106 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-branches-in-block/17") -1107 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-branches-in-block/18") -1108 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-branches-in-block/19") -1109 # . epilogue -1110 89/<- %esp 5/r32/ebp -1111 5d/pop-to-ebp -1112 c3/return -1113 -1114 test-convert-function-with-branches-in-named-block: -1115 # . prologue -1116 55/push-ebp -1117 89/<- %ebp 4/r32/esp -1118 # setup -1119 (clear-stream _test-input-stream) -1120 (clear-stream $_test-input-buffered-file->buffer) -1121 (clear-stream _test-output-stream) -1122 (clear-stream $_test-output-buffered-file->buffer) -1123 c7 0/subop/copy *Next-block-index 1/imm32 -1124 # -1125 (write _test-input-stream "fn foo x: int {\n") -1126 (write _test-input-stream " $bar: {\n") -1127 (write _test-input-stream " break-if->= $bar\n") -1128 (write _test-input-stream " loop-if-addr< $bar\n") -1129 (write _test-input-stream " increment x\n") -1130 (write _test-input-stream " loop\n") -1131 (write _test-input-stream " }\n") -1132 (write _test-input-stream "}\n") -1133 # convert -1134 (convert-mu _test-input-buffered-file _test-output-buffered-file) -1135 (flush _test-output-buffered-file) -1136 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -1142 # check output -1143 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-branches-in-named-block/0") -1144 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-branches-in-named-block/1") -1145 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-branches-in-named-block/2") -1146 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-branches-in-named-block/3") -1147 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-branches-in-named-block/4") -1148 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-branches-in-named-block/5") -1149 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-branches-in-named-block/6") -1150 (check-next-stream-line-equal _test-output-stream "$bar:loop:" "F - test-convert-function-with-branches-in-named-block/7") -1151 (check-next-stream-line-equal _test-output-stream " 0f 8d/jump-if->= $bar:break/disp32" "F - test-convert-function-with-branches-in-named-block/8") -1152 (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/9") -1153 (check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *(ebp+0x00000008)" "F - test-convert-function-with-branches-in-named-block/10") -1154 (check-next-stream-line-equal _test-output-stream " e9/jump loop/disp32" "F - test-convert-function-with-branches-in-named-block/11") -1155 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-branches-in-named-block/12") -1156 (check-next-stream-line-equal _test-output-stream "$bar:break:" "F - test-convert-function-with-branches-in-named-block/13") -1157 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-branches-in-named-block/14") -1158 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-branches-in-named-block/15") -1159 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-branches-in-named-block/16") -1160 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-branches-in-named-block/17") -1161 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-branches-in-named-block/18") -1162 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-branches-in-named-block/19") -1163 # . epilogue -1164 89/<- %esp 5/r32/ebp -1165 5d/pop-to-ebp -1166 c3/return -1167 -1168 test-convert-function-with-var-in-nested-block: -1169 # . prologue -1170 55/push-ebp -1171 89/<- %ebp 4/r32/esp -1172 # setup -1173 (clear-stream _test-input-stream) -1174 (clear-stream $_test-input-buffered-file->buffer) -1175 (clear-stream _test-output-stream) -1176 (clear-stream $_test-output-buffered-file->buffer) -1177 c7 0/subop/copy *Next-block-index 1/imm32 -1178 # -1179 (write _test-input-stream "fn foo x: int {\n") -1180 (write _test-input-stream " {\n") -1181 (write _test-input-stream " {\n") -1182 (write _test-input-stream " var x: int\n") -1183 (write _test-input-stream " increment x\n") -1184 (write _test-input-stream " }\n") -1185 (write _test-input-stream " }\n") -1186 (write _test-input-stream "}\n") -1187 # convert -1188 (convert-mu _test-input-buffered-file _test-output-buffered-file) -1189 (flush _test-output-buffered-file) -1190 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -1196 # check output -1197 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-var-in-nested-block/0") -1198 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-var-in-nested-block/1") -1199 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-var-in-nested-block/2") -1200 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-var-in-nested-block/3") -1201 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-var-in-nested-block/4") -1202 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-var-in-nested-block/5") -1203 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-var-in-nested-block/6") -1204 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:" "F - test-convert-function-with-var-in-nested-block/7") -1205 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-var-in-nested-block/8") -1206 (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:" "F - test-convert-function-with-var-in-nested-block/9") -1207 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-var-in-nested-block/10") -1208 (check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *(ebp+0xfffffffc)" "F - test-convert-function-with-var-in-nested-block/11") -1209 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-var-in-nested-block/12") -1210 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-var-in-nested-block/13") -1211 (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:" "F - test-convert-function-with-var-in-nested-block/14") -1212 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-var-in-nested-block/15") -1213 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:" "F - test-convert-function-with-var-in-nested-block/16") -1214 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-var-in-nested-block/17") -1215 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-var-in-nested-block/18") -1216 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-var-in-nested-block/19") -1217 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-var-in-nested-block/20") -1218 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-var-in-nested-block/21") -1219 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-var-in-nested-block/22") -1220 # . epilogue -1221 89/<- %esp 5/r32/ebp -1222 5d/pop-to-ebp -1223 c3/return -1224 -1225 test-convert-function-with-multiple-vars-in-nested-blocks: -1226 # . prologue -1227 55/push-ebp -1228 89/<- %ebp 4/r32/esp -1229 # setup -1230 (clear-stream _test-input-stream) -1231 (clear-stream $_test-input-buffered-file->buffer) -1232 (clear-stream _test-output-stream) -1233 (clear-stream $_test-output-buffered-file->buffer) -1234 c7 0/subop/copy *Next-block-index 1/imm32 -1235 # -1236 (write _test-input-stream "fn foo x: int {\n") -1237 (write _test-input-stream " {\n") -1238 (write _test-input-stream " var x/eax: int <- copy 0\n") -1239 (write _test-input-stream " {\n") -1240 (write _test-input-stream " var y: int\n") -1241 (write _test-input-stream " x <- add y\n") -1242 (write _test-input-stream " }\n") -1243 (write _test-input-stream " }\n") -1244 (write _test-input-stream "}\n") -1245 # convert -1246 (convert-mu _test-input-buffered-file _test-output-buffered-file) -1247 (flush _test-output-buffered-file) -1248 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -1254 # check output -1255 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-multiple-vars-in-nested-blocks/0") -1256 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-multiple-vars-in-nested-blocks/1") -1257 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-multiple-vars-in-nested-blocks/2") -1258 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-multiple-vars-in-nested-blocks/3") -1259 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-multiple-vars-in-nested-blocks/4") -1260 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-multiple-vars-in-nested-blocks/5") -1261 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-multiple-vars-in-nested-blocks/6") -1262 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:" "F - test-convert-function-with-multiple-vars-in-nested-blocks/7") -1263 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-function-with-multiple-vars-in-nested-blocks/8") -1264 (check-next-stream-line-equal _test-output-stream " b8/copy-to-eax 0/imm32" "F - test-convert-function-with-multiple-vars-in-nested-blocks/9") -1265 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-multiple-vars-in-nested-blocks/10") -1266 (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:" "F - test-convert-function-with-multiple-vars-in-nested-blocks/11") -1267 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-multiple-vars-in-nested-blocks/12") -1268 (check-next-stream-line-equal _test-output-stream " 03/add *(ebp+0xfffffff8) 0x00000000/r32" "F - test-convert-function-with-multiple-vars-in-nested-blocks/13") -1269 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-multiple-vars-in-nested-blocks/14") -1270 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-multiple-vars-in-nested-blocks/15") -1271 (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:" "F - test-convert-function-with-multiple-vars-in-nested-blocks/16") -1272 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-function-with-multiple-vars-in-nested-blocks/17") -1273 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-multiple-vars-in-nested-blocks/18") -1274 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:" "F - test-convert-function-with-multiple-vars-in-nested-blocks/19") -1275 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-multiple-vars-in-nested-blocks/20") -1276 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-multiple-vars-in-nested-blocks/21") -1277 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-multiple-vars-in-nested-blocks/22") -1278 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-multiple-vars-in-nested-blocks/23") -1279 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-multiple-vars-in-nested-blocks/24") -1280 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-multiple-vars-in-nested-blocks/25") -1281 # . epilogue -1282 89/<- %esp 5/r32/ebp -1283 5d/pop-to-ebp -1284 c3/return -1285 -1286 test-convert-function-with-branches-and-local-vars: -1287 # A conditional 'break' after a 'var' in a block is converted into a -1288 # nested block that performs all necessary cleanup before jumping. This -1289 # results in some ugly code duplication. -1290 # . prologue -1291 55/push-ebp -1292 89/<- %ebp 4/r32/esp -1293 # setup -1294 (clear-stream _test-input-stream) -1295 (clear-stream $_test-input-buffered-file->buffer) -1296 (clear-stream _test-output-stream) -1297 (clear-stream $_test-output-buffered-file->buffer) -1298 c7 0/subop/copy *Next-block-index 1/imm32 -1299 # -1300 (write _test-input-stream "fn foo {\n") -1301 (write _test-input-stream " {\n") -1302 (write _test-input-stream " var x: int\n") -1303 (write _test-input-stream " break-if->=\n") -1304 (write _test-input-stream " increment x\n") -1305 (write _test-input-stream " }\n") -1306 (write _test-input-stream "}\n") -1307 # convert -1308 (convert-mu _test-input-buffered-file _test-output-buffered-file) -1309 (flush _test-output-buffered-file) -1310 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -1316 # check output -1317 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-branches-and-local-vars/0") -1318 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-branches-and-local-vars/1") -1319 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-branches-and-local-vars/2") -1320 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-branches-and-local-vars/3") -1321 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-branches-and-local-vars/4") -1322 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-branches-and-local-vars/5") -1323 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-branches-and-local-vars/6") -1324 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:" "F - test-convert-function-with-branches-and-local-vars/7") -1325 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-branches-and-local-vars/8") -1326 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-branches-and-local-vars/9") -1327 (check-next-stream-line-equal _test-output-stream " 0f 8c/jump-if-< break/disp32" "F - test-convert-function-with-branches-and-local-vars/10") -1328 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-branches-and-local-vars/11") -1329 (check-next-stream-line-equal _test-output-stream " e9/jump $foo:0x00000002:break/disp32" "F - test-convert-function-with-branches-and-local-vars/12") -1330 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-branches-and-local-vars/13") -1331 (check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *(ebp+0xfffffffc)" "F - test-convert-function-with-branches-and-local-vars/14") -1332 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-branches-and-local-vars/15") -1333 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-branches-and-local-vars/16") -1334 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:" "F - test-convert-function-with-branches-and-local-vars/17") -1335 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-branches-and-local-vars/18") -1336 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-branches-and-local-vars/19") -1337 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-branches-and-local-vars/20") -1338 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-branches-and-local-vars/21") -1339 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-branches-and-local-vars/22") -1340 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-branches-and-local-vars/23") -1341 # . epilogue -1342 89/<- %esp 5/r32/ebp -1343 5d/pop-to-ebp -1344 c3/return -1345 -1346 test-convert-function-with-conditional-loops-and-local-vars: -1347 # A conditional 'loop' after a 'var' in a block is converted into a nested -1348 # block that performs all necessary cleanup before jumping. This results -1349 # in some ugly code duplication. -1350 # . prologue -1351 55/push-ebp -1352 89/<- %ebp 4/r32/esp -1353 # setup -1354 (clear-stream _test-input-stream) -1355 (clear-stream $_test-input-buffered-file->buffer) -1356 (clear-stream _test-output-stream) -1357 (clear-stream $_test-output-buffered-file->buffer) -1358 c7 0/subop/copy *Next-block-index 1/imm32 -1359 # -1360 (write _test-input-stream "fn foo {\n") -1361 (write _test-input-stream " {\n") -1362 (write _test-input-stream " var x: int\n") -1363 (write _test-input-stream " loop-if->=\n") -1364 (write _test-input-stream " increment x\n") -1365 (write _test-input-stream " }\n") -1366 (write _test-input-stream "}\n") -1367 # convert -1368 (convert-mu _test-input-buffered-file _test-output-buffered-file) -1369 (flush _test-output-buffered-file) -1370 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -1376 # check output -1377 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-conditional-loops-and-local-vars/0") -1378 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-conditional-loops-and-local-vars/1") -1379 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-conditional-loops-and-local-vars/2") -1380 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-conditional-loops-and-local-vars/3") -1381 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-conditional-loops-and-local-vars/4") -1382 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-conditional-loops-and-local-vars/5") -1383 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-conditional-loops-and-local-vars/6") -1384 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:" "F - test-convert-function-with-conditional-loops-and-local-vars/7") -1385 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-conditional-loops-and-local-vars/8") -1386 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-conditional-loops-and-local-vars/9") -1387 (check-next-stream-line-equal _test-output-stream " 0f 8c/jump-if-< break/disp32" "F - test-convert-function-with-conditional-loops-and-local-vars/10") -1388 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-conditional-loops-and-local-vars/11") -1389 (check-next-stream-line-equal _test-output-stream " e9/jump $foo:0x00000002:loop/disp32" "F - test-convert-function-with-conditional-loops-and-local-vars/12") -1390 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-conditional-loops-and-local-vars/13") -1391 (check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *(ebp+0xfffffffc)" "F - test-convert-function-with-conditional-loops-and-local-vars/14") -1392 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-conditional-loops-and-local-vars/15") -1393 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-conditional-loops-and-local-vars/16") -1394 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:" "F - test-convert-function-with-conditional-loops-and-local-vars/17") -1395 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-conditional-loops-and-local-vars/18") -1396 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-conditional-loops-and-local-vars/19") -1397 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-conditional-loops-and-local-vars/20") -1398 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-conditional-loops-and-local-vars/21") -1399 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-conditional-loops-and-local-vars/22") -1400 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-conditional-loops-and-local-vars/23") -1401 # . epilogue -1402 89/<- %esp 5/r32/ebp -1403 5d/pop-to-ebp -1404 c3/return -1405 -1406 test-convert-function-with-unconditional-loops-and-local-vars: -1407 # An unconditional 'loop' after a 'var' in a block is emitted _after_ the -1408 # regular block cleanup. Any instructions after 'loop' are dead and -1409 # therefore skipped. -1410 # . prologue -1411 55/push-ebp -1412 89/<- %ebp 4/r32/esp -1413 # setup -1414 (clear-stream _test-input-stream) -1415 (clear-stream $_test-input-buffered-file->buffer) -1416 (clear-stream _test-output-stream) -1417 (clear-stream $_test-output-buffered-file->buffer) -1418 c7 0/subop/copy *Next-block-index 1/imm32 -1419 # -1420 (write _test-input-stream "fn foo {\n") -1421 (write _test-input-stream " {\n") -1422 (write _test-input-stream " var x: int\n") -1423 (write _test-input-stream " loop\n") -1424 (write _test-input-stream " increment x\n") -1425 (write _test-input-stream " }\n") -1426 (write _test-input-stream "}\n") -1427 # convert -1428 (convert-mu _test-input-buffered-file _test-output-buffered-file) -1429 (flush _test-output-buffered-file) -1430 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -1436 # check output -1437 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-unconditional-loops-and-local-vars/0") -1438 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-unconditional-loops-and-local-vars/1") -1439 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-unconditional-loops-and-local-vars/2") -1440 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-unconditional-loops-and-local-vars/3") -1441 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-unconditional-loops-and-local-vars/4") -1442 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-unconditional-loops-and-local-vars/5") -1443 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-unconditional-loops-and-local-vars/6") -1444 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:" "F - test-convert-function-with-unconditional-loops-and-local-vars/7") -1445 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-unconditional-loops-and-local-vars/8") -1446 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-unconditional-loops-and-local-vars/9") -1447 (check-next-stream-line-equal _test-output-stream " e9/jump loop/disp32" "F - test-convert-function-with-unconditional-loops-and-local-vars/10") -1448 # not emitted: ff 0/subop/increment *(ebp+0xfffffffc) -1449 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-unconditional-loops-and-local-vars/11") -1450 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:" "F - test-convert-function-with-unconditional-loops-and-local-vars/12") -1451 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-unconditional-loops-and-local-vars/13") -1452 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-unconditional-loops-and-local-vars/14") -1453 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-unconditional-loops-and-local-vars/15") -1454 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-unconditional-loops-and-local-vars/16") -1455 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-unconditional-loops-and-local-vars/17") -1456 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-unconditional-loops-and-local-vars/18") -1457 # . epilogue -1458 89/<- %esp 5/r32/ebp -1459 5d/pop-to-ebp -1460 c3/return -1461 -1462 test-convert-function-with-branches-and-loops-and-local-vars: -1463 # . prologue -1464 55/push-ebp -1465 89/<- %ebp 4/r32/esp -1466 # setup -1467 (clear-stream _test-input-stream) -1468 (clear-stream $_test-input-buffered-file->buffer) -1469 (clear-stream _test-output-stream) -1470 (clear-stream $_test-output-buffered-file->buffer) -1471 c7 0/subop/copy *Next-block-index 1/imm32 -1472 # -1473 (write _test-input-stream "fn foo {\n") -1474 (write _test-input-stream " {\n") -1475 (write _test-input-stream " var x: int\n") -1476 (write _test-input-stream " break-if->=\n") -1477 (write _test-input-stream " increment x\n") -1478 (write _test-input-stream " loop\n") -1479 (write _test-input-stream " }\n") -1480 (write _test-input-stream "}\n") -1481 # convert -1482 (convert-mu _test-input-buffered-file _test-output-buffered-file) -1483 (flush _test-output-buffered-file) -1484 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -1490 # check output -1491 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-branches-and-loops-and-local-vars/0") -1492 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-branches-and-loops-and-local-vars/1") -1493 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-branches-and-loops-and-local-vars/2") -1494 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-branches-and-loops-and-local-vars/3") -1495 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-branches-and-loops-and-local-vars/4") -1496 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-branches-and-loops-and-local-vars/5") -1497 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-branches-and-loops-and-local-vars/6") -1498 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:" "F - test-convert-function-with-branches-and-loops-and-local-vars/7") -1499 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-branches-and-loops-and-local-vars/8") -1500 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-branches-and-loops-and-local-vars/9") -1501 (check-next-stream-line-equal _test-output-stream " 0f 8c/jump-if-< break/disp32" "F - test-convert-function-with-branches-and-loops-and-local-vars/10") -1502 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-branches-and-loops-and-local-vars/11") -1503 (check-next-stream-line-equal _test-output-stream " e9/jump $foo:0x00000002:break/disp32" "F - test-convert-function-with-branches-and-loops-and-local-vars/12") -1504 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-branches-and-loops-and-local-vars/13") -1505 (check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *(ebp+0xfffffffc)" "F - test-convert-function-with-branches-and-loops-and-local-vars/14") -1506 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-branches-and-loops-and-local-vars/15") -1507 (check-next-stream-line-equal _test-output-stream " e9/jump loop/disp32" "F - test-convert-function-with-branches-and-loops-and-local-vars/16") -1508 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-branches-and-loops-and-local-vars/17") -1509 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:" "F - test-convert-function-with-branches-and-loops-and-local-vars/18") -1510 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-branches-and-loops-and-local-vars/19") -1511 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-branches-and-loops-and-local-vars/20") -1512 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-branches-and-loops-and-local-vars/21") -1513 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-branches-and-loops-and-local-vars/22") -1514 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-branches-and-loops-and-local-vars/23") -1515 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-branches-and-loops-and-local-vars/24") -1516 # . epilogue -1517 89/<- %esp 5/r32/ebp -1518 5d/pop-to-ebp -1519 c3/return -1520 -1521 test-convert-function-with-nonlocal-branches-and-loops-and-local-vars: -1522 # . prologue -1523 55/push-ebp -1524 89/<- %ebp 4/r32/esp -1525 # setup -1526 (clear-stream _test-input-stream) -1527 (clear-stream $_test-input-buffered-file->buffer) -1528 (clear-stream _test-output-stream) -1529 (clear-stream $_test-output-buffered-file->buffer) -1530 c7 0/subop/copy *Next-block-index 1/imm32 -1531 # -1532 (write _test-input-stream "fn foo {\n") -1533 (write _test-input-stream " a: {\n") -1534 (write _test-input-stream " var x: int\n") -1535 (write _test-input-stream " {\n") -1536 (write _test-input-stream " var y: int\n") -1537 (write _test-input-stream " break-if->= a\n") -1538 (write _test-input-stream " increment x\n") -1539 (write _test-input-stream " loop\n") -1540 (write _test-input-stream " }\n") -1541 (write _test-input-stream " }\n") -1542 (write _test-input-stream "}\n") -1543 # convert -1544 (convert-mu _test-input-buffered-file _test-output-buffered-file) -1545 (flush _test-output-buffered-file) -1546 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -1552 # check output -1553 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/0") -1554 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/1") -1555 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/2") -1556 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/3") -1557 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/4") -1558 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/5") -1559 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/6") -1560 (check-next-stream-line-equal _test-output-stream "a:loop:" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/7") -1561 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/8") -1562 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/9") -1563 (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/10") -1564 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/11") -1565 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/12") -1566 (check-next-stream-line-equal _test-output-stream " 0f 8c/jump-if-< break/disp32" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/13") -1567 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/14") -1568 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/15") -1569 (check-next-stream-line-equal _test-output-stream " e9/jump a:break/disp32" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/16") -1570 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/17") -1571 (check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *(ebp+0xfffffffc)" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/18") -1572 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/19") -1573 (check-next-stream-line-equal _test-output-stream " e9/jump loop/disp32" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/20") -1574 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/21") -1575 (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/22") -1576 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/23") -1577 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/24") -1578 (check-next-stream-line-equal _test-output-stream "a:break:" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/25") -1579 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/26") -1580 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/27") -1581 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/28") -1582 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/29") -1583 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/30") -1584 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/31") -1585 # . epilogue -1586 89/<- %esp 5/r32/ebp -1587 5d/pop-to-ebp -1588 c3/return -1589 -1590 test-convert-function-with-nonlocal-unconditional-break-and-local-vars: -1591 # . prologue -1592 55/push-ebp -1593 89/<- %ebp 4/r32/esp -1594 # setup -1595 (clear-stream _test-input-stream) -1596 (clear-stream $_test-input-buffered-file->buffer) -1597 (clear-stream _test-output-stream) -1598 (clear-stream $_test-output-buffered-file->buffer) -1599 c7 0/subop/copy *Next-block-index 1/imm32 -1600 # -1601 (write _test-input-stream "fn foo {\n") -1602 (write _test-input-stream " a: {\n") -1603 (write _test-input-stream " var x: int\n") -1604 (write _test-input-stream " {\n") -1605 (write _test-input-stream " var y: int\n") -1606 (write _test-input-stream " break a\n") -1607 (write _test-input-stream " increment x\n") -1608 (write _test-input-stream " }\n") -1609 (write _test-input-stream " }\n") -1610 (write _test-input-stream "}\n") -1611 # convert -1612 (convert-mu _test-input-buffered-file _test-output-buffered-file) -1613 (flush _test-output-buffered-file) -1614 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -1620 # check output -1621 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/0") -1622 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/1") -1623 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/2") -1624 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/3") -1625 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/4") -1626 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/5") -1627 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/6") -1628 (check-next-stream-line-equal _test-output-stream "a:loop:" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/7") -1629 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/8") -1630 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/9") -1631 (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/10") -1632 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/11") -1633 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/12") -1634 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/13") -1635 (check-next-stream-line-equal _test-output-stream " e9/jump a:break/disp32" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/14") -1636 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/15") -1637 (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/16") -1638 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/17") -1639 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/18") -1640 (check-next-stream-line-equal _test-output-stream "a:break:" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/19") -1641 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/20") -1642 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/21") -1643 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/22") -1644 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/23") -1645 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/24") -1646 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/25") -1647 # . epilogue -1648 89/<- %esp 5/r32/ebp -1649 5d/pop-to-ebp -1650 c3/return -1651 -1652 test-convert-function-with-unconditional-break-and-local-vars: -1653 # . prologue -1654 55/push-ebp -1655 89/<- %ebp 4/r32/esp -1656 # setup -1657 (clear-stream _test-input-stream) -1658 (clear-stream $_test-input-buffered-file->buffer) -1659 (clear-stream _test-output-stream) -1660 (clear-stream $_test-output-buffered-file->buffer) -1661 c7 0/subop/copy *Next-block-index 1/imm32 -1662 # -1663 (write _test-input-stream "fn foo {\n") -1664 (write _test-input-stream " {\n") -1665 (write _test-input-stream " var x: int\n") -1666 (write _test-input-stream " {\n") -1667 (write _test-input-stream " var y: int\n") -1668 (write _test-input-stream " break\n") -1669 (write _test-input-stream " increment x\n") -1670 (write _test-input-stream " }\n") -1671 (write _test-input-stream " }\n") -1672 (write _test-input-stream "}\n") -1673 # convert -1674 (convert-mu _test-input-buffered-file _test-output-buffered-file) -1675 (flush _test-output-buffered-file) -1676 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -1682 # check output -1683 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-unconditional-break-and-local-vars/0") -1684 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-unconditional-break-and-local-vars/1") -1685 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-unconditional-break-and-local-vars/2") -1686 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-unconditional-break-and-local-vars/3") -1687 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-unconditional-break-and-local-vars/4") -1688 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-unconditional-break-and-local-vars/5") -1689 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-unconditional-break-and-local-vars/6") -1690 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:" "F - test-convert-function-with-unconditional-break-and-local-vars/7") -1691 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-unconditional-break-and-local-vars/8") -1692 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-unconditional-break-and-local-vars/9") -1693 (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:" "F - test-convert-function-with-unconditional-break-and-local-vars/10") -1694 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-unconditional-break-and-local-vars/11") -1695 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-unconditional-break-and-local-vars/12") -1696 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-unconditional-break-and-local-vars/13") -1697 (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:" "F - test-convert-function-with-unconditional-break-and-local-vars/14") -1698 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-unconditional-break-and-local-vars/15") -1699 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-unconditional-break-and-local-vars/16") -1700 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:" "F - test-convert-function-with-unconditional-break-and-local-vars/17") -1701 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-unconditional-break-and-local-vars/18") -1702 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-unconditional-break-and-local-vars/19") -1703 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-unconditional-break-and-local-vars/20") -1704 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-unconditional-break-and-local-vars/21") -1705 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-unconditional-break-and-local-vars/22") -1706 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-unconditional-break-and-local-vars/23") -1707 # . epilogue -1708 89/<- %esp 5/r32/ebp -1709 5d/pop-to-ebp -1710 c3/return -1711 -1712 test-convert-function-with-nonlocal-unconditional-loop-and-local-vars: -1713 # . prologue -1714 55/push-ebp -1715 89/<- %ebp 4/r32/esp -1716 # setup -1717 (clear-stream _test-input-stream) -1718 (clear-stream $_test-input-buffered-file->buffer) -1719 (clear-stream _test-output-stream) -1720 (clear-stream $_test-output-buffered-file->buffer) -1721 c7 0/subop/copy *Next-block-index 1/imm32 -1722 # -1723 (write _test-input-stream "fn foo {\n") -1724 (write _test-input-stream " a: {\n") -1725 (write _test-input-stream " var x: int\n") -1726 (write _test-input-stream " {\n") -1727 (write _test-input-stream " var y: int\n") -1728 (write _test-input-stream " loop a\n") -1729 (write _test-input-stream " increment x\n") -1730 (write _test-input-stream " }\n") -1731 (write _test-input-stream " }\n") -1732 (write _test-input-stream "}\n") -1733 # convert -1734 (convert-mu _test-input-buffered-file _test-output-buffered-file) -1735 (flush _test-output-buffered-file) -1736 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -1742 # check output -1743 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/0") -1744 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/1") -1745 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/2") -1746 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/3") -1747 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/4") -1748 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/5") -1749 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/6") -1750 (check-next-stream-line-equal _test-output-stream "a:loop:" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/7") -1751 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/8") -1752 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/9") -1753 (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/10") -1754 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/11") -1755 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/12") -1756 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/13") -1757 (check-next-stream-line-equal _test-output-stream " e9/jump a:loop/disp32" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/14") -1758 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/15") -1759 (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/16") -1760 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/17") -1761 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/18") -1762 (check-next-stream-line-equal _test-output-stream "a:break:" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/19") -1763 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/20") -1764 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/21") -1765 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/22") -1766 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/23") -1767 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/24") -1768 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/25") -1769 # . epilogue -1770 89/<- %esp 5/r32/ebp -1771 5d/pop-to-ebp -1772 c3/return -1773 -1774 test-convert-length-of-array: -1775 # . prologue -1776 55/push-ebp -1777 89/<- %ebp 4/r32/esp -1778 # setup -1779 (clear-stream _test-input-stream) -1780 (clear-stream $_test-input-buffered-file->buffer) -1781 (clear-stream _test-output-stream) -1782 (clear-stream $_test-output-buffered-file->buffer) -1783 c7 0/subop/copy *Next-block-index 1/imm32 -1784 # -1785 (write _test-input-stream "fn foo a: (addr array int) {\n") -1786 (write _test-input-stream " var b/eax: (addr array int) <- copy a\n") -1787 (write _test-input-stream " var c/eax: int <- length b\n") -1788 (write _test-input-stream "}\n") -1789 # convert -1790 (convert-mu _test-input-buffered-file _test-output-buffered-file) -1791 (flush _test-output-buffered-file) -1792 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -1798 # check output -1799 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-length-of-array/0") -1800 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-length-of-array/1") -1801 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-length-of-array/2") -1802 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-length-of-array/3") -1803 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-length-of-array/4") -1804 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-length-of-array/5") -1805 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-length-of-array/6") -1806 (check-next-stream-line-equal _test-output-stream " 8b/copy-from *(ebp+0x00000008) 0x00000000/r32" "F - test-convert-length-of-array/7") -1807 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-length-of-array/8") -1808 (check-next-stream-line-equal _test-output-stream " 8b/copy-from *eax 0x00000000/r32" "F - test-convert-length-of-array/9") -1809 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-length-of-array/10") -1810 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-length-of-array/11") -1811 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-length-of-array/12") -1812 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-length-of-array/13") -1813 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-length-of-array/14") -1814 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-length-of-array/15") -1815 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-length-of-array/16") -1816 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-length-of-array/17") -1817 # . epilogue -1818 89/<- %esp 5/r32/ebp -1819 5d/pop-to-ebp -1820 c3/return -1821 -1822 ####################################################### -1823 # Parsing -1824 ####################################################### -1825 -1826 parse-mu: # in: (addr buffered-file) -1827 # pseudocode -1828 # var curr-function: (addr (handle function)) = Program -1829 # var line: (stream byte 512) -1830 # var word-slice: slice -1831 # while true # line loop -1832 # clear-stream(line) -1833 # read-line-buffered(in, line) -1834 # if (line->write == 0) break # end of file -1835 # word-slice = next-mu-token(line) -1836 # if slice-empty?(word-slice) # end of line -1837 # continue -1838 # else if slice-starts-with?(word-slice, "#") # comment -1839 # continue # end of line -1840 # else if slice-equal(word-slice, "fn") -1841 # var new-function: (handle function) = allocate(function) -1842 # var vars: (stack (addr var) 256) -1843 # populate-mu-function-header(in, new-function, vars) -1844 # populate-mu-function-body(in, new-function, vars) -1845 # assert(vars->top == 0) -1846 # *curr-function = new-function -1847 # curr-function = &new-function->next -1848 # else -1849 # abort() -1850 # -1851 # . prologue -1852 55/push-ebp -1853 89/<- %ebp 4/r32/esp -1854 # . save registers -1855 50/push-eax -1856 51/push-ecx -1857 52/push-edx -1858 53/push-ebx -1859 57/push-edi -1860 # var line/ecx: (stream byte 512) -1861 81 5/subop/subtract %esp 0x200/imm32 -1862 68/push 0x200/imm32/length -1863 68/push 0/imm32/read -1864 68/push 0/imm32/write -1865 89/<- %ecx 4/r32/esp -1866 # var word-slice/edx: slice -1867 68/push 0/imm32/end -1868 68/push 0/imm32/start -1869 89/<- %edx 4/r32/esp -1870 # var curr-function/edi: (addr (handle function)) = Program -1871 bf/copy-to-edi Program/imm32 -1872 # var vars/ebx: (stack (addr var) 256) -1873 81 5/subop/subtract %esp 0x400/imm32 -1874 68/push 0x400/imm32/length -1875 68/push 0/imm32/top -1876 89/<- %ebx 4/r32/esp -1877 { -1878 $parse-mu:line-loop: -1879 (clear-stream %ecx) -1880 (read-line-buffered *(ebp+8) %ecx) -1881 # if (line->write == 0) break -1882 81 7/subop/compare *ecx 0/imm32 -1883 0f 84/jump-if-= break/disp32 -1884 +-- 6 lines: #? # dump line ------------------------------------------------------------------------------------------------------------------------------------------------------ -1890 (next-mu-token %ecx %edx) -1891 # if slice-empty?(word-slice) continue -1892 (slice-empty? %edx) -1893 3d/compare-eax-and 0/imm32/false -1894 0f 85/jump-if-!= loop/disp32 -1895 # if (*word-slice->start == "#") continue -1896 # . eax = *word-slice->start -1897 8b/-> *edx 0/r32/eax -1898 8a/copy-byte *eax 0/r32/AL -1899 81 4/subop/and %eax 0xff/imm32 -1900 # . if (eax == '#') continue -1901 3d/compare-eax-and 0x23/imm32/hash -1902 0f 84/jump-if-= loop/disp32 -1903 # if (slice-equal?(word-slice, "fn")) parse a function -1904 { -1905 $parse-mu:fn: -1906 (slice-equal? %edx "fn") -1907 3d/compare-eax-and 0/imm32/false -1908 0f 84/jump-if-= break/disp32 -1909 # var new-function/eax: (handle function) = populate-mu-function(in, new-function, vars) -1910 (allocate Heap *Function-size) # => eax -1911 (zero-out %eax *Function-size) -1912 (clear-stack %ebx) -1913 (populate-mu-function-header %ecx %eax %ebx) -1914 (populate-mu-function-body *(ebp+8) %eax %ebx) -1915 # *curr-function = new-function -1916 89/<- *edi 0/r32/eax -1917 # curr-function = &new-function->next -1918 8d/address-> *(eax+0x14) 7/r32/edi # Function-next -1919 e9/jump $parse-mu:line-loop/disp32 -1920 } -1921 # otherwise abort -1922 e9/jump $parse-mu:error1/disp32 -1923 } # end line loop -1924 $parse-mu:end: -1925 # . reclaim locals -1926 81 0/subop/add %esp 0x630/imm32 -1927 # . restore registers -1928 5f/pop-to-edi -1929 5b/pop-to-ebx -1930 5a/pop-to-edx -1931 59/pop-to-ecx -1932 58/pop-to-eax -1933 # . epilogue -1934 89/<- %esp 5/r32/ebp -1935 5d/pop-to-ebp -1936 c3/return -1937 -1938 $parse-mu:error1: -1939 # error("unexpected top-level command: " word-slice "\n") -1940 (write-buffered Stderr "unexpected top-level command: ") -1941 (write-slice-buffered Stderr %edx) -1942 (write-buffered Stderr "\n") -1943 (flush Stderr) -1944 # . syscall(exit, 1) -1945 bb/copy-to-ebx 1/imm32 -1946 b8/copy-to-eax 1/imm32/exit -1947 cd/syscall 0x80/imm8 -1948 # never gets here -1949 -1950 $parse-mu:error2: -1951 # error(vars->top " vars not reclaimed after fn '" new-function->name "'\n") -1952 (print-int32-buffered Stderr *ebx) -1953 (write-buffered Stderr " vars not reclaimed after fn '") -1954 (write-slice-buffered Stderr *eax) # Function-name -1955 (write-buffered Stderr "'\n") -1956 (flush Stderr) -1957 # . syscall(exit, 1) -1958 bb/copy-to-ebx 1/imm32 -1959 b8/copy-to-eax 1/imm32/exit -1960 cd/syscall 0x80/imm8 -1961 # never gets here -1962 -1963 # scenarios considered: -1964 # ✗ fn foo # no block -1965 # ✓ fn foo { -1966 # ✗ fn foo { { -1967 # ✗ fn foo { } -1968 # ✗ fn foo { } { -1969 # ✗ fn foo x { -1970 # ✗ fn foo x: { -1971 # ✓ fn foo x: int { -1972 # ✓ fn foo x: int { -1973 # ✓ fn foo x: int -> y/eax: int { -1974 populate-mu-function-header: # first-line: (addr stream byte), out: (handle function), vars: (addr stack (handle var)) -1975 # pseudocode: -1976 # var name: slice -1977 # next-mu-token(first-line, name) -1978 # assert(name not in '{' '}' '->') -1979 # out->name = slice-to-string(name) -1980 # var next-offset: int = 8 -1981 # ## inouts -1982 # while true -1983 # ## name -1984 # name = next-mu-token(first-line) -1985 # if (name == '{') goto done -1986 # if (name == '->') break -1987 # assert(name != '}') -1988 # var v: (handle var) = parse-var-with-type(name, first-line) -1989 # assert(v->register == null) -1990 # v->stack-offset = next-offset -1991 # next-offset += size-of(v) -1992 # # v->block-depth is implicitly 0 -1993 # out->inouts = append(out->inouts, v) -1994 # push(vars, v) -1995 # ## outputs -1996 # while true -1997 # ## name -1998 # name = next-mu-token(first-line) -1999 # assert(name not in '{' '}' '->') -2000 # var v: (handle var) = parse-var-with-type(name, first-line) -2001 # assert(v->register != null) -2002 # out->outputs = append(out->outputs, v) -2003 # done: -2004 # -2005 # . prologue -2006 55/push-ebp -2007 89/<- %ebp 4/r32/esp -2008 # . save registers -2009 50/push-eax -2010 51/push-ecx -2011 52/push-edx -2012 53/push-ebx -2013 57/push-edi -2014 # edi = out -2015 8b/-> *(ebp+0xc) 7/r32/edi -2016 # var word-slice/ecx: slice -2017 68/push 0/imm32/end -2018 68/push 0/imm32/start -2019 89/<- %ecx 4/r32/esp -2020 # var next-offset/edx = 8 -2021 ba/copy-to-edx 8/imm32 -2022 # read function name -2023 (next-mu-token *(ebp+8) %ecx) -2024 # error checking -2025 # TODO: error if name starts with 'break' or 'loop' -2026 # if (word-slice == '{') abort -2027 (slice-equal? %ecx "{") # => eax -2028 3d/compare-eax-and 0/imm32/false -2029 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 -2030 # if (word-slice == '->') abort -2031 (slice-equal? %ecx "->") # => eax -2032 3d/compare-eax-and 0/imm32/false -2033 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 -2034 # if (word-slice == '}') abort -2035 (slice-equal? %ecx "}") # => eax -2036 3d/compare-eax-and 0/imm32/false -2037 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 -2038 # save function name -2039 (slice-to-string Heap %ecx) # => eax -2040 89/<- *edi 0/r32/eax # Function-name -2041 # initialize default subx-name as well -2042 89/<- *(edi+4) 0/r32/eax # Function-subx-name -2043 # save function inouts -2044 { -2045 $populate-mu-function-header:check-for-inout: -2046 (next-mu-token *(ebp+8) %ecx) -2047 # if (word-slice == '{') goto done -2048 (slice-equal? %ecx "{") # => eax -2049 3d/compare-eax-and 0/imm32/false -2050 0f 85/jump-if-!= $populate-mu-function-header:done/disp32 -2051 # if (word-slice == '->') break -2052 (slice-equal? %ecx "->") # => eax -2053 3d/compare-eax-and 0/imm32/false -2054 0f 85/jump-if-!= break/disp32 -2055 # if (word-slice == '}') abort -2056 (slice-equal? %ecx "}") # => eax -2057 3d/compare-eax-and 0/imm32/false -2058 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 -2059 # var v/ebx: (handle var) = parse-var-with-type(word-slice, first-line) -2060 (parse-var-with-type %ecx *(ebp+8)) # => eax -2061 89/<- %ebx 0/r32/eax -2062 # assert(v->register == null) -2063 81 7/subop/compare *(ebx+0x10) 0/imm32 # Var-register -2064 0f 85/jump-if-!= $populate-mu-function-header:error2/disp32 -2065 # v->stack-offset = next-offset -2066 89/<- *(ebx+0xc) 2/r32/edx # Var-stack-offset -2067 # next-offset += size-of(v) -2068 (size-of %ebx) # => eax -2069 01/add %edx 0/r32/eax -2070 # v->block-depth is implicitly 0 -2071 # -2072 (append-list Heap %ebx *(edi+8)) # Function-inouts => eax -2073 89/<- *(edi+8) 0/r32/eax # Function-inouts -2074 (push *(ebp+0x10) %ebx) -2075 # -2076 e9/jump loop/disp32 -2077 } -2078 # save function outputs -2079 { -2080 $populate-mu-function-header:check-for-out: -2081 (next-mu-token *(ebp+8) %ecx) -2082 # if (word-slice == '{') break -2083 (slice-equal? %ecx "{") # => eax -2084 3d/compare-eax-and 0/imm32/false -2085 0f 85/jump-if-!= break/disp32 -2086 # if (word-slice == '->') abort -2087 (slice-equal? %ecx "->") # => eax -2088 3d/compare-eax-and 0/imm32/false -2089 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 -2090 # if (word-slice == '}') abort -2091 (slice-equal? %ecx "}") # => eax -2092 3d/compare-eax-and 0/imm32/false -2093 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 -2094 # -2095 (parse-var-with-type %ecx *(ebp+8)) # => eax -2096 89/<- %ebx 0/r32/eax -2097 # assert(var->register != null) -2098 81 7/subop/compare *(ebx+0x10) 0/imm32 # Var-register -2099 0f 84/jump-if-= $populate-mu-function-header:error3/disp32 -2100 (append-list Heap %ebx *(edi+0xc)) # Function-outputs => eax -2101 89/<- *(edi+0xc) 0/r32/eax # Function-outputs -2102 e9/jump loop/disp32 -2103 } -2104 $populate-mu-function-header:done: -2105 (check-no-tokens-left *(ebp+8)) -2106 $populate-mu-function-header:end: -2107 # . reclaim locals -2108 81 0/subop/add %esp 8/imm32 -2109 # . restore registers -2110 5f/pop-to-edi -2111 5b/pop-to-ebx -2112 5a/pop-to-edx -2113 59/pop-to-ecx -2114 58/pop-to-eax -2115 # . epilogue -2116 89/<- %esp 5/r32/ebp -2117 5d/pop-to-ebp -2118 c3/return -2119 -2120 $populate-mu-function-header:error1: -2121 # error("function header not in form 'fn <name> {'") -2122 (write-buffered Stderr "function header not in form 'fn <name> [inouts] [-> outputs] {' -- '") -2123 (flush Stderr) -2124 (rewind-stream *(ebp+8)) -2125 (write-stream 2 *(ebp+8)) -2126 (write-buffered Stderr "'\n") -2127 (flush Stderr) -2128 # . syscall(exit, 1) -2129 bb/copy-to-ebx 1/imm32 -2130 b8/copy-to-eax 1/imm32/exit -2131 cd/syscall 0x80/imm8 -2132 # never gets here -2133 -2134 $populate-mu-function-header:error2: -2135 # error("function input '" var "' cannot be in a register") -2136 (write-buffered Stderr "function input '") -2137 (write-buffered Stderr *ebx) # Var-name -2138 (write-buffered Stderr "' cannot be in a register") -2139 (flush Stderr) -2140 # . syscall(exit, 1) -2141 bb/copy-to-ebx 1/imm32 -2142 b8/copy-to-eax 1/imm32/exit -2143 cd/syscall 0x80/imm8 -2144 # never gets here -2145 -2146 $populate-mu-function-header:error3: -2147 # error("function input '" var "' must be in a register") -2148 (write-buffered Stderr "function input '") -2149 (write-buffered Stderr *eax) # Var-name -2150 (write-buffered Stderr " must be in a register'") -2151 (flush Stderr) -2152 (rewind-stream *(ebp+8)) -2153 (write-stream 2 *(ebp+8)) -2154 (write-buffered Stderr "'\n") -2155 (flush Stderr) -2156 # . syscall(exit, 1) -2157 bb/copy-to-ebx 1/imm32 -2158 b8/copy-to-eax 1/imm32/exit -2159 cd/syscall 0x80/imm8 -2160 # never gets here -2161 -2162 test-function-header-with-arg: -2163 # . prologue -2164 55/push-ebp -2165 89/<- %ebp 4/r32/esp -2166 # setup -2167 (clear-stream _test-input-stream) -2168 (write _test-input-stream "foo n: int {\n") -2169 # var result/ecx: function -2170 2b/subtract-> *Function-size 4/r32/esp -2171 89/<- %ecx 4/r32/esp -2172 (zero-out %ecx *Function-size) -2173 # var vars/ebx: (stack (addr var) 16) -2174 81 5/subop/subtract %esp 0x10/imm32 -2175 68/push 0x10/imm32/length -2176 68/push 0/imm32/top -2177 89/<- %ebx 4/r32/esp -2178 # convert -2179 (populate-mu-function-header _test-input-stream %ecx %ebx) -2180 # check result -2181 (check-strings-equal *ecx "foo" "F - test-function-header-with-arg/name") # Function-name -2182 # edx: (handle list var) = result->inouts -2183 8b/-> *(ecx+8) 2/r32/edx # Function-inouts -2184 # ebx: (handle var) = result->inouts->value -2185 8b/-> *edx 3/r32/ebx # List-value -2186 (check-strings-equal *ebx "n" "F - test-function-header-with-arg/inout:0") # Var-name -2187 8b/-> *(ebx+4) 3/r32/ebx # Var-type -2188 (check-ints-equal *ebx 1 "F - test-function-header-with-arg/inout:0/type:0") # Tree-left -2189 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-arg/inout:0/type:1") # Tree-right -2190 # . epilogue -2191 89/<- %esp 5/r32/ebp -2192 5d/pop-to-ebp -2193 c3/return -2194 -2195 test-function-header-with-multiple-args: -2196 # . prologue -2197 55/push-ebp -2198 89/<- %ebp 4/r32/esp -2199 # setup -2200 (clear-stream _test-input-stream) -2201 (write _test-input-stream "foo a: int, b: int c: int {\n") -2202 # result/ecx: (handle function) -2203 2b/subtract-> *Function-size 4/r32/esp -2204 89/<- %ecx 4/r32/esp -2205 (zero-out %ecx *Function-size) -2206 # var vars/ebx: (stack (addr var) 16) -2207 81 5/subop/subtract %esp 0x10/imm32 -2208 68/push 0x10/imm32/length -2209 68/push 0/imm32/top -2210 89/<- %ebx 4/r32/esp -2211 # convert -2212 (populate-mu-function-header _test-input-stream %ecx %ebx) -2213 # check result -2214 (check-strings-equal *ecx "foo") # Function-name -2215 # edx: (handle list var) = result->inouts -2216 8b/-> *(ecx+8) 2/r32/edx # Function-inouts -2217 $test-function-header-with-multiple-args:inout0: -2218 # ebx: (handle var) = result->inouts->value -2219 8b/-> *edx 3/r32/ebx # List-value -2220 (check-strings-equal *ebx "a" "F - test-function-header-with-multiple-args/inout:0") # Var-name -2221 8b/-> *(ebx+4) 3/r32/ebx # Var-type -2222 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args/inout:0/type:0") # Tree-left -2223 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args/inout:0/type:1") # Tree-right -2224 # edx = result->inouts->next -2225 8b/-> *(edx+4) 2/r32/edx # List-next -2226 $test-function-header-with-multiple-args:inout1: -2227 # ebx = result->inouts->next->value -2228 8b/-> *edx 3/r32/ebx # List-value -2229 (check-strings-equal *ebx "b" "F - test-function-header-with-multiple-args/inout:1") # Var-name -2230 8b/-> *(ebx+4) 3/r32/ebx # Var-type -2231 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args/inout:1/type:0") # Tree-left -2232 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args/inout:1/type:1") # Tree-right -2233 # edx = result->inouts->next->next -2234 8b/-> *(edx+4) 2/r32/edx # List-next -2235 $test-function-header-with-multiple-args:inout2: -2236 # ebx = result->inouts->next->next->value -2237 8b/-> *edx 3/r32/ebx # List-value -2238 (check-strings-equal *ebx "c" "F - test-function-header-with-multiple-args/inout:2") # Var-name -2239 8b/-> *(ebx+4) 3/r32/ebx # Var-type -2240 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args/inout:2/type:0") # Tree-left -2241 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args/inout:2/type:1") # Tree-right -2242 # . epilogue -2243 89/<- %esp 5/r32/ebp -2244 5d/pop-to-ebp -2245 c3/return -2246 -2247 test-function-with-multiple-args-and-outputs: -2248 # . prologue -2249 55/push-ebp -2250 89/<- %ebp 4/r32/esp -2251 # setup -2252 (clear-stream _test-input-stream) -2253 (write _test-input-stream "foo a: int, b: int, c: int -> x/ecx: int y/edx: int {\n") -2254 # result/ecx: (handle function) -2255 2b/subtract-> *Function-size 4/r32/esp -2256 89/<- %ecx 4/r32/esp -2257 (zero-out %ecx *Function-size) -2258 # var vars/ebx: (stack (addr var) 16) -2259 81 5/subop/subtract %esp 0x10/imm32 -2260 68/push 0x10/imm32/length -2261 68/push 0/imm32/top -2262 89/<- %ebx 4/r32/esp -2263 # convert -2264 (populate-mu-function-header _test-input-stream %ecx %ebx) -2265 # check result -2266 (check-strings-equal *ecx "foo") # Function-name -2267 # edx: (handle list var) = result->inouts -2268 8b/-> *(ecx+8) 2/r32/edx # Function-inouts -2269 # ebx: (handle var) = result->inouts->value -2270 8b/-> *edx 3/r32/ebx # List-value -2271 (check-strings-equal *ebx "a" "F - test-function-header-with-multiple-args-and-outputs/inout:0") # Var-name -2272 8b/-> *(ebx+4) 3/r32/ebx # Var-type -2273 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args-and-outputs/inout:0/type:0") # Tree-left -2274 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args-and-outputs/inout:0/type:1") # Tree-right -2275 # edx = result->inouts->next -2276 8b/-> *(edx+4) 2/r32/edx # List-next -2277 # ebx = result->inouts->next->value -2278 8b/-> *edx 3/r32/ebx # List-value -2279 (check-strings-equal *ebx "b" "F - test-function-header-with-multiple-args-and-outputs/inout:1") # Var-name -2280 8b/-> *(ebx+4) 3/r32/ebx # Var-type -2281 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args-and-outputs/inout:1/type:0") # Tree-left -2282 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args-and-outputs/inout:1/type:1") # Tree-right -2283 # edx = result->inouts->next->next -2284 8b/-> *(edx+4) 2/r32/edx # List-next -2285 # ebx = result->inouts->next->next->value -2286 8b/-> *edx 3/r32/ebx # List-value -2287 (check-strings-equal *ebx "c" "F - test-function-header-with-multiple-args-and-outputs/inout:2") # Var-name -2288 8b/-> *(ebx+4) 3/r32/ebx # Var-type -2289 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args-and-outputs/inout:2/type:0") # Tree-left -2290 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args-and-outputs/inout:2/type:1") # Tree-right -2291 # edx: (handle list var) = result->outputs -2292 8b/-> *(ecx+0xc) 2/r32/edx # Function-outputs -2293 # ebx: (handle var) = result->outputs->value -2294 8b/-> *edx 3/r32/ebx # List-value -2295 (check-strings-equal *ebx "x" "F - test-function-header-with-multiple-args-and-outputs/output:0") # Var-name -2296 (check-strings-equal *(ebx+0x10) "ecx" "F - test-function-header-with-multiple-args-and-outputs/output:0/register") # Var-register -2297 8b/-> *(ebx+4) 3/r32/ebx # Var-type -2298 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args-and-outputs/output:0/type:1") # Tree-left -2299 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args-and-outputs/output:0/type:1") # Tree-right -2300 # edx = result->outputs->next -2301 8b/-> *(edx+4) 2/r32/edx # List-next -2302 # ebx = result->outputs->next->value -2303 8b/-> *edx 3/r32/ebx # List-value -2304 (check-strings-equal *ebx "y" "F - test-function-header-with-multiple-args-and-outputs/output:1") # Var-name -2305 (check-strings-equal *(ebx+0x10) "edx" "F - test-function-header-with-multiple-args-and-outputs/output:0/register") # Var-register -2306 8b/-> *(ebx+4) 3/r32/ebx # Var-type -2307 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args-and-outputs/output:1/type:1") # Tree-left -2308 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args-and-outputs/output:1/type:1") # Tree-right -2309 # . epilogue -2310 89/<- %esp 5/r32/ebp -2311 5d/pop-to-ebp -2312 c3/return -2313 -2314 # format for variables with types -2315 # x: int -2316 # x: int, -2317 # x/eax: int -2318 # x/eax: int, -2319 # ignores at most one trailing comma -2320 # WARNING: modifies name -2321 parse-var-with-type: # name: (addr slice), first-line: (addr stream byte) -> result/eax: (handle var) -2322 # pseudocode: -2323 # var v: (handle var) = allocate(Heap, Var-size) -2324 # var s: slice -2325 # if (!slice-ends-with(name, ":")) -2326 # abort -2327 # --name->end to skip ':' -2328 # next-token-from-slice(name->start, name->end, '/', s) -2329 # v->name = slice-to-string(s) -2330 # ## register -2331 # next-token-from-slice(s->end, name->end, '/', s) -2332 # if (!slice-empty?(s)) -2333 # v->register = slice-to-string(s) -2334 # ## type -2335 # var type: (handle tree type-id) = parse-type(first-line) -2336 # v->type = type -2337 # return v -2338 # -2339 # . prologue -2340 55/push-ebp -2341 89/<- %ebp 4/r32/esp -2342 # . save registers -2343 51/push-ecx -2344 52/push-edx -2345 53/push-ebx -2346 56/push-esi -2347 57/push-edi -2348 # esi = name -2349 8b/-> *(ebp+8) 6/r32/esi -2350 # if (!slice-ends-with?(name, ":")) abort -2351 8b/-> *(esi+4) 1/r32/ecx # Slice-end -2352 49/decrement-ecx -2353 8a/copy-byte *ecx 1/r32/CL -2354 81 4/subop/and %ecx 0xff/imm32 -2355 81 7/subop/compare %ecx 0x3a/imm32/colon -2356 0f 85/jump-if-!= $parse-var-with-type:abort/disp32 -2357 # --name->end to skip ':' -2358 ff 1/subop/decrement *(esi+4) -2359 # var result/edi: (handle var) = allocate(Heap, Var-size) -2360 (allocate Heap *Var-size) # => eax -2361 (zero-out %eax *Var-size) -2362 89/<- %edi 0/r32/eax -2363 # var s/ecx: slice -2364 68/push 0/imm32/end -2365 68/push 0/imm32/start -2366 89/<- %ecx 4/r32/esp -2367 $parse-var-with-type:save-name: -2368 # save v->name -2369 (next-token-from-slice *esi *(esi+4) 0x2f %ecx) # Slice-start, Slice-end, '/' -2370 # . end/edx = s->end -2371 8b/-> *(ecx+4) 2/r32/edx -2372 $parse-var-with-type:write-name: -2373 (slice-to-string Heap %ecx) # => eax -2374 89/<- *edi 0/r32/eax # Var-name -2375 # save v->register -2376 $parse-var-with-type:save-register: -2377 (next-token-from-slice %edx *(esi+4) 0x2f %ecx) # end, name->end, '/' -2378 # if (!slice-empty?(s)) v->register = slice-to-string(s) -2379 { -2380 $parse-var-with-type:write-register: -2381 (slice-empty? %ecx) # => eax -2382 3d/compare-eax-and 0/imm32/false -2383 75/jump-if-!= break/disp8 -2384 (slice-to-string Heap %ecx) -2385 89/<- *(edi+0x10) 0/r32/eax # Var-register -2386 } -2387 $parse-var-with-type:save-type: -2388 (parse-type Heap *(ebp+0xc)) # => eax -2389 89/<- *(edi+4) 0/r32/eax # Var-type -2390 $parse-var-with-type:end: -2391 # return result -2392 89/<- %eax 7/r32/edi -2393 # . reclaim locals -2394 81 0/subop/add %esp 8/imm32 -2395 # . restore registers -2396 5f/pop-to-edi -2397 5e/pop-to-esi -2398 5b/pop-to-ebx -2399 5a/pop-to-edx -2400 59/pop-to-ecx -2401 # . epilogue -2402 89/<- %esp 5/r32/ebp -2403 5d/pop-to-ebp -2404 c3/return -2405 -2406 $parse-var-with-type:abort: -2407 # error("var should have form 'name: type' in '" line "'\n") -2408 (write-buffered Stderr "var should have form 'name: type' in '") -2409 (flush Stderr) -2410 (rewind-stream *(ebp+0xc)) -2411 (write-stream 2 *(ebp+0xc)) -2412 (write-buffered Stderr "'\n") -2413 (flush Stderr) -2414 # . syscall(exit, 1) -2415 bb/copy-to-ebx 1/imm32 -2416 b8/copy-to-eax 1/imm32/exit -2417 cd/syscall 0x80/imm8 -2418 # never gets here -2419 -2420 parse-type: # ad: (address allocation-descriptor), in: (addr stream byte) -> result/eax: (handle tree type-id) -2421 # pseudocode: -2422 # var s: slice = next-mu-token(in) -2423 # assert s != "" -2424 # assert s != "->" -2425 # assert s != "{" -2426 # assert s != "}" -2427 # if s == ")" -2428 # return 0 -2429 # result = allocate(Tree) -2430 # zero-out(result, *Tree-size) -2431 # if s != "(" -2432 # result->left = pos-slice(Type-id, s) -2433 # return -2434 # result->left = parse-type(ad, in) -2435 # result->right = parse-type-tree(ad, in) -2436 # -2437 # . prologue -2438 55/push-ebp -2439 89/<- %ebp 4/r32/esp -2440 # . save registers -2441 51/push-ecx -2442 52/push-edx -2443 # var s/ecx: slice -2444 68/push 0/imm32 -2445 68/push 0/imm32 -2446 89/<- %ecx 4/r32/esp -2447 # s = next-mu-token(in) -2448 (next-mu-token *(ebp+0xc) %ecx) -2449 #? (write-buffered Stderr "tok: ") -2450 #? (write-slice-buffered Stderr %ecx) -2451 #? (write-buffered Stderr "$\n") -2452 #? (flush Stderr) -2453 # assert s != "" -2454 (slice-equal? %ecx "") -2455 3d/compare-eax-and 0/imm32/false -2456 0f 85/jump-if-!= $parse-type:abort/disp32 -2457 # assert s != "{" -2458 (slice-equal? %ecx "{") -2459 3d/compare-eax-and 0/imm32/false -2460 0f 85/jump-if-!= $parse-type:abort/disp32 -2461 # assert s != "}" -2462 (slice-equal? %ecx "}") -2463 3d/compare-eax-and 0/imm32/false -2464 0f 85/jump-if-!= $parse-type:abort/disp32 -2465 # assert s != "->" -2466 (slice-equal? %ecx "->") -2467 3d/compare-eax-and 0/imm32/false -2468 0f 85/jump-if-!= $parse-type:abort/disp32 -2469 # if (s == ")") return 0 -2470 (slice-equal? %ecx ")") -2471 3d/compare-eax-and 0/imm32/false -2472 b8/copy-to-eax 0/imm32 -2473 0f 85/jump-if-!= $parse-type:end/disp32 -2474 # var result/edx: (handle tree type-id) -2475 (allocate *(ebp+8) *Tree-size) # => eax -2476 (zero-out %eax *Tree-size) -2477 89/<- %edx 0/r32/eax -2478 { -2479 # if (s != "(") break -2480 (slice-equal? %ecx "(") -2481 3d/compare-eax-and 0/imm32/false -2482 75/jump-if-!= break/disp8 -2483 # result->left = pos-slice(Type-id, s) -2484 (pos-slice Type-id %ecx) -2485 #? (write-buffered Stderr "=> {") -2486 #? (print-int32-buffered Stderr %eax) -2487 #? (write-buffered Stderr ", 0}\n") -2488 #? (flush Stderr) -2489 89/<- *edx 0/r32/eax # Tree-left -2490 e9/jump $parse-type:return-edx/disp32 -2491 } -2492 # otherwise s == "(" -2493 # result->left = parse-type(ad, in) -2494 (parse-type *(ebp+8) *(ebp+0xc)) -2495 #? (write-buffered Stderr "=> {") -2496 #? (print-int32-buffered Stderr %eax) -2497 89/<- *edx 0/r32/eax # Tree-left -2498 # result->right = parse-type-tree(ad, in) -2499 (parse-type-tree *(ebp+8) *(ebp+0xc)) -2500 #? (write-buffered Stderr Space) -2501 #? (print-int32-buffered Stderr %eax) -2502 #? (write-buffered Stderr "}\n") -2503 #? (flush Stderr) -2504 89/<- *(edx+4) 0/r32/eax # Tree-right -2505 $parse-type:return-edx: -2506 89/<- %eax 2/r32/edx -2507 $parse-type:end: -2508 # . reclaim locals -2509 81 0/subop/add %esp 8/imm32 -2510 # . restore registers -2511 5a/pop-to-edx -2512 59/pop-to-ecx -2513 # . epilogue -2514 89/<- %esp 5/r32/ebp -2515 5d/pop-to-ebp -2516 c3/return -2517 -2518 $parse-type:abort: -2519 # error("unexpected token when parsing type: '" s "'\n") -2520 (write-buffered Stderr "unexpected token when parsing type: '") -2521 (write-slice-buffered Stderr %ecx) -2522 (write-buffered Stderr "'\n") -2523 (flush Stderr) -2524 # . syscall(exit, 1) -2525 bb/copy-to-ebx 1/imm32 -2526 b8/copy-to-eax 1/imm32/exit -2527 cd/syscall 0x80/imm8 -2528 # never gets here -2529 -2530 parse-type-tree: # ad: (address allocation-descriptor), in: (addr stream byte) -> result/eax: (handle tree type-id) -2531 # pseudocode: -2532 # var tmp: (handle tree type-id) = parse-type(ad, in) -2533 # if tmp == 0 -2534 # return 0 -2535 # result = allocate(Tree) -2536 # zero-out(result, *Tree-size) -2537 # result->left = tmp -2538 # result->right = parse-type-tree(ad, in) -2539 # -2540 # . prologue -2541 55/push-ebp -2542 89/<- %ebp 4/r32/esp -2543 # . save registers -2544 51/push-ecx -2545 52/push-edx -2546 # var tmp/eax: (handle tree type-id) = parse-type(ad, in) -2547 (parse-type *(ebp+8) *(ebp+0xc)) -2548 # if (tmp == 0) return tmp -2549 3d/compare-eax-and 0/imm32 -2550 74/jump-if-= $parse-type-tree:end/disp8 -2551 # var tmp2/ecx = tmp -2552 89/<- %ecx 0/r32/eax -2553 # var result/edx: (handle tree type-id) -2554 (allocate *(ebp+8) *Tree-size) # => eax -2555 (zero-out %eax *Tree-size) -2556 89/<- %edx 0/r32/eax -2557 # result->left = tmp2 -2558 89/<- *edx 1/r32/ecx # Tree-left -2559 # result->right = parse-type-tree(ad, in) -2560 (parse-type-tree *(ebp+8) *(ebp+0xc)) -2561 89/<- *(edx+4) 0/r32/eax # Tree-right -2562 $parse-type-tree:return-edx: -2563 89/<- %eax 2/r32/edx -2564 $parse-type-tree:end: -2565 # . restore registers -2566 5a/pop-to-edx -2567 59/pop-to-ecx -2568 # . epilogue -2569 89/<- %esp 5/r32/ebp -2570 5d/pop-to-ebp -2571 c3/return -2572 -2573 next-mu-token: # in: (addr stream byte), out: (addr slice) -2574 # pseudocode: -2575 # start: -2576 # skip-chars-matching-whitespace(in) -2577 # if in->read >= in->write # end of in -2578 # out = {0, 0} -2579 # return -2580 # out->start = &in->data[in->read] -2581 # var curr-byte/eax: byte = in->data[in->read] -2582 # if curr->byte == ',' # comment token -2583 # ++in->read -2584 # goto start -2585 # if curr-byte == '#' # comment -2586 # goto done # treat as eof -2587 # if curr-byte == '"' # string literal -2588 # skip-string(in) -2589 # goto done # no metadata -2590 # if curr-byte == '(' -2591 # ++in->read -2592 # goto done -2593 # if curr-byte == ')' -2594 # ++in->read -2595 # goto done -2596 # # read a word -2597 # while true -2598 # if in->read >= in->write -2599 # break -2600 # curr-byte = in->data[in->read] -2601 # if curr-byte == ' ' -2602 # break -2603 # if curr-byte == '\r' -2604 # break -2605 # if curr-byte == '\n' -2606 # break -2607 # if curr-byte == '(' -2608 # break -2609 # if curr-byte == ')' -2610 # break -2611 # if curr-byte == ',' -2612 # break -2613 # ++in->read -2614 # done: -2615 # out->end = &in->data[in->read] -2616 # -2617 # . prologue -2618 55/push-ebp -2619 89/<- %ebp 4/r32/esp -2620 # . save registers -2621 50/push-eax -2622 51/push-ecx -2623 56/push-esi -2624 57/push-edi -2625 # esi = in -2626 8b/-> *(ebp+8) 6/r32/esi -2627 # edi = out -2628 8b/-> *(ebp+0xc) 7/r32/edi -2629 $next-mu-token:start: -2630 (skip-chars-matching-whitespace %esi) -2631 $next-mu-token:check0: -2632 # if (in->read >= in->write) return out = {0, 0} -2633 # . ecx = in->read -2634 8b/-> *(esi+4) 1/r32/ecx -2635 # . if (ecx >= in->write) return out = {0, 0} -2636 3b/compare 1/r32/ecx *esi -2637 c7 0/subop/copy *edi 0/imm32 -2638 c7 0/subop/copy *(edi+4) 0/imm32 -2639 0f 8d/jump-if->= $next-mu-token:end/disp32 -2640 # out->start = &in->data[in->read] -2641 8d/copy-address *(esi+ecx+0xc) 0/r32/eax -2642 89/<- *edi 0/r32/eax -2643 # var curr-byte/eax: byte = in->data[in->read] -2644 31/xor %eax 0/r32/eax -2645 8a/copy-byte *(esi+ecx+0xc) 0/r32/AL -2646 { -2647 $next-mu-token:check-for-comma: -2648 # if (curr-byte != ',') break -2649 3d/compare-eax-and 0x2c/imm32/comma -2650 75/jump-if-!= break/disp8 -2651 # ++in->read -2652 ff 0/subop/increment *(esi+4) -2653 # restart -2654 e9/jump $next-mu-token:start/disp32 -2655 } -2656 { -2657 $next-mu-token:check-for-comment: -2658 # if (curr-byte != '#') break -2659 3d/compare-eax-and 0x23/imm32/pound -2660 75/jump-if-!= break/disp8 -2661 # return eof -2662 e9/jump $next-mu-token:done/disp32 -2663 } -2664 { -2665 $next-mu-token:check-for-string-literal: -2666 # if (curr-byte != '"') break -2667 3d/compare-eax-and 0x22/imm32/dquote -2668 75/jump-if-!= break/disp8 -2669 (skip-string %esi) -2670 # return -2671 e9/jump $next-mu-token:done/disp32 -2672 } -2673 { -2674 $next-mu-token:check-for-open-paren: -2675 # if (curr-byte != '(') break -2676 3d/compare-eax-and 0x28/imm32/open-paren -2677 75/jump-if-!= break/disp8 -2678 # ++in->read -2679 ff 0/subop/increment *(esi+4) -2680 # return -2681 e9/jump $next-mu-token:done/disp32 -2682 } -2683 { -2684 $next-mu-token:check-for-close-paren: -2685 # if (curr-byte != ')') break -2686 3d/compare-eax-and 0x29/imm32/close-paren -2687 75/jump-if-!= break/disp8 -2688 # ++in->read -2689 ff 0/subop/increment *(esi+4) -2690 # return -2691 e9/jump $next-mu-token:done/disp32 -2692 } -2693 { -2694 $next-mu-token:regular-word-without-metadata: -2695 # if (in->read >= in->write) break -2696 # . ecx = in->read -2697 8b/-> *(esi+4) 1/r32/ecx -2698 # . if (ecx >= in->write) break -2699 3b/compare *esi 1/r32/ecx -2700 7d/jump-if->= break/disp8 -2701 # var c/eax: byte = in->data[in->read] -2702 31/xor %eax 0/r32/eax -2703 8a/copy-byte *(esi+ecx+0xc) 0/r32/AL -2704 # if (c == ' ') break -2705 3d/compare-eax-and 0x20/imm32/space -2706 74/jump-if-= break/disp8 -2707 # if (c == '\r') break -2708 3d/compare-eax-and 0xd/imm32/carriage-return -2709 74/jump-if-= break/disp8 -2710 # if (c == '\n') break -2711 3d/compare-eax-and 0xa/imm32/newline -2712 74/jump-if-= break/disp8 -2713 # if (c == '(') break -2714 3d/compare-eax-and 0x28/imm32/open-paren -2715 0f 84/jump-if-= break/disp32 -2716 # if (c == ')') break -2717 3d/compare-eax-and 0x29/imm32/close-paren -2718 0f 84/jump-if-= break/disp32 -2719 # if (c == ',') break -2720 3d/compare-eax-and 0x2c/imm32/comma -2721 0f 84/jump-if-= break/disp32 + 476 # convert + 477 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 478 (flush _test-output-buffered-file) + 479 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- + 485 # check first function + 486 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-multiple-function-skeletons/0") + 487 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-multiple-function-skeletons/1") + 488 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-multiple-function-skeletons/2") + 489 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-multiple-function-skeletons/3") + 490 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-multiple-function-skeletons/4") + 491 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-multiple-function-skeletons/5") + 492 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-multiple-function-skeletons/6") + 493 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-multiple-function-skeletons/7") + 494 # check second function + 495 (check-next-stream-line-equal _test-output-stream "bar:" "F - test-convert-multiple-function-skeletons/10") + 496 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-multiple-function-skeletons/11") + 497 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-multiple-function-skeletons/12") + 498 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-multiple-function-skeletons/13") + 499 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-multiple-function-skeletons/14") + 500 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-multiple-function-skeletons/15") + 501 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-multiple-function-skeletons/16") + 502 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-multiple-function-skeletons/17") + 503 # . epilogue + 504 89/<- %esp 5/r32/ebp + 505 5d/pop-to-ebp + 506 c3/return + 507 + 508 test-convert-function-with-arg: + 509 # . prologue + 510 55/push-ebp + 511 89/<- %ebp 4/r32/esp + 512 # setup + 513 (clear-stream _test-input-stream) + 514 (clear-stream $_test-input-buffered-file->buffer) + 515 (clear-stream _test-output-stream) + 516 (clear-stream $_test-output-buffered-file->buffer) + 517 # + 518 (write _test-input-stream "fn foo n: int {\n") + 519 (write _test-input-stream "}\n") + 520 # convert + 521 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 522 (flush _test-output-buffered-file) + 523 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- + 529 # check output + 530 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-arg/0") + 531 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-arg/1") + 532 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-arg/2") + 533 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-arg/3") + 534 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-arg/4") + 535 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-arg/5") + 536 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-arg/6") + 537 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-arg/7") + 538 # . epilogue + 539 89/<- %esp 5/r32/ebp + 540 5d/pop-to-ebp + 541 c3/return + 542 + 543 test-convert-function-with-arg-and-body: + 544 # . prologue + 545 55/push-ebp + 546 89/<- %ebp 4/r32/esp + 547 # setup + 548 (clear-stream _test-input-stream) + 549 (clear-stream $_test-input-buffered-file->buffer) + 550 (clear-stream _test-output-stream) + 551 (clear-stream $_test-output-buffered-file->buffer) + 552 c7 0/subop/copy *Next-block-index 1/imm32 + 553 # + 554 (write _test-input-stream "fn foo n: int {\n") + 555 (write _test-input-stream " increment n\n") + 556 (write _test-input-stream "}\n") + 557 # convert + 558 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 559 (flush _test-output-buffered-file) + 560 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- + 566 # check output + 567 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-arg-and-body/0") + 568 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-arg-and-body/1") + 569 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-arg-and-body/2") + 570 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-arg-and-body/3") + 571 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-arg-and-body/4") + 572 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-arg-and-body/5") + 573 (check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *(ebp+0x00000008)" "F - test-convert-function-with-arg-and-body/6") + 574 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-arg-and-body/7") + 575 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-arg-and-body/8") + 576 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-arg-and-body/9") + 577 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-arg-and-body/10") + 578 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-arg-and-body/11") + 579 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-arg-and-body/12") + 580 # . epilogue + 581 89/<- %esp 5/r32/ebp + 582 5d/pop-to-ebp + 583 c3/return + 584 + 585 test-convert-function-distinguishes-args: + 586 # . prologue + 587 55/push-ebp + 588 89/<- %ebp 4/r32/esp + 589 # setup + 590 (clear-stream _test-input-stream) + 591 (clear-stream $_test-input-buffered-file->buffer) + 592 (clear-stream _test-output-stream) + 593 (clear-stream $_test-output-buffered-file->buffer) + 594 c7 0/subop/copy *Next-block-index 1/imm32 + 595 # + 596 (write _test-input-stream "fn foo a: int, b: int {\n") + 597 (write _test-input-stream " increment b\n") + 598 (write _test-input-stream "}\n") + 599 # convert + 600 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 601 (flush _test-output-buffered-file) + 602 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- + 608 # check output + 609 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-distinguishes-args/0") + 610 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-distinguishes-args/1") + 611 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-distinguishes-args/2") + 612 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-distinguishes-args/3") + 613 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-distinguishes-args/4") + 614 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-distinguishes-args/5") + 615 (check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *(ebp+0x0000000c)" "F - test-convert-function-distinguishes-args/6") + 616 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-distinguishes-args/7") + 617 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-distinguishes-args/8") + 618 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-distinguishes-args/9") + 619 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-distinguishes-args/10") + 620 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-distinguishes-args/11") + 621 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-distinguishes-args/12") + 622 # . epilogue + 623 89/<- %esp 5/r32/ebp + 624 5d/pop-to-ebp + 625 c3/return + 626 + 627 test-convert-function-returns-result: + 628 # . prologue + 629 55/push-ebp + 630 89/<- %ebp 4/r32/esp + 631 # setup + 632 (clear-stream _test-input-stream) + 633 (clear-stream $_test-input-buffered-file->buffer) + 634 (clear-stream _test-output-stream) + 635 (clear-stream $_test-output-buffered-file->buffer) + 636 c7 0/subop/copy *Next-block-index 1/imm32 + 637 # + 638 (write _test-input-stream "fn foo a: int, b: int -> result/eax: int {\n") + 639 (write _test-input-stream " result <- copy a\n") + 640 (write _test-input-stream " result <- increment\n") + 641 (write _test-input-stream "}\n") + 642 # convert + 643 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 644 (flush _test-output-buffered-file) + 645 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- + 651 # check output + 652 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-returns-result/0") + 653 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-returns-result/1") + 654 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-returns-result/2") + 655 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-returns-result/3") + 656 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-returns-result/4") + 657 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-returns-result/5") + 658 (check-next-stream-line-equal _test-output-stream " 8b/copy-from *(ebp+0x00000008) 0x00000000/r32" "F - test-convert-function-returns-result/6") + 659 (check-next-stream-line-equal _test-output-stream " 40/increment-eax" "F - test-convert-function-returns-result/7") + 660 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-returns-result/8") + 661 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-returns-result/9") + 662 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-returns-result/10") + 663 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-returns-result/11") + 664 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-returns-result/12") + 665 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-returns-result/13") + 666 # . epilogue + 667 89/<- %esp 5/r32/ebp + 668 5d/pop-to-ebp + 669 c3/return + 670 + 671 test-convert-function-literal-arg: + 672 # . prologue + 673 55/push-ebp + 674 89/<- %ebp 4/r32/esp + 675 # setup + 676 (clear-stream _test-input-stream) + 677 (clear-stream $_test-input-buffered-file->buffer) + 678 (clear-stream _test-output-stream) + 679 (clear-stream $_test-output-buffered-file->buffer) + 680 c7 0/subop/copy *Next-block-index 1/imm32 + 681 # + 682 (write _test-input-stream "fn foo a: int, b: int -> result/eax: int {\n") + 683 (write _test-input-stream " result <- copy a\n") + 684 (write _test-input-stream " result <- add 1\n") + 685 (write _test-input-stream "}\n") + 686 # convert + 687 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 688 (flush _test-output-buffered-file) + 689 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- + 695 # check output + 696 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-literal-arg/0") + 697 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-literal-arg/1") + 698 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-literal-arg/2") + 699 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-literal-arg/3") + 700 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-literal-arg/4") + 701 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-literal-arg/5") + 702 (check-next-stream-line-equal _test-output-stream " 8b/copy-from *(ebp+0x00000008) 0x00000000/r32" "F - test-convert-function-literal-arg/6") + 703 (check-next-stream-line-equal _test-output-stream " 05/add-to-eax 1/imm32" "F - test-convert-function-literal-arg/7") + 704 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-literal-arg/8") + 705 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-literal-arg/9") + 706 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-literal-arg/10") + 707 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-literal-arg/11") + 708 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-literal-arg/12") + 709 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-literal-arg/13") + 710 # . epilogue + 711 89/<- %esp 5/r32/ebp + 712 5d/pop-to-ebp + 713 c3/return + 714 + 715 test-convert-function-literal-arg-2: + 716 # . prologue + 717 55/push-ebp + 718 89/<- %ebp 4/r32/esp + 719 # setup + 720 (clear-stream _test-input-stream) + 721 (clear-stream $_test-input-buffered-file->buffer) + 722 (clear-stream _test-output-stream) + 723 (clear-stream $_test-output-buffered-file->buffer) + 724 c7 0/subop/copy *Next-block-index 1/imm32 + 725 # + 726 (write _test-input-stream "fn foo a: int, b: int -> result/ebx: int {\n") + 727 (write _test-input-stream " result <- copy a\n") + 728 (write _test-input-stream " result <- add 1\n") + 729 (write _test-input-stream "}\n") + 730 # convert + 731 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 732 (flush _test-output-buffered-file) + 733 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- + 739 # check output + 740 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-literal-arg-2/0") + 741 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-literal-arg-2/1") + 742 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-literal-arg-2/2") + 743 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-literal-arg-2/3") + 744 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-literal-arg-2/4") + 745 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-literal-arg-2/5") + 746 (check-next-stream-line-equal _test-output-stream " 8b/copy-from *(ebp+0x00000008) 0x00000003/r32" "F - test-convert-function-literal-arg-2/6") + 747 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %ebx 1/imm32" "F - test-convert-function-literal-arg-2/7") + 748 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-literal-arg-2/8") + 749 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-literal-arg-2/9") + 750 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-literal-arg-2/10") + 751 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-literal-arg-2/11") + 752 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-literal-arg-2/12") + 753 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-literal-arg-2/13") + 754 # . epilogue + 755 89/<- %esp 5/r32/ebp + 756 5d/pop-to-ebp + 757 c3/return + 758 + 759 test-convert-function-call-with-literal-arg: + 760 # . prologue + 761 55/push-ebp + 762 89/<- %ebp 4/r32/esp + 763 # setup + 764 (clear-stream _test-input-stream) + 765 (clear-stream $_test-input-buffered-file->buffer) + 766 (clear-stream _test-output-stream) + 767 (clear-stream $_test-output-buffered-file->buffer) + 768 c7 0/subop/copy *Next-block-index 1/imm32 + 769 # + 770 (write _test-input-stream "fn main -> result/ebx: int {\n") + 771 (write _test-input-stream " result <- do-add 3 4\n") + 772 (write _test-input-stream "}\n") + 773 (write _test-input-stream "fn do-add a: int, b: int -> result/ebx: int {\n") + 774 (write _test-input-stream " result <- copy a\n") + 775 (write _test-input-stream " result <- add b\n") + 776 (write _test-input-stream "}\n") + 777 # convert + 778 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 779 (flush _test-output-buffered-file) + 780 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- + 786 # check output + 787 (check-next-stream-line-equal _test-output-stream "main:" "F - test-convert-function-call-with-literal-arg/0") + 788 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-call-with-literal-arg/1") + 789 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-call-with-literal-arg/2") + 790 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-call-with-literal-arg/3") + 791 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-call-with-literal-arg/4") + 792 (check-next-stream-line-equal _test-output-stream "$main:0x00000001:loop:" "F - test-convert-function-call-with-literal-arg/5") + 793 (check-next-stream-line-equal _test-output-stream " (do-add 3 4)" "F - test-convert-function-call-with-literal-arg/6") + 794 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-call-with-literal-arg/7") + 795 (check-next-stream-line-equal _test-output-stream "$main:0x00000001:break:" "F - test-convert-function-call-with-literal-arg/8") + 796 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-call-with-literal-arg/9") + 797 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-call-with-literal-arg/10") + 798 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-call-with-literal-arg/11") + 799 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-call-with-literal-arg/12") + 800 (check-next-stream-line-equal _test-output-stream "do-add:" "F - test-convert-function-call-with-literal-arg/13") + 801 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-call-with-literal-arg/14") + 802 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-call-with-literal-arg/15") + 803 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-call-with-literal-arg/16") + 804 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-call-with-literal-arg/17") + 805 (check-next-stream-line-equal _test-output-stream "$do-add:0x00000002:loop:" "F - test-convert-function-call-with-literal-arg/18") + 806 (check-next-stream-line-equal _test-output-stream " 8b/copy-from *(ebp+0x00000008) 0x00000003/r32" "F - test-convert-function-call-with-literal-arg/19") + 807 (check-next-stream-line-equal _test-output-stream " 03/add *(ebp+0x0000000c) 0x00000003/r32" "F - test-convert-function-call-with-literal-arg/20") + 808 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-call-with-literal-arg/21") + 809 (check-next-stream-line-equal _test-output-stream "$do-add:0x00000002:break:" "F - test-convert-function-call-with-literal-arg/22") + 810 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-call-with-literal-arg/23") + 811 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-call-with-literal-arg/24") + 812 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-call-with-literal-arg/25") + 813 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-call-with-literal-arg/26") + 814 # . epilogue + 815 89/<- %esp 5/r32/ebp + 816 5d/pop-to-ebp + 817 c3/return + 818 + 819 test-convert-function-with-local-var-in-mem: + 820 # . prologue + 821 55/push-ebp + 822 89/<- %ebp 4/r32/esp + 823 # setup + 824 (clear-stream _test-input-stream) + 825 (clear-stream $_test-input-buffered-file->buffer) + 826 (clear-stream _test-output-stream) + 827 (clear-stream $_test-output-buffered-file->buffer) + 828 c7 0/subop/copy *Next-block-index 1/imm32 + 829 # + 830 (write _test-input-stream "fn foo {\n") + 831 (write _test-input-stream " var x: int\n") + 832 (write _test-input-stream " increment x\n") + 833 (write _test-input-stream "}\n") + 834 # convert + 835 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 836 (flush _test-output-buffered-file) + 837 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- + 843 # check output + 844 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-local-var-in-mem/0") + 845 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-local-var-in-mem/1") + 846 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-local-var-in-mem/2") + 847 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-local-var-in-mem/3") + 848 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-local-var-in-mem/4") + 849 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-local-var-in-mem/5") + 850 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-local-var-in-mem/6") + 851 (check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *(ebp+0xfffffffc)" "F - test-convert-function-with-local-var-in-mem/7") + 852 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-local-var-in-mem/8") + 853 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-local-var-in-mem/9") + 854 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-local-var-in-mem/10") + 855 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-local-var-in-mem/11") + 856 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-local-var-in-mem/12") + 857 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-local-var-in-mem/13") + 858 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-local-var-in-mem/14") + 859 # . epilogue + 860 89/<- %esp 5/r32/ebp + 861 5d/pop-to-ebp + 862 c3/return + 863 + 864 test-convert-function-with-local-var-in-reg: + 865 # . prologue + 866 55/push-ebp + 867 89/<- %ebp 4/r32/esp + 868 # setup + 869 (clear-stream _test-input-stream) + 870 (clear-stream $_test-input-buffered-file->buffer) + 871 (clear-stream _test-output-stream) + 872 (clear-stream $_test-output-buffered-file->buffer) + 873 c7 0/subop/copy *Next-block-index 1/imm32 + 874 # + 875 (write _test-input-stream "fn foo {\n") + 876 (write _test-input-stream " var x/ecx: int <- copy 3\n") + 877 (write _test-input-stream " x <- increment\n") + 878 (write _test-input-stream "}\n") + 879 # convert + 880 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 881 (flush _test-output-buffered-file) + 882 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- + 888 # check output + 889 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-local-var-in-reg/0") + 890 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-local-var-in-reg/1") + 891 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-local-var-in-reg/2") + 892 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-local-var-in-reg/3") + 893 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-local-var-in-reg/4") + 894 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-local-var-in-reg/5") + 895 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-convert-function-with-local-var-in-reg/6") + 896 (check-next-stream-line-equal _test-output-stream " b9/copy-to-ecx 3/imm32" "F - test-convert-function-with-local-var-in-reg/7") + 897 (check-next-stream-line-equal _test-output-stream " 41/increment-ecx" "F - test-convert-function-with-local-var-in-reg/8") + 898 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-convert-function-with-local-var-in-reg/9") + 899 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-local-var-in-reg/10") + 900 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-local-var-in-reg/11") + 901 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-local-var-in-reg/12") + 902 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-local-var-in-reg/13") + 903 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-local-var-in-reg/14") + 904 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-local-var-in-reg/15") + 905 # . epilogue + 906 89/<- %esp 5/r32/ebp + 907 5d/pop-to-ebp + 908 c3/return + 909 + 910 test-convert-function-with-local-var-dereferenced: + 911 # . prologue + 912 55/push-ebp + 913 89/<- %ebp 4/r32/esp + 914 # setup + 915 (clear-stream _test-input-stream) + 916 (clear-stream $_test-input-buffered-file->buffer) + 917 (clear-stream _test-output-stream) + 918 (clear-stream $_test-output-buffered-file->buffer) + 919 c7 0/subop/copy *Next-block-index 1/imm32 + 920 # + 921 (write _test-input-stream "fn foo {\n") + 922 (write _test-input-stream " var x/ecx: (addr int) <- copy 0\n") + 923 (write _test-input-stream " increment *x\n") + 924 (write _test-input-stream "}\n") + 925 # convert + 926 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 927 (flush _test-output-buffered-file) + 928 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- + 934 # check output + 935 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-local-var-dereferenced/0") + 936 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-local-var-dereferenced/1") + 937 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-local-var-dereferenced/2") + 938 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-local-var-dereferenced/3") + 939 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-local-var-dereferenced/4") + 940 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-local-var-dereferenced/5") + 941 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-convert-function-with-local-var-dereferenced/6") + 942 (check-next-stream-line-equal _test-output-stream " b9/copy-to-ecx 0/imm32" "F - test-convert-function-with-local-var-dereferenced/7") + 943 (check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *ecx" "F - test-convert-function-with-local-var-dereferenced/8") + 944 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-convert-function-with-local-var-dereferenced/9") + 945 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-local-var-dereferenced/10") + 946 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-local-var-dereferenced/11") + 947 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-local-var-dereferenced/12") + 948 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-local-var-dereferenced/13") + 949 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-local-var-dereferenced/14") + 950 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-local-var-dereferenced/15") + 951 # . epilogue + 952 89/<- %esp 5/r32/ebp + 953 5d/pop-to-ebp + 954 c3/return + 955 + 956 test-convert-compare-register-with-literal: + 957 # . prologue + 958 55/push-ebp + 959 89/<- %ebp 4/r32/esp + 960 # setup + 961 (clear-stream _test-input-stream) + 962 (clear-stream $_test-input-buffered-file->buffer) + 963 (clear-stream _test-output-stream) + 964 (clear-stream $_test-output-buffered-file->buffer) + 965 c7 0/subop/copy *Next-block-index 1/imm32 + 966 # + 967 (write _test-input-stream "fn foo {\n") + 968 (write _test-input-stream " var x/ecx: int <- copy 0\n") + 969 (write _test-input-stream " compare x, 0\n") + 970 (write _test-input-stream "}\n") + 971 # convert + 972 (convert-mu _test-input-buffered-file _test-output-buffered-file) + 973 (flush _test-output-buffered-file) + 974 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- + 980 # check output + 981 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-compare-register-with-literal/0") + 982 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-compare-register-with-literal/1") + 983 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-compare-register-with-literal/2") + 984 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-compare-register-with-literal/3") + 985 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-compare-register-with-literal/4") + 986 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-compare-register-with-literal/5") + 987 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %ecx" "F - test-convert-compare-register-with-literal/6") + 988 (check-next-stream-line-equal _test-output-stream " b9/copy-to-ecx 0/imm32" "F - test-convert-compare-register-with-literal/7") + 989 (check-next-stream-line-equal _test-output-stream " 81 7/subop/compare %ecx 0/imm32" "F - test-convert-compare-register-with-literal/8") + 990 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %ecx" "F - test-convert-compare-register-with-literal/9") + 991 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-compare-register-with-literal/10") + 992 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-compare-register-with-literal/11") + 993 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-compare-register-with-literal/12") + 994 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-compare-register-with-literal/13") + 995 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-compare-register-with-literal/14") + 996 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-compare-register-with-literal/15") + 997 # . epilogue + 998 89/<- %esp 5/r32/ebp + 999 5d/pop-to-ebp +1000 c3/return +1001 +1002 test-convert-function-with-local-var-in-block: +1003 # . prologue +1004 55/push-ebp +1005 89/<- %ebp 4/r32/esp +1006 # setup +1007 (clear-stream _test-input-stream) +1008 (clear-stream $_test-input-buffered-file->buffer) +1009 (clear-stream _test-output-stream) +1010 (clear-stream $_test-output-buffered-file->buffer) +1011 c7 0/subop/copy *Next-block-index 1/imm32 +1012 # +1013 (write _test-input-stream "fn foo {\n") +1014 (write _test-input-stream " {\n") +1015 (write _test-input-stream " var x: int\n") +1016 (write _test-input-stream " increment x\n") +1017 (write _test-input-stream " }\n") +1018 (write _test-input-stream "}\n") +1019 # convert +1020 (convert-mu _test-input-buffered-file _test-output-buffered-file) +1021 (flush _test-output-buffered-file) +1022 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +1028 # check output +1029 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-local-var-in-block/0") +1030 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-local-var-in-block/1") +1031 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-local-var-in-block/2") +1032 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-local-var-in-block/3") +1033 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-local-var-in-block/4") +1034 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-local-var-in-block/5") +1035 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-local-var-in-block/6") +1036 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:" "F - test-convert-function-with-local-var-in-block/7") +1037 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-local-var-in-block/8") +1038 (check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *(ebp+0xfffffffc)" "F - test-convert-function-with-local-var-in-block/9") +1039 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-local-var-in-block/10") +1040 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-local-var-in-block/11") +1041 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:" "F - test-convert-function-with-local-var-in-block/12") +1042 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-local-var-in-block/13") +1043 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-local-var-in-block/14") +1044 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-local-var-in-block/15") +1045 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-local-var-in-block/16") +1046 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-local-var-in-block/17") +1047 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-local-var-in-block/18") +1048 # . epilogue +1049 89/<- %esp 5/r32/ebp +1050 5d/pop-to-ebp +1051 c3/return +1052 +1053 test-convert-function-with-local-var-in-named-block: +1054 # . prologue +1055 55/push-ebp +1056 89/<- %ebp 4/r32/esp +1057 # setup +1058 (clear-stream _test-input-stream) +1059 (clear-stream $_test-input-buffered-file->buffer) +1060 (clear-stream _test-output-stream) +1061 (clear-stream $_test-output-buffered-file->buffer) +1062 c7 0/subop/copy *Next-block-index 1/imm32 +1063 # +1064 (write _test-input-stream "fn foo {\n") +1065 (write _test-input-stream " $bar: {\n") +1066 (write _test-input-stream " var x: int\n") +1067 (write _test-input-stream " increment x\n") +1068 (write _test-input-stream " }\n") +1069 (write _test-input-stream "}\n") +1070 # convert +1071 (convert-mu _test-input-buffered-file _test-output-buffered-file) +1072 (flush _test-output-buffered-file) +1073 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +1079 # check output +1080 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-local-var-in-named-block/0") +1081 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-local-var-in-named-block/1") +1082 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-local-var-in-named-block/2") +1083 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-local-var-in-named-block/3") +1084 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-local-var-in-named-block/4") +1085 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-local-var-in-named-block/5") +1086 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-local-var-in-named-block/6") +1087 (check-next-stream-line-equal _test-output-stream "$bar:loop:" "F - test-convert-function-with-local-var-in-named-block/7") +1088 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-local-var-in-named-block/8") +1089 (check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *(ebp+0xfffffffc)" "F - test-convert-function-with-local-var-in-named-block/9") +1090 (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/10") +1091 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-local-var-in-named-block/11") +1092 (check-next-stream-line-equal _test-output-stream "$bar:break:" "F - test-convert-function-with-local-var-in-named-block/12") +1093 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-local-var-in-named-block/13") +1094 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-local-var-in-named-block/14") +1095 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-local-var-in-named-block/15") +1096 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-local-var-in-named-block/16") +1097 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-local-var-in-named-block/17") +1098 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-local-var-in-named-block/18") +1099 # . epilogue +1100 89/<- %esp 5/r32/ebp +1101 5d/pop-to-ebp +1102 c3/return +1103 +1104 test-convert-function-with-branches-in-block: +1105 # . prologue +1106 55/push-ebp +1107 89/<- %ebp 4/r32/esp +1108 # setup +1109 (clear-stream _test-input-stream) +1110 (clear-stream $_test-input-buffered-file->buffer) +1111 (clear-stream _test-output-stream) +1112 (clear-stream $_test-output-buffered-file->buffer) +1113 c7 0/subop/copy *Next-block-index 1/imm32 +1114 # +1115 (write _test-input-stream "fn foo x: int {\n") +1116 (write _test-input-stream " {\n") +1117 (write _test-input-stream " break-if->=\n") +1118 (write _test-input-stream " loop-if-addr<\n") +1119 (write _test-input-stream " increment x\n") +1120 (write _test-input-stream " loop\n") +1121 (write _test-input-stream " }\n") +1122 (write _test-input-stream "}\n") +1123 # convert +1124 (convert-mu _test-input-buffered-file _test-output-buffered-file) +1125 (flush _test-output-buffered-file) +1126 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +1132 # check output +1133 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-branches-in-block/0") +1134 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-branches-in-block/1") +1135 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-branches-in-block/2") +1136 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-branches-in-block/3") +1137 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-branches-in-block/4") +1138 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-branches-in-block/5") +1139 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-branches-in-block/6") +1140 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:" "F - test-convert-function-with-branches-in-block/7") +1141 (check-next-stream-line-equal _test-output-stream " 0f 8d/jump-if->= break/disp32" "F - test-convert-function-with-branches-in-block/8") +1142 (check-next-stream-line-equal _test-output-stream " 0f 82/jump-if-addr< loop/disp32" "F - test-convert-function-with-branches-in-block/9") +1143 (check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *(ebp+0x00000008)" "F - test-convert-function-with-branches-in-block/10") +1144 (check-next-stream-line-equal _test-output-stream " e9/jump loop/disp32" "F - test-convert-function-with-branches-in-block/11") +1145 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-branches-in-block/12") +1146 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:" "F - test-convert-function-with-branches-in-block/13") +1147 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-branches-in-block/14") +1148 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-branches-in-block/15") +1149 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-branches-in-block/16") +1150 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-branches-in-block/17") +1151 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-branches-in-block/18") +1152 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-branches-in-block/19") +1153 # . epilogue +1154 89/<- %esp 5/r32/ebp +1155 5d/pop-to-ebp +1156 c3/return +1157 +1158 test-convert-function-with-branches-in-named-block: +1159 # . prologue +1160 55/push-ebp +1161 89/<- %ebp 4/r32/esp +1162 # setup +1163 (clear-stream _test-input-stream) +1164 (clear-stream $_test-input-buffered-file->buffer) +1165 (clear-stream _test-output-stream) +1166 (clear-stream $_test-output-buffered-file->buffer) +1167 c7 0/subop/copy *Next-block-index 1/imm32 +1168 # +1169 (write _test-input-stream "fn foo x: int {\n") +1170 (write _test-input-stream " $bar: {\n") +1171 (write _test-input-stream " break-if->= $bar\n") +1172 (write _test-input-stream " loop-if-addr< $bar\n") +1173 (write _test-input-stream " increment x\n") +1174 (write _test-input-stream " loop\n") +1175 (write _test-input-stream " }\n") +1176 (write _test-input-stream "}\n") +1177 # convert +1178 (convert-mu _test-input-buffered-file _test-output-buffered-file) +1179 (flush _test-output-buffered-file) +1180 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +1186 # check output +1187 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-branches-in-named-block/0") +1188 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-branches-in-named-block/1") +1189 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-branches-in-named-block/2") +1190 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-branches-in-named-block/3") +1191 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-branches-in-named-block/4") +1192 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-branches-in-named-block/5") +1193 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-branches-in-named-block/6") +1194 (check-next-stream-line-equal _test-output-stream "$bar:loop:" "F - test-convert-function-with-branches-in-named-block/7") +1195 (check-next-stream-line-equal _test-output-stream " 0f 8d/jump-if->= $bar:break/disp32" "F - test-convert-function-with-branches-in-named-block/8") +1196 (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/9") +1197 (check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *(ebp+0x00000008)" "F - test-convert-function-with-branches-in-named-block/10") +1198 (check-next-stream-line-equal _test-output-stream " e9/jump loop/disp32" "F - test-convert-function-with-branches-in-named-block/11") +1199 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-branches-in-named-block/12") +1200 (check-next-stream-line-equal _test-output-stream "$bar:break:" "F - test-convert-function-with-branches-in-named-block/13") +1201 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-branches-in-named-block/14") +1202 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-branches-in-named-block/15") +1203 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-branches-in-named-block/16") +1204 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-branches-in-named-block/17") +1205 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-branches-in-named-block/18") +1206 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-branches-in-named-block/19") +1207 # . epilogue +1208 89/<- %esp 5/r32/ebp +1209 5d/pop-to-ebp +1210 c3/return +1211 +1212 test-convert-function-with-var-in-nested-block: +1213 # . prologue +1214 55/push-ebp +1215 89/<- %ebp 4/r32/esp +1216 # setup +1217 (clear-stream _test-input-stream) +1218 (clear-stream $_test-input-buffered-file->buffer) +1219 (clear-stream _test-output-stream) +1220 (clear-stream $_test-output-buffered-file->buffer) +1221 c7 0/subop/copy *Next-block-index 1/imm32 +1222 # +1223 (write _test-input-stream "fn foo x: int {\n") +1224 (write _test-input-stream " {\n") +1225 (write _test-input-stream " {\n") +1226 (write _test-input-stream " var x: int\n") +1227 (write _test-input-stream " increment x\n") +1228 (write _test-input-stream " }\n") +1229 (write _test-input-stream " }\n") +1230 (write _test-input-stream "}\n") +1231 # convert +1232 (convert-mu _test-input-buffered-file _test-output-buffered-file) +1233 (flush _test-output-buffered-file) +1234 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +1240 # check output +1241 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-var-in-nested-block/0") +1242 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-var-in-nested-block/1") +1243 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-var-in-nested-block/2") +1244 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-var-in-nested-block/3") +1245 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-var-in-nested-block/4") +1246 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-var-in-nested-block/5") +1247 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-var-in-nested-block/6") +1248 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:" "F - test-convert-function-with-var-in-nested-block/7") +1249 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-var-in-nested-block/8") +1250 (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:" "F - test-convert-function-with-var-in-nested-block/9") +1251 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-var-in-nested-block/10") +1252 (check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *(ebp+0xfffffffc)" "F - test-convert-function-with-var-in-nested-block/11") +1253 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-var-in-nested-block/12") +1254 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-var-in-nested-block/13") +1255 (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:" "F - test-convert-function-with-var-in-nested-block/14") +1256 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-var-in-nested-block/15") +1257 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:" "F - test-convert-function-with-var-in-nested-block/16") +1258 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-var-in-nested-block/17") +1259 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-var-in-nested-block/18") +1260 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-var-in-nested-block/19") +1261 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-var-in-nested-block/20") +1262 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-var-in-nested-block/21") +1263 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-var-in-nested-block/22") +1264 # . epilogue +1265 89/<- %esp 5/r32/ebp +1266 5d/pop-to-ebp +1267 c3/return +1268 +1269 test-convert-function-with-multiple-vars-in-nested-blocks: +1270 # . prologue +1271 55/push-ebp +1272 89/<- %ebp 4/r32/esp +1273 # setup +1274 (clear-stream _test-input-stream) +1275 (clear-stream $_test-input-buffered-file->buffer) +1276 (clear-stream _test-output-stream) +1277 (clear-stream $_test-output-buffered-file->buffer) +1278 c7 0/subop/copy *Next-block-index 1/imm32 +1279 # +1280 (write _test-input-stream "fn foo x: int {\n") +1281 (write _test-input-stream " {\n") +1282 (write _test-input-stream " var x/eax: int <- copy 0\n") +1283 (write _test-input-stream " {\n") +1284 (write _test-input-stream " var y: int\n") +1285 (write _test-input-stream " x <- add y\n") +1286 (write _test-input-stream " }\n") +1287 (write _test-input-stream " }\n") +1288 (write _test-input-stream "}\n") +1289 # convert +1290 (convert-mu _test-input-buffered-file _test-output-buffered-file) +1291 (flush _test-output-buffered-file) +1292 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +1298 # check output +1299 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-multiple-vars-in-nested-blocks/0") +1300 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-multiple-vars-in-nested-blocks/1") +1301 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-multiple-vars-in-nested-blocks/2") +1302 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-multiple-vars-in-nested-blocks/3") +1303 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-multiple-vars-in-nested-blocks/4") +1304 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-multiple-vars-in-nested-blocks/5") +1305 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-multiple-vars-in-nested-blocks/6") +1306 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:" "F - test-convert-function-with-multiple-vars-in-nested-blocks/7") +1307 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-function-with-multiple-vars-in-nested-blocks/8") +1308 (check-next-stream-line-equal _test-output-stream " b8/copy-to-eax 0/imm32" "F - test-convert-function-with-multiple-vars-in-nested-blocks/9") +1309 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-multiple-vars-in-nested-blocks/10") +1310 (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:" "F - test-convert-function-with-multiple-vars-in-nested-blocks/11") +1311 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-multiple-vars-in-nested-blocks/12") +1312 (check-next-stream-line-equal _test-output-stream " 03/add *(ebp+0xfffffff8) 0x00000000/r32" "F - test-convert-function-with-multiple-vars-in-nested-blocks/13") +1313 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-multiple-vars-in-nested-blocks/14") +1314 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-multiple-vars-in-nested-blocks/15") +1315 (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:" "F - test-convert-function-with-multiple-vars-in-nested-blocks/16") +1316 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-function-with-multiple-vars-in-nested-blocks/17") +1317 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-multiple-vars-in-nested-blocks/18") +1318 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:" "F - test-convert-function-with-multiple-vars-in-nested-blocks/19") +1319 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-multiple-vars-in-nested-blocks/20") +1320 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-multiple-vars-in-nested-blocks/21") +1321 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-multiple-vars-in-nested-blocks/22") +1322 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-multiple-vars-in-nested-blocks/23") +1323 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-multiple-vars-in-nested-blocks/24") +1324 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-multiple-vars-in-nested-blocks/25") +1325 # . epilogue +1326 89/<- %esp 5/r32/ebp +1327 5d/pop-to-ebp +1328 c3/return +1329 +1330 test-convert-function-with-branches-and-local-vars: +1331 # A conditional 'break' after a 'var' in a block is converted into a +1332 # nested block that performs all necessary cleanup before jumping. This +1333 # results in some ugly code duplication. +1334 # . prologue +1335 55/push-ebp +1336 89/<- %ebp 4/r32/esp +1337 # setup +1338 (clear-stream _test-input-stream) +1339 (clear-stream $_test-input-buffered-file->buffer) +1340 (clear-stream _test-output-stream) +1341 (clear-stream $_test-output-buffered-file->buffer) +1342 c7 0/subop/copy *Next-block-index 1/imm32 +1343 # +1344 (write _test-input-stream "fn foo {\n") +1345 (write _test-input-stream " {\n") +1346 (write _test-input-stream " var x: int\n") +1347 (write _test-input-stream " break-if->=\n") +1348 (write _test-input-stream " increment x\n") +1349 (write _test-input-stream " }\n") +1350 (write _test-input-stream "}\n") +1351 # convert +1352 (convert-mu _test-input-buffered-file _test-output-buffered-file) +1353 (flush _test-output-buffered-file) +1354 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +1360 # check output +1361 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-branches-and-local-vars/0") +1362 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-branches-and-local-vars/1") +1363 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-branches-and-local-vars/2") +1364 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-branches-and-local-vars/3") +1365 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-branches-and-local-vars/4") +1366 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-branches-and-local-vars/5") +1367 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-branches-and-local-vars/6") +1368 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:" "F - test-convert-function-with-branches-and-local-vars/7") +1369 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-branches-and-local-vars/8") +1370 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-branches-and-local-vars/9") +1371 (check-next-stream-line-equal _test-output-stream " 0f 8c/jump-if-< break/disp32" "F - test-convert-function-with-branches-and-local-vars/10") +1372 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-branches-and-local-vars/11") +1373 (check-next-stream-line-equal _test-output-stream " e9/jump $foo:0x00000002:break/disp32" "F - test-convert-function-with-branches-and-local-vars/12") +1374 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-branches-and-local-vars/13") +1375 (check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *(ebp+0xfffffffc)" "F - test-convert-function-with-branches-and-local-vars/14") +1376 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-branches-and-local-vars/15") +1377 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-branches-and-local-vars/16") +1378 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:" "F - test-convert-function-with-branches-and-local-vars/17") +1379 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-branches-and-local-vars/18") +1380 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-branches-and-local-vars/19") +1381 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-branches-and-local-vars/20") +1382 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-branches-and-local-vars/21") +1383 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-branches-and-local-vars/22") +1384 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-branches-and-local-vars/23") +1385 # . epilogue +1386 89/<- %esp 5/r32/ebp +1387 5d/pop-to-ebp +1388 c3/return +1389 +1390 test-convert-function-with-conditional-loops-and-local-vars: +1391 # A conditional 'loop' after a 'var' in a block is converted into a nested +1392 # block that performs all necessary cleanup before jumping. This results +1393 # in some ugly code duplication. +1394 # . prologue +1395 55/push-ebp +1396 89/<- %ebp 4/r32/esp +1397 # setup +1398 (clear-stream _test-input-stream) +1399 (clear-stream $_test-input-buffered-file->buffer) +1400 (clear-stream _test-output-stream) +1401 (clear-stream $_test-output-buffered-file->buffer) +1402 c7 0/subop/copy *Next-block-index 1/imm32 +1403 # +1404 (write _test-input-stream "fn foo {\n") +1405 (write _test-input-stream " {\n") +1406 (write _test-input-stream " var x: int\n") +1407 (write _test-input-stream " loop-if->=\n") +1408 (write _test-input-stream " increment x\n") +1409 (write _test-input-stream " }\n") +1410 (write _test-input-stream "}\n") +1411 # convert +1412 (convert-mu _test-input-buffered-file _test-output-buffered-file) +1413 (flush _test-output-buffered-file) +1414 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +1420 # check output +1421 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-conditional-loops-and-local-vars/0") +1422 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-conditional-loops-and-local-vars/1") +1423 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-conditional-loops-and-local-vars/2") +1424 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-conditional-loops-and-local-vars/3") +1425 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-conditional-loops-and-local-vars/4") +1426 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-conditional-loops-and-local-vars/5") +1427 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-conditional-loops-and-local-vars/6") +1428 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:" "F - test-convert-function-with-conditional-loops-and-local-vars/7") +1429 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-conditional-loops-and-local-vars/8") +1430 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-conditional-loops-and-local-vars/9") +1431 (check-next-stream-line-equal _test-output-stream " 0f 8c/jump-if-< break/disp32" "F - test-convert-function-with-conditional-loops-and-local-vars/10") +1432 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-conditional-loops-and-local-vars/11") +1433 (check-next-stream-line-equal _test-output-stream " e9/jump $foo:0x00000002:loop/disp32" "F - test-convert-function-with-conditional-loops-and-local-vars/12") +1434 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-conditional-loops-and-local-vars/13") +1435 (check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *(ebp+0xfffffffc)" "F - test-convert-function-with-conditional-loops-and-local-vars/14") +1436 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-conditional-loops-and-local-vars/15") +1437 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-conditional-loops-and-local-vars/16") +1438 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:" "F - test-convert-function-with-conditional-loops-and-local-vars/17") +1439 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-conditional-loops-and-local-vars/18") +1440 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-conditional-loops-and-local-vars/19") +1441 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-conditional-loops-and-local-vars/20") +1442 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-conditional-loops-and-local-vars/21") +1443 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-conditional-loops-and-local-vars/22") +1444 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-conditional-loops-and-local-vars/23") +1445 # . epilogue +1446 89/<- %esp 5/r32/ebp +1447 5d/pop-to-ebp +1448 c3/return +1449 +1450 test-convert-function-with-unconditional-loops-and-local-vars: +1451 # An unconditional 'loop' after a 'var' in a block is emitted _after_ the +1452 # regular block cleanup. Any instructions after 'loop' are dead and +1453 # therefore skipped. +1454 # . prologue +1455 55/push-ebp +1456 89/<- %ebp 4/r32/esp +1457 # setup +1458 (clear-stream _test-input-stream) +1459 (clear-stream $_test-input-buffered-file->buffer) +1460 (clear-stream _test-output-stream) +1461 (clear-stream $_test-output-buffered-file->buffer) +1462 c7 0/subop/copy *Next-block-index 1/imm32 +1463 # +1464 (write _test-input-stream "fn foo {\n") +1465 (write _test-input-stream " {\n") +1466 (write _test-input-stream " var x: int\n") +1467 (write _test-input-stream " loop\n") +1468 (write _test-input-stream " increment x\n") +1469 (write _test-input-stream " }\n") +1470 (write _test-input-stream "}\n") +1471 # convert +1472 (convert-mu _test-input-buffered-file _test-output-buffered-file) +1473 (flush _test-output-buffered-file) +1474 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +1480 # check output +1481 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-unconditional-loops-and-local-vars/0") +1482 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-unconditional-loops-and-local-vars/1") +1483 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-unconditional-loops-and-local-vars/2") +1484 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-unconditional-loops-and-local-vars/3") +1485 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-unconditional-loops-and-local-vars/4") +1486 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-unconditional-loops-and-local-vars/5") +1487 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-unconditional-loops-and-local-vars/6") +1488 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:" "F - test-convert-function-with-unconditional-loops-and-local-vars/7") +1489 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-unconditional-loops-and-local-vars/8") +1490 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-unconditional-loops-and-local-vars/9") +1491 (check-next-stream-line-equal _test-output-stream " e9/jump loop/disp32" "F - test-convert-function-with-unconditional-loops-and-local-vars/10") +1492 # not emitted: ff 0/subop/increment *(ebp+0xfffffffc) +1493 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-unconditional-loops-and-local-vars/11") +1494 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:" "F - test-convert-function-with-unconditional-loops-and-local-vars/12") +1495 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-unconditional-loops-and-local-vars/13") +1496 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-unconditional-loops-and-local-vars/14") +1497 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-unconditional-loops-and-local-vars/15") +1498 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-unconditional-loops-and-local-vars/16") +1499 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-unconditional-loops-and-local-vars/17") +1500 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-unconditional-loops-and-local-vars/18") +1501 # . epilogue +1502 89/<- %esp 5/r32/ebp +1503 5d/pop-to-ebp +1504 c3/return +1505 +1506 test-convert-function-with-branches-and-loops-and-local-vars: +1507 # . prologue +1508 55/push-ebp +1509 89/<- %ebp 4/r32/esp +1510 # setup +1511 (clear-stream _test-input-stream) +1512 (clear-stream $_test-input-buffered-file->buffer) +1513 (clear-stream _test-output-stream) +1514 (clear-stream $_test-output-buffered-file->buffer) +1515 c7 0/subop/copy *Next-block-index 1/imm32 +1516 # +1517 (write _test-input-stream "fn foo {\n") +1518 (write _test-input-stream " {\n") +1519 (write _test-input-stream " var x: int\n") +1520 (write _test-input-stream " break-if->=\n") +1521 (write _test-input-stream " increment x\n") +1522 (write _test-input-stream " loop\n") +1523 (write _test-input-stream " }\n") +1524 (write _test-input-stream "}\n") +1525 # convert +1526 (convert-mu _test-input-buffered-file _test-output-buffered-file) +1527 (flush _test-output-buffered-file) +1528 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +1534 # check output +1535 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-branches-and-loops-and-local-vars/0") +1536 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-branches-and-loops-and-local-vars/1") +1537 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-branches-and-loops-and-local-vars/2") +1538 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-branches-and-loops-and-local-vars/3") +1539 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-branches-and-loops-and-local-vars/4") +1540 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-branches-and-loops-and-local-vars/5") +1541 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-branches-and-loops-and-local-vars/6") +1542 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:" "F - test-convert-function-with-branches-and-loops-and-local-vars/7") +1543 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-branches-and-loops-and-local-vars/8") +1544 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-branches-and-loops-and-local-vars/9") +1545 (check-next-stream-line-equal _test-output-stream " 0f 8c/jump-if-< break/disp32" "F - test-convert-function-with-branches-and-loops-and-local-vars/10") +1546 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-branches-and-loops-and-local-vars/11") +1547 (check-next-stream-line-equal _test-output-stream " e9/jump $foo:0x00000002:break/disp32" "F - test-convert-function-with-branches-and-loops-and-local-vars/12") +1548 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-branches-and-loops-and-local-vars/13") +1549 (check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *(ebp+0xfffffffc)" "F - test-convert-function-with-branches-and-loops-and-local-vars/14") +1550 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-branches-and-loops-and-local-vars/15") +1551 (check-next-stream-line-equal _test-output-stream " e9/jump loop/disp32" "F - test-convert-function-with-branches-and-loops-and-local-vars/16") +1552 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-branches-and-loops-and-local-vars/17") +1553 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:" "F - test-convert-function-with-branches-and-loops-and-local-vars/18") +1554 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-branches-and-loops-and-local-vars/19") +1555 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-branches-and-loops-and-local-vars/20") +1556 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-branches-and-loops-and-local-vars/21") +1557 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-branches-and-loops-and-local-vars/22") +1558 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-branches-and-loops-and-local-vars/23") +1559 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-branches-and-loops-and-local-vars/24") +1560 # . epilogue +1561 89/<- %esp 5/r32/ebp +1562 5d/pop-to-ebp +1563 c3/return +1564 +1565 test-convert-function-with-nonlocal-branches-and-loops-and-local-vars: +1566 # . prologue +1567 55/push-ebp +1568 89/<- %ebp 4/r32/esp +1569 # setup +1570 (clear-stream _test-input-stream) +1571 (clear-stream $_test-input-buffered-file->buffer) +1572 (clear-stream _test-output-stream) +1573 (clear-stream $_test-output-buffered-file->buffer) +1574 c7 0/subop/copy *Next-block-index 1/imm32 +1575 # +1576 (write _test-input-stream "fn foo {\n") +1577 (write _test-input-stream " a: {\n") +1578 (write _test-input-stream " var x: int\n") +1579 (write _test-input-stream " {\n") +1580 (write _test-input-stream " var y: int\n") +1581 (write _test-input-stream " break-if->= a\n") +1582 (write _test-input-stream " increment x\n") +1583 (write _test-input-stream " loop\n") +1584 (write _test-input-stream " }\n") +1585 (write _test-input-stream " }\n") +1586 (write _test-input-stream "}\n") +1587 # convert +1588 (convert-mu _test-input-buffered-file _test-output-buffered-file) +1589 (flush _test-output-buffered-file) +1590 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +1596 # check output +1597 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/0") +1598 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/1") +1599 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/2") +1600 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/3") +1601 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/4") +1602 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/5") +1603 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/6") +1604 (check-next-stream-line-equal _test-output-stream "a:loop:" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/7") +1605 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/8") +1606 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/9") +1607 (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/10") +1608 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/11") +1609 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/12") +1610 (check-next-stream-line-equal _test-output-stream " 0f 8c/jump-if-< break/disp32" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/13") +1611 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/14") +1612 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/15") +1613 (check-next-stream-line-equal _test-output-stream " e9/jump a:break/disp32" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/16") +1614 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/17") +1615 (check-next-stream-line-equal _test-output-stream " ff 0/subop/increment *(ebp+0xfffffffc)" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/18") +1616 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/19") +1617 (check-next-stream-line-equal _test-output-stream " e9/jump loop/disp32" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/20") +1618 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/21") +1619 (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/22") +1620 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/23") +1621 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/24") +1622 (check-next-stream-line-equal _test-output-stream "a:break:" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/25") +1623 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/26") +1624 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/27") +1625 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/28") +1626 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/29") +1627 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/30") +1628 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/31") +1629 # . epilogue +1630 89/<- %esp 5/r32/ebp +1631 5d/pop-to-ebp +1632 c3/return +1633 +1634 test-convert-function-with-nonlocal-unconditional-break-and-local-vars: +1635 # . prologue +1636 55/push-ebp +1637 89/<- %ebp 4/r32/esp +1638 # setup +1639 (clear-stream _test-input-stream) +1640 (clear-stream $_test-input-buffered-file->buffer) +1641 (clear-stream _test-output-stream) +1642 (clear-stream $_test-output-buffered-file->buffer) +1643 c7 0/subop/copy *Next-block-index 1/imm32 +1644 # +1645 (write _test-input-stream "fn foo {\n") +1646 (write _test-input-stream " a: {\n") +1647 (write _test-input-stream " var x: int\n") +1648 (write _test-input-stream " {\n") +1649 (write _test-input-stream " var y: int\n") +1650 (write _test-input-stream " break a\n") +1651 (write _test-input-stream " increment x\n") +1652 (write _test-input-stream " }\n") +1653 (write _test-input-stream " }\n") +1654 (write _test-input-stream "}\n") +1655 # convert +1656 (convert-mu _test-input-buffered-file _test-output-buffered-file) +1657 (flush _test-output-buffered-file) +1658 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +1664 # check output +1665 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/0") +1666 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/1") +1667 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/2") +1668 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/3") +1669 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/4") +1670 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/5") +1671 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/6") +1672 (check-next-stream-line-equal _test-output-stream "a:loop:" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/7") +1673 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/8") +1674 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/9") +1675 (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/10") +1676 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/11") +1677 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/12") +1678 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/13") +1679 (check-next-stream-line-equal _test-output-stream " e9/jump a:break/disp32" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/14") +1680 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/15") +1681 (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/16") +1682 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/17") +1683 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/18") +1684 (check-next-stream-line-equal _test-output-stream "a:break:" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/19") +1685 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/20") +1686 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/21") +1687 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/22") +1688 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/23") +1689 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/24") +1690 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/25") +1691 # . epilogue +1692 89/<- %esp 5/r32/ebp +1693 5d/pop-to-ebp +1694 c3/return +1695 +1696 test-convert-function-with-unconditional-break-and-local-vars: +1697 # . prologue +1698 55/push-ebp +1699 89/<- %ebp 4/r32/esp +1700 # setup +1701 (clear-stream _test-input-stream) +1702 (clear-stream $_test-input-buffered-file->buffer) +1703 (clear-stream _test-output-stream) +1704 (clear-stream $_test-output-buffered-file->buffer) +1705 c7 0/subop/copy *Next-block-index 1/imm32 +1706 # +1707 (write _test-input-stream "fn foo {\n") +1708 (write _test-input-stream " {\n") +1709 (write _test-input-stream " var x: int\n") +1710 (write _test-input-stream " {\n") +1711 (write _test-input-stream " var y: int\n") +1712 (write _test-input-stream " break\n") +1713 (write _test-input-stream " increment x\n") +1714 (write _test-input-stream " }\n") +1715 (write _test-input-stream " }\n") +1716 (write _test-input-stream "}\n") +1717 # convert +1718 (convert-mu _test-input-buffered-file _test-output-buffered-file) +1719 (flush _test-output-buffered-file) +1720 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +1726 # check output +1727 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-unconditional-break-and-local-vars/0") +1728 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-unconditional-break-and-local-vars/1") +1729 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-unconditional-break-and-local-vars/2") +1730 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-unconditional-break-and-local-vars/3") +1731 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-unconditional-break-and-local-vars/4") +1732 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-unconditional-break-and-local-vars/5") +1733 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-unconditional-break-and-local-vars/6") +1734 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:" "F - test-convert-function-with-unconditional-break-and-local-vars/7") +1735 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-unconditional-break-and-local-vars/8") +1736 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-unconditional-break-and-local-vars/9") +1737 (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:" "F - test-convert-function-with-unconditional-break-and-local-vars/10") +1738 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-unconditional-break-and-local-vars/11") +1739 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-unconditional-break-and-local-vars/12") +1740 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-unconditional-break-and-local-vars/13") +1741 (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:" "F - test-convert-function-with-unconditional-break-and-local-vars/14") +1742 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-unconditional-break-and-local-vars/15") +1743 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-unconditional-break-and-local-vars/16") +1744 (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:" "F - test-convert-function-with-unconditional-break-and-local-vars/17") +1745 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-unconditional-break-and-local-vars/18") +1746 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-unconditional-break-and-local-vars/19") +1747 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-unconditional-break-and-local-vars/20") +1748 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-unconditional-break-and-local-vars/21") +1749 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-unconditional-break-and-local-vars/22") +1750 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-unconditional-break-and-local-vars/23") +1751 # . epilogue +1752 89/<- %esp 5/r32/ebp +1753 5d/pop-to-ebp +1754 c3/return +1755 +1756 test-convert-function-with-nonlocal-unconditional-loop-and-local-vars: +1757 # . prologue +1758 55/push-ebp +1759 89/<- %ebp 4/r32/esp +1760 # setup +1761 (clear-stream _test-input-stream) +1762 (clear-stream $_test-input-buffered-file->buffer) +1763 (clear-stream _test-output-stream) +1764 (clear-stream $_test-output-buffered-file->buffer) +1765 c7 0/subop/copy *Next-block-index 1/imm32 +1766 # +1767 (write _test-input-stream "fn foo {\n") +1768 (write _test-input-stream " a: {\n") +1769 (write _test-input-stream " var x: int\n") +1770 (write _test-input-stream " {\n") +1771 (write _test-input-stream " var y: int\n") +1772 (write _test-input-stream " loop a\n") +1773 (write _test-input-stream " increment x\n") +1774 (write _test-input-stream " }\n") +1775 (write _test-input-stream " }\n") +1776 (write _test-input-stream "}\n") +1777 # convert +1778 (convert-mu _test-input-buffered-file _test-output-buffered-file) +1779 (flush _test-output-buffered-file) +1780 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +1786 # check output +1787 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/0") +1788 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/1") +1789 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/2") +1790 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/3") +1791 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/4") +1792 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/5") +1793 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/6") +1794 (check-next-stream-line-equal _test-output-stream "a:loop:" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/7") +1795 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/8") +1796 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/9") +1797 (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/10") +1798 (check-next-stream-line-equal _test-output-stream " 68/push 0/imm32" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/11") +1799 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/12") +1800 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/13") +1801 (check-next-stream-line-equal _test-output-stream " e9/jump a:loop/disp32" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/14") +1802 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/15") +1803 (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/16") +1804 (check-next-stream-line-equal _test-output-stream " 81 0/subop/add %esp 0x00000004/imm32" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/17") +1805 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/18") +1806 (check-next-stream-line-equal _test-output-stream "a:break:" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/19") +1807 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/20") +1808 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/21") +1809 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/22") +1810 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/23") +1811 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/24") +1812 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/25") +1813 # . epilogue +1814 89/<- %esp 5/r32/ebp +1815 5d/pop-to-ebp +1816 c3/return +1817 +1818 test-convert-length-of-array: +1819 # . prologue +1820 55/push-ebp +1821 89/<- %ebp 4/r32/esp +1822 # setup +1823 (clear-stream _test-input-stream) +1824 (clear-stream $_test-input-buffered-file->buffer) +1825 (clear-stream _test-output-stream) +1826 (clear-stream $_test-output-buffered-file->buffer) +1827 c7 0/subop/copy *Next-block-index 1/imm32 +1828 # +1829 (write _test-input-stream "fn foo a: (addr array int) {\n") +1830 (write _test-input-stream " var b/eax: (addr array int) <- copy a\n") +1831 (write _test-input-stream " var c/eax: int <- length b\n") +1832 (write _test-input-stream "}\n") +1833 # convert +1834 (convert-mu _test-input-buffered-file _test-output-buffered-file) +1835 (flush _test-output-buffered-file) +1836 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +1842 # check output +1843 (check-next-stream-line-equal _test-output-stream "foo:" "F - test-convert-length-of-array/0") +1844 (check-next-stream-line-equal _test-output-stream " # . prologue" "F - test-convert-length-of-array/1") +1845 (check-next-stream-line-equal _test-output-stream " 55/push-ebp" "F - test-convert-length-of-array/2") +1846 (check-next-stream-line-equal _test-output-stream " 89/<- %ebp 4/r32/esp" "F - test-convert-length-of-array/3") +1847 (check-next-stream-line-equal _test-output-stream " {" "F - test-convert-length-of-array/4") +1848 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:" "F - test-convert-length-of-array/5") +1849 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-length-of-array/6") +1850 (check-next-stream-line-equal _test-output-stream " 8b/copy-from *(ebp+0x00000008) 0x00000000/r32" "F - test-convert-length-of-array/7") +1851 (check-next-stream-line-equal _test-output-stream " ff 6/subop/push %eax" "F - test-convert-length-of-array/8") +1852 (check-next-stream-line-equal _test-output-stream " 8b/copy-from *eax 0x00000000/r32" "F - test-convert-length-of-array/9") +1853 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-length-of-array/10") +1854 (check-next-stream-line-equal _test-output-stream " 8f 0/subop/pop %eax" "F - test-convert-length-of-array/11") +1855 (check-next-stream-line-equal _test-output-stream " }" "F - test-convert-length-of-array/12") +1856 (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:" "F - test-convert-length-of-array/13") +1857 (check-next-stream-line-equal _test-output-stream " # . epilogue" "F - test-convert-length-of-array/14") +1858 (check-next-stream-line-equal _test-output-stream " 89/<- %esp 5/r32/ebp" "F - test-convert-length-of-array/15") +1859 (check-next-stream-line-equal _test-output-stream " 5d/pop-to-ebp" "F - test-convert-length-of-array/16") +1860 (check-next-stream-line-equal _test-output-stream " c3/return" "F - test-convert-length-of-array/17") +1861 # . epilogue +1862 89/<- %esp 5/r32/ebp +1863 5d/pop-to-ebp +1864 c3/return +1865 +1866 ####################################################### +1867 # Parsing +1868 ####################################################### +1869 +1870 parse-mu: # in: (addr buffered-file) +1871 # pseudocode +1872 # var curr-function: (addr (handle function)) = Program +1873 # var line: (stream byte 512) +1874 # var word-slice: slice +1875 # while true # line loop +1876 # clear-stream(line) +1877 # read-line-buffered(in, line) +1878 # if (line->write == 0) break # end of file +1879 # word-slice = next-mu-token(line) +1880 # if slice-empty?(word-slice) # end of line +1881 # continue +1882 # else if slice-starts-with?(word-slice, "#") # comment +1883 # continue # end of line +1884 # else if slice-equal(word-slice, "fn") +1885 # var new-function: (handle function) = allocate(function) +1886 # var vars: (stack (addr var) 256) +1887 # populate-mu-function-header(in, new-function, vars) +1888 # populate-mu-function-body(in, new-function, vars) +1889 # assert(vars->top == 0) +1890 # *curr-function = new-function +1891 # curr-function = &new-function->next +1892 # else +1893 # abort() +1894 # +1895 # . prologue +1896 55/push-ebp +1897 89/<- %ebp 4/r32/esp +1898 # . save registers +1899 50/push-eax +1900 51/push-ecx +1901 52/push-edx +1902 53/push-ebx +1903 57/push-edi +1904 # var line/ecx: (stream byte 512) +1905 81 5/subop/subtract %esp 0x200/imm32 +1906 68/push 0x200/imm32/length +1907 68/push 0/imm32/read +1908 68/push 0/imm32/write +1909 89/<- %ecx 4/r32/esp +1910 # var word-slice/edx: slice +1911 68/push 0/imm32/end +1912 68/push 0/imm32/start +1913 89/<- %edx 4/r32/esp +1914 # var curr-function/edi: (addr (handle function)) = Program +1915 bf/copy-to-edi Program/imm32 +1916 # var vars/ebx: (stack (addr var) 256) +1917 81 5/subop/subtract %esp 0x400/imm32 +1918 68/push 0x400/imm32/length +1919 68/push 0/imm32/top +1920 89/<- %ebx 4/r32/esp +1921 { +1922 $parse-mu:line-loop: +1923 (clear-stream %ecx) +1924 (read-line-buffered *(ebp+8) %ecx) +1925 # if (line->write == 0) break +1926 81 7/subop/compare *ecx 0/imm32 +1927 0f 84/jump-if-= break/disp32 +1928 +-- 6 lines: #? # dump line ------------------------------------------------------------------------------------------------------------------------------------------------------ +1934 (next-mu-token %ecx %edx) +1935 # if slice-empty?(word-slice) continue +1936 (slice-empty? %edx) +1937 3d/compare-eax-and 0/imm32/false +1938 0f 85/jump-if-!= loop/disp32 +1939 # if (*word-slice->start == "#") continue +1940 # . eax = *word-slice->start +1941 8b/-> *edx 0/r32/eax +1942 8a/copy-byte *eax 0/r32/AL +1943 81 4/subop/and %eax 0xff/imm32 +1944 # . if (eax == '#') continue +1945 3d/compare-eax-and 0x23/imm32/hash +1946 0f 84/jump-if-= loop/disp32 +1947 # if (slice-equal?(word-slice, "fn")) parse a function +1948 { +1949 $parse-mu:fn: +1950 (slice-equal? %edx "fn") +1951 3d/compare-eax-and 0/imm32/false +1952 0f 84/jump-if-= break/disp32 +1953 # var new-function/eax: (handle function) = populate-mu-function(in, new-function, vars) +1954 (allocate Heap *Function-size) # => eax +1955 (zero-out %eax *Function-size) +1956 (clear-stack %ebx) +1957 (populate-mu-function-header %ecx %eax %ebx) +1958 (populate-mu-function-body *(ebp+8) %eax %ebx) +1959 # *curr-function = new-function +1960 89/<- *edi 0/r32/eax +1961 # curr-function = &new-function->next +1962 8d/address-> *(eax+0x14) 7/r32/edi # Function-next +1963 e9/jump $parse-mu:line-loop/disp32 +1964 } +1965 # otherwise abort +1966 e9/jump $parse-mu:error1/disp32 +1967 } # end line loop +1968 $parse-mu:end: +1969 # . reclaim locals +1970 81 0/subop/add %esp 0x630/imm32 +1971 # . restore registers +1972 5f/pop-to-edi +1973 5b/pop-to-ebx +1974 5a/pop-to-edx +1975 59/pop-to-ecx +1976 58/pop-to-eax +1977 # . epilogue +1978 89/<- %esp 5/r32/ebp +1979 5d/pop-to-ebp +1980 c3/return +1981 +1982 $parse-mu:error1: +1983 # error("unexpected top-level command: " word-slice "\n") +1984 (write-buffered Stderr "unexpected top-level command: ") +1985 (write-slice-buffered Stderr %edx) +1986 (write-buffered Stderr "\n") +1987 (flush Stderr) +1988 # . syscall(exit, 1) +1989 bb/copy-to-ebx 1/imm32 +1990 b8/copy-to-eax 1/imm32/exit +1991 cd/syscall 0x80/imm8 +1992 # never gets here +1993 +1994 $parse-mu:error2: +1995 # error(vars->top " vars not reclaimed after fn '" new-function->name "'\n") +1996 (print-int32-buffered Stderr *ebx) +1997 (write-buffered Stderr " vars not reclaimed after fn '") +1998 (write-slice-buffered Stderr *eax) # Function-name +1999 (write-buffered Stderr "'\n") +2000 (flush Stderr) +2001 # . syscall(exit, 1) +2002 bb/copy-to-ebx 1/imm32 +2003 b8/copy-to-eax 1/imm32/exit +2004 cd/syscall 0x80/imm8 +2005 # never gets here +2006 +2007 # scenarios considered: +2008 # ✗ fn foo # no block +2009 # ✓ fn foo { +2010 # ✗ fn foo { { +2011 # ✗ fn foo { } +2012 # ✗ fn foo { } { +2013 # ✗ fn foo x { +2014 # ✗ fn foo x: { +2015 # ✓ fn foo x: int { +2016 # ✓ fn foo x: int { +2017 # ✓ fn foo x: int -> y/eax: int { +2018 populate-mu-function-header: # first-line: (addr stream byte), out: (handle function), vars: (addr stack (handle var)) +2019 # pseudocode: +2020 # var name: slice +2021 # next-mu-token(first-line, name) +2022 # assert(name not in '{' '}' '->') +2023 # out->name = slice-to-string(name) +2024 # var next-offset: int = 8 +2025 # ## inouts +2026 # while true +2027 # ## name +2028 # name = next-mu-token(first-line) +2029 # if (name == '{') goto done +2030 # if (name == '->') break +2031 # assert(name != '}') +2032 # var v: (handle var) = parse-var-with-type(name, first-line) +2033 # assert(v->register == null) +2034 # v->stack-offset = next-offset +2035 # next-offset += size-of(v) +2036 # # v->block-depth is implicitly 0 +2037 # out->inouts = append(out->inouts, v) +2038 # push(vars, v) +2039 # ## outputs +2040 # while true +2041 # ## name +2042 # name = next-mu-token(first-line) +2043 # assert(name not in '{' '}' '->') +2044 # var v: (handle var) = parse-var-with-type(name, first-line) +2045 # assert(v->register != null) +2046 # out->outputs = append(out->outputs, v) +2047 # done: +2048 # +2049 # . prologue +2050 55/push-ebp +2051 89/<- %ebp 4/r32/esp +2052 # . save registers +2053 50/push-eax +2054 51/push-ecx +2055 52/push-edx +2056 53/push-ebx +2057 57/push-edi +2058 # edi = out +2059 8b/-> *(ebp+0xc) 7/r32/edi +2060 # var word-slice/ecx: slice +2061 68/push 0/imm32/end +2062 68/push 0/imm32/start +2063 89/<- %ecx 4/r32/esp +2064 # var next-offset/edx = 8 +2065 ba/copy-to-edx 8/imm32 +2066 # read function name +2067 (next-mu-token *(ebp+8) %ecx) +2068 # error checking +2069 # TODO: error if name starts with 'break' or 'loop' +2070 # if (word-slice == '{') abort +2071 (slice-equal? %ecx "{") # => eax +2072 3d/compare-eax-and 0/imm32/false +2073 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 +2074 # if (word-slice == '->') abort +2075 (slice-equal? %ecx "->") # => eax +2076 3d/compare-eax-and 0/imm32/false +2077 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 +2078 # if (word-slice == '}') abort +2079 (slice-equal? %ecx "}") # => eax +2080 3d/compare-eax-and 0/imm32/false +2081 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 +2082 # save function name +2083 (slice-to-string Heap %ecx) # => eax +2084 89/<- *edi 0/r32/eax # Function-name +2085 # initialize default subx-name as well +2086 89/<- *(edi+4) 0/r32/eax # Function-subx-name +2087 # save function inouts +2088 { +2089 $populate-mu-function-header:check-for-inout: +2090 (next-mu-token *(ebp+8) %ecx) +2091 # if (word-slice == '{') goto done +2092 (slice-equal? %ecx "{") # => eax +2093 3d/compare-eax-and 0/imm32/false +2094 0f 85/jump-if-!= $populate-mu-function-header:done/disp32 +2095 # if (word-slice == '->') break +2096 (slice-equal? %ecx "->") # => eax +2097 3d/compare-eax-and 0/imm32/false +2098 0f 85/jump-if-!= break/disp32 +2099 # if (word-slice == '}') abort +2100 (slice-equal? %ecx "}") # => eax +2101 3d/compare-eax-and 0/imm32/false +2102 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 +2103 # var v/ebx: (handle var) = parse-var-with-type(word-slice, first-line) +2104 (parse-var-with-type %ecx *(ebp+8)) # => eax +2105 89/<- %ebx 0/r32/eax +2106 # assert(v->register == null) +2107 81 7/subop/compare *(ebx+0x10) 0/imm32 # Var-register +2108 0f 85/jump-if-!= $populate-mu-function-header:error2/disp32 +2109 # v->stack-offset = next-offset +2110 89/<- *(ebx+0xc) 2/r32/edx # Var-stack-offset +2111 # next-offset += size-of(v) +2112 (size-of %ebx) # => eax +2113 01/add %edx 0/r32/eax +2114 # v->block-depth is implicitly 0 +2115 # +2116 (append-list Heap %ebx *(edi+8)) # Function-inouts => eax +2117 89/<- *(edi+8) 0/r32/eax # Function-inouts +2118 (push *(ebp+0x10) %ebx) +2119 # +2120 e9/jump loop/disp32 +2121 } +2122 # save function outputs +2123 { +2124 $populate-mu-function-header:check-for-out: +2125 (next-mu-token *(ebp+8) %ecx) +2126 # if (word-slice == '{') break +2127 (slice-equal? %ecx "{") # => eax +2128 3d/compare-eax-and 0/imm32/false +2129 0f 85/jump-if-!= break/disp32 +2130 # if (word-slice == '->') abort +2131 (slice-equal? %ecx "->") # => eax +2132 3d/compare-eax-and 0/imm32/false +2133 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 +2134 # if (word-slice == '}') abort +2135 (slice-equal? %ecx "}") # => eax +2136 3d/compare-eax-and 0/imm32/false +2137 0f 85/jump-if-!= $populate-mu-function-header:error1/disp32 +2138 # +2139 (parse-var-with-type %ecx *(ebp+8)) # => eax +2140 89/<- %ebx 0/r32/eax +2141 # assert(var->register != null) +2142 81 7/subop/compare *(ebx+0x10) 0/imm32 # Var-register +2143 0f 84/jump-if-= $populate-mu-function-header:error3/disp32 +2144 (append-list Heap %ebx *(edi+0xc)) # Function-outputs => eax +2145 89/<- *(edi+0xc) 0/r32/eax # Function-outputs +2146 e9/jump loop/disp32 +2147 } +2148 $populate-mu-function-header:done: +2149 (check-no-tokens-left *(ebp+8)) +2150 $populate-mu-function-header:end: +2151 # . reclaim locals +2152 81 0/subop/add %esp 8/imm32 +2153 # . restore registers +2154 5f/pop-to-edi +2155 5b/pop-to-ebx +2156 5a/pop-to-edx +2157 59/pop-to-ecx +2158 58/pop-to-eax +2159 # . epilogue +2160 89/<- %esp 5/r32/ebp +2161 5d/pop-to-ebp +2162 c3/return +2163 +2164 $populate-mu-function-header:error1: +2165 # error("function header not in form 'fn <name> {'") +2166 (write-buffered Stderr "function header not in form 'fn <name> [inouts] [-> outputs] {' -- '") +2167 (flush Stderr) +2168 (rewind-stream *(ebp+8)) +2169 (write-stream 2 *(ebp+8)) +2170 (write-buffered Stderr "'\n") +2171 (flush Stderr) +2172 # . syscall(exit, 1) +2173 bb/copy-to-ebx 1/imm32 +2174 b8/copy-to-eax 1/imm32/exit +2175 cd/syscall 0x80/imm8 +2176 # never gets here +2177 +2178 $populate-mu-function-header:error2: +2179 # error("function input '" var "' cannot be in a register") +2180 (write-buffered Stderr "function input '") +2181 (write-buffered Stderr *ebx) # Var-name +2182 (write-buffered Stderr "' cannot be in a register") +2183 (flush Stderr) +2184 # . syscall(exit, 1) +2185 bb/copy-to-ebx 1/imm32 +2186 b8/copy-to-eax 1/imm32/exit +2187 cd/syscall 0x80/imm8 +2188 # never gets here +2189 +2190 $populate-mu-function-header:error3: +2191 # error("function input '" var "' must be in a register") +2192 (write-buffered Stderr "function input '") +2193 (write-buffered Stderr *eax) # Var-name +2194 (write-buffered Stderr " must be in a register'") +2195 (flush Stderr) +2196 (rewind-stream *(ebp+8)) +2197 (write-stream 2 *(ebp+8)) +2198 (write-buffered Stderr "'\n") +2199 (flush Stderr) +2200 # . syscall(exit, 1) +2201 bb/copy-to-ebx 1/imm32 +2202 b8/copy-to-eax 1/imm32/exit +2203 cd/syscall 0x80/imm8 +2204 # never gets here +2205 +2206 test-function-header-with-arg: +2207 # . prologue +2208 55/push-ebp +2209 89/<- %ebp 4/r32/esp +2210 # setup +2211 (clear-stream _test-input-stream) +2212 (write _test-input-stream "foo n: int {\n") +2213 # var result/ecx: function +2214 2b/subtract-> *Function-size 4/r32/esp +2215 89/<- %ecx 4/r32/esp +2216 (zero-out %ecx *Function-size) +2217 # var vars/ebx: (stack (addr var) 16) +2218 81 5/subop/subtract %esp 0x10/imm32 +2219 68/push 0x10/imm32/length +2220 68/push 0/imm32/top +2221 89/<- %ebx 4/r32/esp +2222 # convert +2223 (populate-mu-function-header _test-input-stream %ecx %ebx) +2224 # check result +2225 (check-strings-equal *ecx "foo" "F - test-function-header-with-arg/name") # Function-name +2226 # edx: (handle list var) = result->inouts +2227 8b/-> *(ecx+8) 2/r32/edx # Function-inouts +2228 # ebx: (handle var) = result->inouts->value +2229 8b/-> *edx 3/r32/ebx # List-value +2230 (check-strings-equal *ebx "n" "F - test-function-header-with-arg/inout:0") # Var-name +2231 8b/-> *(ebx+4) 3/r32/ebx # Var-type +2232 (check-ints-equal *ebx 1 "F - test-function-header-with-arg/inout:0/type:0") # Tree-left +2233 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-arg/inout:0/type:1") # Tree-right +2234 # . epilogue +2235 89/<- %esp 5/r32/ebp +2236 5d/pop-to-ebp +2237 c3/return +2238 +2239 test-function-header-with-multiple-args: +2240 # . prologue +2241 55/push-ebp +2242 89/<- %ebp 4/r32/esp +2243 # setup +2244 (clear-stream _test-input-stream) +2245 (write _test-input-stream "foo a: int, b: int c: int {\n") +2246 # result/ecx: (handle function) +2247 2b/subtract-> *Function-size 4/r32/esp +2248 89/<- %ecx 4/r32/esp +2249 (zero-out %ecx *Function-size) +2250 # var vars/ebx: (stack (addr var) 16) +2251 81 5/subop/subtract %esp 0x10/imm32 +2252 68/push 0x10/imm32/length +2253 68/push 0/imm32/top +2254 89/<- %ebx 4/r32/esp +2255 # convert +2256 (populate-mu-function-header _test-input-stream %ecx %ebx) +2257 # check result +2258 (check-strings-equal *ecx "foo") # Function-name +2259 # edx: (handle list var) = result->inouts +2260 8b/-> *(ecx+8) 2/r32/edx # Function-inouts +2261 $test-function-header-with-multiple-args:inout0: +2262 # ebx: (handle var) = result->inouts->value +2263 8b/-> *edx 3/r32/ebx # List-value +2264 (check-strings-equal *ebx "a" "F - test-function-header-with-multiple-args/inout:0") # Var-name +2265 8b/-> *(ebx+4) 3/r32/ebx # Var-type +2266 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args/inout:0/type:0") # Tree-left +2267 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args/inout:0/type:1") # Tree-right +2268 # edx = result->inouts->next +2269 8b/-> *(edx+4) 2/r32/edx # List-next +2270 $test-function-header-with-multiple-args:inout1: +2271 # ebx = result->inouts->next->value +2272 8b/-> *edx 3/r32/ebx # List-value +2273 (check-strings-equal *ebx "b" "F - test-function-header-with-multiple-args/inout:1") # Var-name +2274 8b/-> *(ebx+4) 3/r32/ebx # Var-type +2275 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args/inout:1/type:0") # Tree-left +2276 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args/inout:1/type:1") # Tree-right +2277 # edx = result->inouts->next->next +2278 8b/-> *(edx+4) 2/r32/edx # List-next +2279 $test-function-header-with-multiple-args:inout2: +2280 # ebx = result->inouts->next->next->value +2281 8b/-> *edx 3/r32/ebx # List-value +2282 (check-strings-equal *ebx "c" "F - test-function-header-with-multiple-args/inout:2") # Var-name +2283 8b/-> *(ebx+4) 3/r32/ebx # Var-type +2284 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args/inout:2/type:0") # Tree-left +2285 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args/inout:2/type:1") # Tree-right +2286 # . epilogue +2287 89/<- %esp 5/r32/ebp +2288 5d/pop-to-ebp +2289 c3/return +2290 +2291 test-function-with-multiple-args-and-outputs: +2292 # . prologue +2293 55/push-ebp +2294 89/<- %ebp 4/r32/esp +2295 # setup +2296 (clear-stream _test-input-stream) +2297 (write _test-input-stream "foo a: int, b: int, c: int -> x/ecx: int y/edx: int {\n") +2298 # result/ecx: (handle function) +2299 2b/subtract-> *Function-size 4/r32/esp +2300 89/<- %ecx 4/r32/esp +2301 (zero-out %ecx *Function-size) +2302 # var vars/ebx: (stack (addr var) 16) +2303 81 5/subop/subtract %esp 0x10/imm32 +2304 68/push 0x10/imm32/length +2305 68/push 0/imm32/top +2306 89/<- %ebx 4/r32/esp +2307 # convert +2308 (populate-mu-function-header _test-input-stream %ecx %ebx) +2309 # check result +2310 (check-strings-equal *ecx "foo") # Function-name +2311 # edx: (handle list var) = result->inouts +2312 8b/-> *(ecx+8) 2/r32/edx # Function-inouts +2313 # ebx: (handle var) = result->inouts->value +2314 8b/-> *edx 3/r32/ebx # List-value +2315 (check-strings-equal *ebx "a" "F - test-function-header-with-multiple-args-and-outputs/inout:0") # Var-name +2316 8b/-> *(ebx+4) 3/r32/ebx # Var-type +2317 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args-and-outputs/inout:0/type:0") # Tree-left +2318 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args-and-outputs/inout:0/type:1") # Tree-right +2319 # edx = result->inouts->next +2320 8b/-> *(edx+4) 2/r32/edx # List-next +2321 # ebx = result->inouts->next->value +2322 8b/-> *edx 3/r32/ebx # List-value +2323 (check-strings-equal *ebx "b" "F - test-function-header-with-multiple-args-and-outputs/inout:1") # Var-name +2324 8b/-> *(ebx+4) 3/r32/ebx # Var-type +2325 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args-and-outputs/inout:1/type:0") # Tree-left +2326 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args-and-outputs/inout:1/type:1") # Tree-right +2327 # edx = result->inouts->next->next +2328 8b/-> *(edx+4) 2/r32/edx # List-next +2329 # ebx = result->inouts->next->next->value +2330 8b/-> *edx 3/r32/ebx # List-value +2331 (check-strings-equal *ebx "c" "F - test-function-header-with-multiple-args-and-outputs/inout:2") # Var-name +2332 8b/-> *(ebx+4) 3/r32/ebx # Var-type +2333 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args-and-outputs/inout:2/type:0") # Tree-left +2334 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args-and-outputs/inout:2/type:1") # Tree-right +2335 # edx: (handle list var) = result->outputs +2336 8b/-> *(ecx+0xc) 2/r32/edx # Function-outputs +2337 # ebx: (handle var) = result->outputs->value +2338 8b/-> *edx 3/r32/ebx # List-value +2339 (check-strings-equal *ebx "x" "F - test-function-header-with-multiple-args-and-outputs/output:0") # Var-name +2340 (check-strings-equal *(ebx+0x10) "ecx" "F - test-function-header-with-multiple-args-and-outputs/output:0/register") # Var-register +2341 8b/-> *(ebx+4) 3/r32/ebx # Var-type +2342 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args-and-outputs/output:0/type:1") # Tree-left +2343 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args-and-outputs/output:0/type:1") # Tree-right +2344 # edx = result->outputs->next +2345 8b/-> *(edx+4) 2/r32/edx # List-next +2346 # ebx = result->outputs->next->value +2347 8b/-> *edx 3/r32/ebx # List-value +2348 (check-strings-equal *ebx "y" "F - test-function-header-with-multiple-args-and-outputs/output:1") # Var-name +2349 (check-strings-equal *(ebx+0x10) "edx" "F - test-function-header-with-multiple-args-and-outputs/output:0/register") # Var-register +2350 8b/-> *(ebx+4) 3/r32/ebx # Var-type +2351 (check-ints-equal *ebx 1 "F - test-function-header-with-multiple-args-and-outputs/output:1/type:1") # Tree-left +2352 (check-ints-equal *(ebx+4) 0 "F - test-function-header-with-multiple-args-and-outputs/output:1/type:1") # Tree-right +2353 # . epilogue +2354 89/<- %esp 5/r32/ebp +2355 5d/pop-to-ebp +2356 c3/return +2357 +2358 # format for variables with types +2359 # x: int +2360 # x: int, +2361 # x/eax: int +2362 # x/eax: int, +2363 # ignores at most one trailing comma +2364 # WARNING: modifies name +2365 parse-var-with-type: # name: (addr slice), first-line: (addr stream byte) -> result/eax: (handle var) +2366 # pseudocode: +2367 # var v: (handle var) = allocate(Heap, Var-size) +2368 # var s: slice +2369 # if (!slice-ends-with(name, ":")) +2370 # abort +2371 # --name->end to skip ':' +2372 # next-token-from-slice(name->start, name->end, '/', s) +2373 # v->name = slice-to-string(s) +2374 # ## register +2375 # next-token-from-slice(s->end, name->end, '/', s) +2376 # if (!slice-empty?(s)) +2377 # v->register = slice-to-string(s) +2378 # ## type +2379 # var type: (handle tree type-id) = parse-type(first-line) +2380 # v->type = type +2381 # return v +2382 # +2383 # . prologue +2384 55/push-ebp +2385 89/<- %ebp 4/r32/esp +2386 # . save registers +2387 51/push-ecx +2388 52/push-edx +2389 53/push-ebx +2390 56/push-esi +2391 57/push-edi +2392 # esi = name +2393 8b/-> *(ebp+8) 6/r32/esi +2394 # if (!slice-ends-with?(name, ":")) abort +2395 8b/-> *(esi+4) 1/r32/ecx # Slice-end +2396 49/decrement-ecx +2397 8a/copy-byte *ecx 1/r32/CL +2398 81 4/subop/and %ecx 0xff/imm32 +2399 81 7/subop/compare %ecx 0x3a/imm32/colon +2400 0f 85/jump-if-!= $parse-var-with-type:abort/disp32 +2401 # --name->end to skip ':' +2402 ff 1/subop/decrement *(esi+4) +2403 # var result/edi: (handle var) = allocate(Heap, Var-size) +2404 (allocate Heap *Var-size) # => eax +2405 (zero-out %eax *Var-size) +2406 89/<- %edi 0/r32/eax +2407 # var s/ecx: slice +2408 68/push 0/imm32/end +2409 68/push 0/imm32/start +2410 89/<- %ecx 4/r32/esp +2411 $parse-var-with-type:save-name: +2412 # save v->name +2413 (next-token-from-slice *esi *(esi+4) 0x2f %ecx) # Slice-start, Slice-end, '/' +2414 # . end/edx = s->end +2415 8b/-> *(ecx+4) 2/r32/edx +2416 $parse-var-with-type:write-name: +2417 (slice-to-string Heap %ecx) # => eax +2418 89/<- *edi 0/r32/eax # Var-name +2419 # save v->register +2420 $parse-var-with-type:save-register: +2421 (next-token-from-slice %edx *(esi+4) 0x2f %ecx) # end, name->end, '/' +2422 # if (!slice-empty?(s)) v->register = slice-to-string(s) +2423 { +2424 $parse-var-with-type:write-register: +2425 (slice-empty? %ecx) # => eax +2426 3d/compare-eax-and 0/imm32/false +2427 75/jump-if-!= break/disp8 +2428 (slice-to-string Heap %ecx) +2429 89/<- *(edi+0x10) 0/r32/eax # Var-register +2430 } +2431 $parse-var-with-type:save-type: +2432 (parse-type Heap *(ebp+0xc)) # => eax +2433 89/<- *(edi+4) 0/r32/eax # Var-type +2434 $parse-var-with-type:end: +2435 # return result +2436 89/<- %eax 7/r32/edi +2437 # . reclaim locals +2438 81 0/subop/add %esp 8/imm32 +2439 # . restore registers +2440 5f/pop-to-edi +2441 5e/pop-to-esi +2442 5b/pop-to-ebx +2443 5a/pop-to-edx +2444 59/pop-to-ecx +2445 # . epilogue +2446 89/<- %esp 5/r32/ebp +2447 5d/pop-to-ebp +2448 c3/return +2449 +2450 $parse-var-with-type:abort: +2451 # error("var should have form 'name: type' in '" line "'\n") +2452 (write-buffered Stderr "var should have form 'name: type' in '") +2453 (flush Stderr) +2454 (rewind-stream *(ebp+0xc)) +2455 (write-stream 2 *(ebp+0xc)) +2456 (write-buffered Stderr "'\n") +2457 (flush Stderr) +2458 # . syscall(exit, 1) +2459 bb/copy-to-ebx 1/imm32 +2460 b8/copy-to-eax 1/imm32/exit +2461 cd/syscall 0x80/imm8 +2462 # never gets here +2463 +2464 parse-type: # ad: (address allocation-descriptor), in: (addr stream byte) -> result/eax: (handle tree type-id) +2465 # pseudocode: +2466 # var s: slice = next-mu-token(in) +2467 # assert s != "" +2468 # assert s != "->" +2469 # assert s != "{" +2470 # assert s != "}" +2471 # if s == ")" +2472 # return 0 +2473 # result = allocate(Tree) +2474 # zero-out(result, *Tree-size) +2475 # if s != "(" +2476 # result->left = pos-slice(Type-id, s) +2477 # return +2478 # result->left = parse-type(ad, in) +2479 # result->right = parse-type-tree(ad, in) +2480 # +2481 # . prologue +2482 55/push-ebp +2483 89/<- %ebp 4/r32/esp +2484 # . save registers +2485 51/push-ecx +2486 52/push-edx +2487 # var s/ecx: slice +2488 68/push 0/imm32 +2489 68/push 0/imm32 +2490 89/<- %ecx 4/r32/esp +2491 # s = next-mu-token(in) +2492 (next-mu-token *(ebp+0xc) %ecx) +2493 #? (write-buffered Stderr "tok: ") +2494 #? (write-slice-buffered Stderr %ecx) +2495 #? (write-buffered Stderr "$\n") +2496 #? (flush Stderr) +2497 # assert s != "" +2498 (slice-equal? %ecx "") +2499 3d/compare-eax-and 0/imm32/false +2500 0f 85/jump-if-!= $parse-type:abort/disp32 +2501 # assert s != "{" +2502 (slice-equal? %ecx "{") +2503 3d/compare-eax-and 0/imm32/false +2504 0f 85/jump-if-!= $parse-type:abort/disp32 +2505 # assert s != "}" +2506 (slice-equal? %ecx "}") +2507 3d/compare-eax-and 0/imm32/false +2508 0f 85/jump-if-!= $parse-type:abort/disp32 +2509 # assert s != "->" +2510 (slice-equal? %ecx "->") +2511 3d/compare-eax-and 0/imm32/false +2512 0f 85/jump-if-!= $parse-type:abort/disp32 +2513 # if (s == ")") return 0 +2514 (slice-equal? %ecx ")") +2515 3d/compare-eax-and 0/imm32/false +2516 b8/copy-to-eax 0/imm32 +2517 0f 85/jump-if-!= $parse-type:end/disp32 +2518 # var result/edx: (handle tree type-id) +2519 (allocate *(ebp+8) *Tree-size) # => eax +2520 (zero-out %eax *Tree-size) +2521 89/<- %edx 0/r32/eax +2522 { +2523 # if (s != "(") break +2524 (slice-equal? %ecx "(") +2525 3d/compare-eax-and 0/imm32/false +2526 75/jump-if-!= break/disp8 +2527 # result->left = pos-slice(Type-id, s) +2528 (pos-slice Type-id %ecx) +2529 #? (write-buffered Stderr "=> {") +2530 #? (print-int32-buffered Stderr %eax) +2531 #? (write-buffered Stderr ", 0}\n") +2532 #? (flush Stderr) +2533 89/<- *edx 0/r32/eax # Tree-left +2534 e9/jump $parse-type:return-edx/disp32 +2535 } +2536 # otherwise s == "(" +2537 # result->left = parse-type(ad, in) +2538 (parse-type *(ebp+8) *(ebp+0xc)) +2539 #? (write-buffered Stderr "=> {") +2540 #? (print-int32-buffered Stderr %eax) +2541 89/<- *edx 0/r32/eax # Tree-left +2542 # result->right = parse-type-tree(ad, in) +2543 (parse-type-tree *(ebp+8) *(ebp+0xc)) +2544 #? (write-buffered Stderr Space) +2545 #? (print-int32-buffered Stderr %eax) +2546 #? (write-buffered Stderr "}\n") +2547 #? (flush Stderr) +2548 89/<- *(edx+4) 0/r32/eax # Tree-right +2549 $parse-type:return-edx: +2550 89/<- %eax 2/r32/edx +2551 $parse-type:end: +2552 # . reclaim locals +2553 81 0/subop/add %esp 8/imm32 +2554 # . restore registers +2555 5a/pop-to-edx +2556 59/pop-to-ecx +2557 # . epilogue +2558 89/<- %esp 5/r32/ebp +2559 5d/pop-to-ebp +2560 c3/return +2561 +2562 $parse-type:abort: +2563 # error("unexpected token when parsing type: '" s "'\n") +2564 (write-buffered Stderr "unexpected token when parsing type: '") +2565 (write-slice-buffered Stderr %ecx) +2566 (write-buffered Stderr "'\n") +2567 (flush Stderr) +2568 # . syscall(exit, 1) +2569 bb/copy-to-ebx 1/imm32 +2570 b8/copy-to-eax 1/imm32/exit +2571 cd/syscall 0x80/imm8 +2572 # never gets here +2573 +2574 parse-type-tree: # ad: (address allocation-descriptor), in: (addr stream byte) -> result/eax: (handle tree type-id) +2575 # pseudocode: +2576 # var tmp: (handle tree type-id) = parse-type(ad, in) +2577 # if tmp == 0 +2578 # return 0 +2579 # result = allocate(Tree) +2580 # zero-out(result, *Tree-size) +2581 # result->left = tmp +2582 # result->right = parse-type-tree(ad, in) +2583 # +2584 # . prologue +2585 55/push-ebp +2586 89/<- %ebp 4/r32/esp +2587 # . save registers +2588 51/push-ecx +2589 52/push-edx +2590 # var tmp/eax: (handle tree type-id) = parse-type(ad, in) +2591 (parse-type *(ebp+8) *(ebp+0xc)) +2592 # if (tmp == 0) return tmp +2593 3d/compare-eax-and 0/imm32 +2594 74/jump-if-= $parse-type-tree:end/disp8 +2595 # var tmp2/ecx = tmp +2596 89/<- %ecx 0/r32/eax +2597 # var result/edx: (handle tree type-id) +2598 (allocate *(ebp+8) *Tree-size) # => eax +2599 (zero-out %eax *Tree-size) +2600 89/<- %edx 0/r32/eax +2601 # result->left = tmp2 +2602 89/<- *edx 1/r32/ecx # Tree-left +2603 # result->right = parse-type-tree(ad, in) +2604 (parse-type-tree *(ebp+8) *(ebp+0xc)) +2605 89/<- *(edx+4) 0/r32/eax # Tree-right +2606 $parse-type-tree:return-edx: +2607 89/<- %eax 2/r32/edx +2608 $parse-type-tree:end: +2609 # . restore registers +2610 5a/pop-to-edx +2611 59/pop-to-ecx +2612 # . epilogue +2613 89/<- %esp 5/r32/ebp +2614 5d/pop-to-ebp +2615 c3/return +2616 +2617 next-mu-token: # in: (addr stream byte), out: (addr slice) +2618 # pseudocode: +2619 # start: +2620 # skip-chars-matching-whitespace(in) +2621 # if in->read >= in->write # end of in +2622 # out = {0, 0} +2623 # return +2624 # out->start = &in->data[in->read] +2625 # var curr-byte/eax: byte = in->data[in->read] +2626 # if curr->byte == ',' # comment token +2627 # ++in->read +2628 # goto start +2629 # if curr-byte == '#' # comment +2630 # goto done # treat as eof +2631 # if curr-byte == '"' # string literal +2632 # skip-string(in) +2633 # goto done # no metadata +2634 # if curr-byte == '(' +2635 # ++in->read +2636 # goto done +2637 # if curr-byte == ')' +2638 # ++in->read +2639 # goto done +2640 # # read a word +2641 # while true +2642 # if in->read >= in->write +2643 # break +2644 # curr-byte = in->data[in->read] +2645 # if curr-byte == ' ' +2646 # break +2647 # if curr-byte == '\r' +2648 # break +2649 # if curr-byte == '\n' +2650 # break +2651 # if curr-byte == '(' +2652 # break +2653 # if curr-byte == ')' +2654 # break +2655 # if curr-byte == ',' +2656 # break +2657 # ++in->read +2658 # done: +2659 # out->end = &in->data[in->read] +2660 # +2661 # . prologue +2662 55/push-ebp +2663 89/<- %ebp 4/r32/esp +2664 # . save registers +2665 50/push-eax +2666 51/push-ecx +2667 56/push-esi +2668 57/push-edi +2669 # esi = in +2670 8b/-> *(ebp+8) 6/r32/esi +2671 # edi = out +2672 8b/-> *(ebp+0xc) 7/r32/edi +2673 $next-mu-token:start: +2674 (skip-chars-matching-whitespace %esi) +2675 $next-mu-token:check0: +2676 # if (in->read >= in->write) return out = {0, 0} +2677 # . ecx = in->read +2678 8b/-> *(esi+4) 1/r32/ecx +2679 # . if (ecx >= in->write) return out = {0, 0} +2680 3b/compare 1/r32/ecx *esi +2681 c7 0/subop/copy *edi 0/imm32 +2682 c7 0/subop/copy *(edi+4) 0/imm32 +2683 0f 8d/jump-if->= $next-mu-token:end/disp32 +2684 # out->start = &in->data[in->read] +2685 8d/copy-address *(esi+ecx+0xc) 0/r32/eax +2686 89/<- *edi 0/r32/eax +2687 # var curr-byte/eax: byte = in->data[in->read] +2688 31/xor %eax 0/r32/eax +2689 8a/copy-byte *(esi+ecx+0xc) 0/r32/AL +2690 { +2691 $next-mu-token:check-for-comma: +2692 # if (curr-byte != ',') break +2693 3d/compare-eax-and 0x2c/imm32/comma +2694 75/jump-if-!= break/disp8 +2695 # ++in->read +2696 ff 0/subop/increment *(esi+4) +2697 # restart +2698 e9/jump $next-mu-token:start/disp32 +2699 } +2700 { +2701 $next-mu-token:check-for-comment: +2702 # if (curr-byte != '#') break +2703 3d/compare-eax-and 0x23/imm32/pound +2704 75/jump-if-!= break/disp8 +2705 # return eof +2706 e9/jump $next-mu-token:done/disp32 +2707 } +2708 { +2709 $next-mu-token:check-for-string-literal: +2710 # if (curr-byte != '"') break +2711 3d/compare-eax-and 0x22/imm32/dquote +2712 75/jump-if-!= break/disp8 +2713 (skip-string %esi) +2714 # return +2715 e9/jump $next-mu-token:done/disp32 +2716 } +2717 { +2718 $next-mu-token:check-for-open-paren: +2719 # if (curr-byte != '(') break +2720 3d/compare-eax-and 0x28/imm32/open-paren +2721 75/jump-if-!= break/disp8 2722 # ++in->read 2723 ff 0/subop/increment *(esi+4) -2724 # -2725 e9/jump loop/disp32 +2724 # return +2725 e9/jump $next-mu-token:done/disp32 2726 } -2727 $next-mu-token:done: -2728 # out->end = &in->data[in->read] -2729 8b/-> *(esi+4) 1/r32/ecx -2730 8d/copy-address *(esi+ecx+0xc) 0/r32/eax -2731 89/<- *(edi+4) 0/r32/eax -2732 $next-mu-token:end: -2733 # . restore registers -2734 5f/pop-to-edi -2735 5e/pop-to-esi -2736 59/pop-to-ecx -2737 58/pop-to-eax -2738 # . epilogue -2739 89/<- %esp 5/r32/ebp -2740 5d/pop-to-ebp -2741 c3/return -2742 -2743 # return the index in an array of strings matching 's' -2744 # index is denominated in elements, not bytes -2745 pos-slice: # arr: (addr stream (handle array byte)), s: (addr slice) -> index/eax: int -2746 # . prologue -2747 55/push-ebp -2748 89/<- %ebp 4/r32/esp -2749 # . save registers -2750 51/push-ecx -2751 52/push-edx -2752 53/push-ebx -2753 56/push-esi -2754 #? (write-buffered Stderr "pos-slice: ") -2755 #? (write-slice-buffered Stderr *(ebp+0xc)) -2756 #? (write-buffered Stderr "\n") -2757 #? (flush Stderr) -2758 # esi = arr -2759 8b/-> *(ebp+8) 6/r32/esi -2760 # var index/ecx: int = 0 -2761 b9/copy-to-ecx 0/imm32 -2762 # var curr/edx: (addr (addr array byte)) = arr->data -2763 8d/copy-address *(esi+0xc) 2/r32/edx -2764 # var max/ebx: (addr (addr array byte)) = &arr->data[arr->write] -2765 8b/-> *esi 3/r32/ebx -2766 8d/copy-address *(esi+ebx+0xc) 3/r32/ebx -2767 { -2768 #? (write-buffered Stderr " ") -2769 #? (print-int32-buffered Stderr %ecx) -2770 #? (write-buffered Stderr "\n") -2771 #? (flush Stderr) -2772 # if (curr >= max) return -1 -2773 39/compare %edx 3/r32/ebx -2774 b8/copy-to-eax -1/imm32 -2775 73/jump-if-addr>= $pos-slice:end/disp8 -2776 # if (slice-equal?(s, *curr)) break -2777 (slice-equal? *(ebp+0xc) *edx) # => eax -2778 3d/compare-eax-and 0/imm32/false -2779 75/jump-if-!= break/disp8 -2780 # ++index -2781 41/increment-ecx -2782 # curr += 4 -2783 81 0/subop/add %edx 4/imm32 -2784 # -2785 eb/jump loop/disp8 -2786 } -2787 # return index -2788 89/<- %eax 1/r32/ecx -2789 $pos-slice:end: -2790 #? (write-buffered Stderr "=> ") -2791 #? (print-int32-buffered Stderr %eax) -2792 #? (write-buffered Stderr "\n") -2793 # . restore registers -2794 5e/pop-to-esi -2795 5b/pop-to-ebx -2796 5a/pop-to-edx -2797 59/pop-to-ecx -2798 # . epilogue -2799 89/<- %esp 5/r32/ebp -2800 5d/pop-to-ebp -2801 c3/return -2802 -2803 == data -2804 -2805 Type-id: # (stream (address array byte)) -2806 0x18/imm32/write -2807 0/imm32/read -2808 0x100/imm32/length -2809 # data -2810 "literal"/imm32 # 0 -2811 "int"/imm32 # 1 -2812 "addr"/imm32 # 2 -2813 "array"/imm32 # 3 -2814 "handle"/imm32 # 4 -2815 "bool"/imm32 # 5 -2816 0/imm32 -2817 0/imm32 -2818 # 0x20 -2819 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 -2820 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 -2821 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 -2822 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 -2823 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 -2824 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 -2825 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 -2826 -2827 == code -2828 -2829 test-parse-var-with-type: -2830 # . prologue -2831 55/push-ebp -2832 89/<- %ebp 4/r32/esp -2833 # (eax..ecx) = "x:" -2834 b8/copy-to-eax "x:"/imm32 -2835 8b/-> *eax 1/r32/ecx -2836 8d/copy-address *(eax+ecx+4) 1/r32/ecx -2837 05/add-to-eax 4/imm32 -2838 # var slice/ecx: slice = {eax, ecx} -2839 51/push-ecx -2840 50/push-eax -2841 89/<- %ecx 4/r32/esp -2842 # _test-input-stream contains "int" -2843 (clear-stream _test-input-stream) -2844 (write _test-input-stream "int") -2845 # -2846 (parse-var-with-type %ecx _test-input-stream) -2847 8b/-> *eax 2/r32/edx # Var-name -2848 (check-strings-equal %edx "x" "F - test-var-with-type/name") -2849 8b/-> *(eax+4) 2/r32/edx # Var-type -2850 (check-ints-equal *edx 1 "F - test-var-with-type/type") -2851 (check-ints-equal *(edx+4) 0 "F - test-var-with-type/type") -2852 # . epilogue -2853 89/<- %esp 5/r32/ebp -2854 5d/pop-to-ebp -2855 c3/return -2856 -2857 test-parse-var-with-type-and-register: -2858 # . prologue -2859 55/push-ebp -2860 89/<- %ebp 4/r32/esp -2861 # (eax..ecx) = "x/eax:" -2862 b8/copy-to-eax "x/eax:"/imm32 -2863 8b/-> *eax 1/r32/ecx -2864 8d/copy-address *(eax+ecx+4) 1/r32/ecx -2865 05/add-to-eax 4/imm32 -2866 # var slice/ecx: slice = {eax, ecx} -2867 51/push-ecx -2868 50/push-eax -2869 89/<- %ecx 4/r32/esp -2870 # _test-input-stream contains "int" -2871 (clear-stream _test-input-stream) -2872 (write _test-input-stream "int") -2873 # -2874 (parse-var-with-type %ecx _test-input-stream) -2875 8b/-> *eax 2/r32/edx # Var-name -2876 (check-strings-equal %edx "x" "F - test-var-with-type-and-register/name") -2877 8b/-> *(eax+0x10) 2/r32/edx # Var-register -2878 (check-strings-equal %edx "eax" "F - test-var-with-type-and-register/register") -2879 8b/-> *(eax+4) 2/r32/edx # Var-type -2880 (check-ints-equal *edx 1 "F - test-var-with-type-and-register/type") -2881 (check-ints-equal *(edx+4) 0 "F - test-var-with-type-and-register/type") -2882 # . epilogue -2883 89/<- %esp 5/r32/ebp -2884 5d/pop-to-ebp -2885 c3/return -2886 -2887 test-parse-var-with-trailing-characters: -2888 # . prologue -2889 55/push-ebp -2890 89/<- %ebp 4/r32/esp -2891 # (eax..ecx) = "x:" -2892 b8/copy-to-eax "x:"/imm32 -2893 8b/-> *eax 1/r32/ecx -2894 8d/copy-address *(eax+ecx+4) 1/r32/ecx -2895 05/add-to-eax 4/imm32 -2896 # var slice/ecx: slice = {eax, ecx} -2897 51/push-ecx -2898 50/push-eax -2899 89/<- %ecx 4/r32/esp -2900 # _test-input-stream contains "int," -2901 (clear-stream _test-input-stream) -2902 (write _test-input-stream "int,") -2903 # -2904 (parse-var-with-type %ecx _test-input-stream) -2905 8b/-> *eax 2/r32/edx # Var-name -2906 (check-strings-equal %edx "x" "F - test-var-with-trailing-characters/name") -2907 8b/-> *(eax+0x10) 2/r32/edx # Var-register -2908 (check-ints-equal %edx 0 "F - test-var-with-trailing-characters/register") -2909 8b/-> *(eax+4) 2/r32/edx # Var-type -2910 (check-ints-equal *edx 1 "F - test-var-with-trailing-characters/type") -2911 (check-ints-equal *(edx+4) 0 "F - test-var-with-trailing-characters/type") -2912 # . epilogue -2913 89/<- %esp 5/r32/ebp -2914 5d/pop-to-ebp -2915 c3/return -2916 -2917 test-parse-var-with-register-and-trailing-characters: -2918 # . prologue -2919 55/push-ebp -2920 89/<- %ebp 4/r32/esp -2921 # (eax..ecx) = "x/eax:" -2922 b8/copy-to-eax "x/eax:"/imm32 -2923 8b/-> *eax 1/r32/ecx -2924 8d/copy-address *(eax+ecx+4) 1/r32/ecx -2925 05/add-to-eax 4/imm32 -2926 # var slice/ecx: slice = {eax, ecx} -2927 51/push-ecx -2928 50/push-eax -2929 89/<- %ecx 4/r32/esp -2930 # _test-input-stream contains "int," -2931 (clear-stream _test-input-stream) -2932 (write _test-input-stream "int,") -2933 # -2934 (parse-var-with-type %ecx _test-input-stream) -2935 8b/-> *eax 2/r32/edx # Var-name -2936 (check-strings-equal %edx "x" "F - test-var-with-register-and-trailing-characters/name") -2937 8b/-> *(eax+0x10) 2/r32/edx # Var-register -2938 (check-strings-equal %edx "eax" "F - test-var-with-register-and-trailing-characters/register") -2939 8b/-> *(eax+4) 2/r32/edx # Var-type -2940 (check-ints-equal *edx 1 "F - test-var-with-register-and-trailing-characters/type") -2941 (check-ints-equal *(edx+4) 0 "F - test-var-with-register-and-trailing-characters/type") -2942 # . epilogue -2943 89/<- %esp 5/r32/ebp -2944 5d/pop-to-ebp -2945 c3/return -2946 -2947 test-parse-var-with-compound-type: -2948 # . prologue -2949 55/push-ebp -2950 89/<- %ebp 4/r32/esp -2951 # (eax..ecx) = "x:" -2952 b8/copy-to-eax "x:"/imm32 -2953 8b/-> *eax 1/r32/ecx -2954 8d/copy-address *(eax+ecx+4) 1/r32/ecx -2955 05/add-to-eax 4/imm32 -2956 # var slice/ecx: slice = {eax, ecx} -2957 51/push-ecx -2958 50/push-eax -2959 89/<- %ecx 4/r32/esp -2960 # _test-input-stream contains "(addr int)" -2961 (clear-stream _test-input-stream) -2962 (write _test-input-stream "(addr int)") -2963 # -2964 (parse-var-with-type %ecx _test-input-stream) -2965 8b/-> *eax 2/r32/edx # Var-name -2966 (check-strings-equal %edx "x" "F - test-var-with-compound-type/name") -2967 8b/-> *(eax+0x10) 2/r32/edx # Var-register -2968 (check-ints-equal %edx 0 "F - test-var-with-compound-type/register") -2969 # var type/edx: (handle tree type-id) = var->type -2970 8b/-> *(eax+4) 2/r32/edx # Var-type -2971 # type->left == atom(addr) -2972 8b/-> *edx 0/r32/eax # Atom-value -2973 (check-ints-equal *eax 2 "F - test-var-with-compound-type/type:0") # Tree-left -2974 # type->right->left == atom(int) -2975 8b/-> *(edx+4) 2/r32/edx # Tree-right -2976 8b/-> *edx 0/r32/eax # Tree-left -2977 (check-ints-equal *eax 1 "F - test-var-with-compound-type/type:1") # Atom-value -2978 # type->right->right == null -2979 (check-ints-equal *(edx+4) 0 "F - test-var-with-compound-type/type:2") # Tree-right -2980 # . epilogue -2981 89/<- %esp 5/r32/ebp -2982 5d/pop-to-ebp -2983 c3/return -2984 -2985 # identifier starts with a letter or '$' or '_' -2986 # no constraints at the moment on later letters -2987 # all we really want to do so far is exclude '{', '}' and '->' -2988 is-identifier?: # in: (addr slice) -> result/eax: boolean -2989 # . prologue -2990 55/push-ebp -2991 89/<- %ebp 4/r32/esp -2992 # if (slice-empty?(in)) return false -2993 (slice-empty? *(ebp+8)) # => eax -2994 3d/compare-eax-and 0/imm32/false -2995 75/jump-if-!= $is-identifier?:false/disp8 -2996 # var c/eax: byte = *in->start -2997 8b/-> *(ebp+8) 0/r32/eax -2998 8b/-> *eax 0/r32/eax -2999 8a/copy-byte *eax 0/r32/AL -3000 81 4/subop/and %eax 0xff/imm32 -3001 # if (c == '$') return true -3002 3d/compare-eax-and 0x24/imm32/$ -3003 74/jump-if-= $is-identifier?:true/disp8 -3004 # if (c == '_') return true -3005 3d/compare-eax-and 0x5f/imm32/_ -3006 74/jump-if-= $is-identifier?:true/disp8 -3007 # drop case -3008 25/and-eax-with 0x5f/imm32 -3009 # if (c < 'A') return false -3010 3d/compare-eax-and 0x41/imm32/A -3011 7c/jump-if-< $is-identifier?:false/disp8 -3012 # if (c > 'Z') return false -3013 3d/compare-eax-and 0x5a/imm32/Z -3014 7f/jump-if-> $is-identifier?:false/disp8 -3015 # otherwise return true -3016 $is-identifier?:true: -3017 b8/copy-to-eax 1/imm32/true -3018 eb/jump $is-identifier?:end/disp8 -3019 $is-identifier?:false: -3020 b8/copy-to-eax 0/imm32/false -3021 $is-identifier?:end: -3022 # . epilogue -3023 89/<- %esp 5/r32/ebp -3024 5d/pop-to-ebp -3025 c3/return -3026 -3027 test-is-identifier-dollar: -3028 # . prologue -3029 55/push-ebp -3030 89/<- %ebp 4/r32/esp -3031 # (eax..ecx) = "$a" -3032 b8/copy-to-eax "$a"/imm32 -3033 8b/-> *eax 1/r32/ecx -3034 8d/copy-address *(eax+ecx+4) 1/r32/ecx -3035 05/add-to-eax 4/imm32 -3036 # var slice/ecx: slice = {eax, ecx} -3037 51/push-ecx -3038 50/push-eax -3039 89/<- %ecx 4/r32/esp -3040 # -3041 (is-identifier? %ecx) -3042 (check-ints-equal %eax 1 "F - test-is-identifier-dollar") -3043 # . epilogue -3044 89/<- %esp 5/r32/ebp -3045 5d/pop-to-ebp -3046 c3/return -3047 -3048 test-is-identifier-underscore: -3049 # . prologue -3050 55/push-ebp -3051 89/<- %ebp 4/r32/esp -3052 # (eax..ecx) = "_a" -3053 b8/copy-to-eax "_a"/imm32 -3054 8b/-> *eax 1/r32/ecx -3055 8d/copy-address *(eax+ecx+4) 1/r32/ecx -3056 05/add-to-eax 4/imm32 -3057 # var slice/ecx: slice = {eax, ecx} -3058 51/push-ecx -3059 50/push-eax -3060 89/<- %ecx 4/r32/esp -3061 # -3062 (is-identifier? %ecx) -3063 (check-ints-equal %eax 1 "F - test-is-identifier-underscore") -3064 # . epilogue -3065 89/<- %esp 5/r32/ebp -3066 5d/pop-to-ebp -3067 c3/return -3068 -3069 test-is-identifier-a: -3070 # . prologue -3071 55/push-ebp -3072 89/<- %ebp 4/r32/esp -3073 # (eax..ecx) = "a$" -3074 b8/copy-to-eax "a$"/imm32 -3075 8b/-> *eax 1/r32/ecx -3076 8d/copy-address *(eax+ecx+4) 1/r32/ecx -3077 05/add-to-eax 4/imm32 -3078 # var slice/ecx: slice = {eax, ecx} -3079 51/push-ecx -3080 50/push-eax -3081 89/<- %ecx 4/r32/esp -3082 # -3083 (is-identifier? %ecx) -3084 (check-ints-equal %eax 1 "F - test-is-identifier-a") -3085 # . epilogue -3086 89/<- %esp 5/r32/ebp -3087 5d/pop-to-ebp -3088 c3/return -3089 -3090 test-is-identifier-z: -3091 # . prologue -3092 55/push-ebp -3093 89/<- %ebp 4/r32/esp -3094 # (eax..ecx) = "z$" -3095 b8/copy-to-eax "z$"/imm32 -3096 8b/-> *eax 1/r32/ecx -3097 8d/copy-address *(eax+ecx+4) 1/r32/ecx -3098 05/add-to-eax 4/imm32 -3099 # var slice/ecx: slice = {eax, ecx} -3100 51/push-ecx -3101 50/push-eax -3102 89/<- %ecx 4/r32/esp -3103 # -3104 (is-identifier? %ecx) -3105 (check-ints-equal %eax 1 "F - test-is-identifier-z") -3106 # . epilogue -3107 89/<- %esp 5/r32/ebp -3108 5d/pop-to-ebp -3109 c3/return -3110 -3111 test-is-identifier-A: -3112 # . prologue -3113 55/push-ebp -3114 89/<- %ebp 4/r32/esp -3115 # (eax..ecx) = "A$" -3116 b8/copy-to-eax "A$"/imm32 -3117 8b/-> *eax 1/r32/ecx -3118 8d/copy-address *(eax+ecx+4) 1/r32/ecx -3119 05/add-to-eax 4/imm32 -3120 # var slice/ecx: slice = {eax, ecx} -3121 51/push-ecx -3122 50/push-eax -3123 89/<- %ecx 4/r32/esp -3124 # -3125 (is-identifier? %ecx) -3126 (check-ints-equal %eax 1 "F - test-is-identifier-A") -3127 # . epilogue -3128 89/<- %esp 5/r32/ebp -3129 5d/pop-to-ebp -3130 c3/return -3131 -3132 test-is-identifier-Z: -3133 # . prologue -3134 55/push-ebp -3135 89/<- %ebp 4/r32/esp -3136 # (eax..ecx) = "Z$" -3137 b8/copy-to-eax "Z$"/imm32 -3138 8b/-> *eax 1/r32/ecx -3139 8d/copy-address *(eax+ecx+4) 1/r32/ecx -3140 05/add-to-eax 4/imm32 -3141 # var slice/ecx: slice = {eax, ecx} -3142 51/push-ecx -3143 50/push-eax -3144 89/<- %ecx 4/r32/esp -3145 # -3146 (is-identifier? %ecx) -3147 (check-ints-equal %eax 1 "F - test-is-identifier-Z") -3148 # . epilogue -3149 89/<- %esp 5/r32/ebp -3150 5d/pop-to-ebp -3151 c3/return -3152 -3153 test-is-identifier-@: -3154 # character before 'A' is invalid -3155 # . prologue -3156 55/push-ebp -3157 89/<- %ebp 4/r32/esp -3158 # (eax..ecx) = "@a" -3159 b8/copy-to-eax "@a"/imm32 -3160 8b/-> *eax 1/r32/ecx -3161 8d/copy-address *(eax+ecx+4) 1/r32/ecx -3162 05/add-to-eax 4/imm32 -3163 # var slice/ecx: slice = {eax, ecx} -3164 51/push-ecx -3165 50/push-eax -3166 89/<- %ecx 4/r32/esp -3167 # -3168 (is-identifier? %ecx) -3169 (check-ints-equal %eax 0 "F - test-is-identifier-@") -3170 # . epilogue -3171 89/<- %esp 5/r32/ebp -3172 5d/pop-to-ebp -3173 c3/return -3174 -3175 test-is-identifier-square-bracket: -3176 # character after 'Z' is invalid +2727 { +2728 $next-mu-token:check-for-close-paren: +2729 # if (curr-byte != ')') break +2730 3d/compare-eax-and 0x29/imm32/close-paren +2731 75/jump-if-!= break/disp8 +2732 # ++in->read +2733 ff 0/subop/increment *(esi+4) +2734 # return +2735 e9/jump $next-mu-token:done/disp32 +2736 } +2737 { +2738 $next-mu-token:regular-word-without-metadata: +2739 # if (in->read >= in->write) break +2740 # . ecx = in->read +2741 8b/-> *(esi+4) 1/r32/ecx +2742 # . if (ecx >= in->write) break +2743 3b/compare *esi 1/r32/ecx +2744 7d/jump-if->= break/disp8 +2745 # var c/eax: byte = in->data[in->read] +2746 31/xor %eax 0/r32/eax +2747 8a/copy-byte *(esi+ecx+0xc) 0/r32/AL +2748 # if (c == ' ') break +2749 3d/compare-eax-and 0x20/imm32/space +2750 74/jump-if-= break/disp8 +2751 # if (c == '\r') break +2752 3d/compare-eax-and 0xd/imm32/carriage-return +2753 74/jump-if-= break/disp8 +2754 # if (c == '\n') break +2755 3d/compare-eax-and 0xa/imm32/newline +2756 74/jump-if-= break/disp8 +2757 # if (c == '(') break +2758 3d/compare-eax-and 0x28/imm32/open-paren +2759 0f 84/jump-if-= break/disp32 +2760 # if (c == ')') break +2761 3d/compare-eax-and 0x29/imm32/close-paren +2762 0f 84/jump-if-= break/disp32 +2763 # if (c == ',') break +2764 3d/compare-eax-and 0x2c/imm32/comma +2765 0f 84/jump-if-= break/disp32 +2766 # ++in->read +2767 ff 0/subop/increment *(esi+4) +2768 # +2769 e9/jump loop/disp32 +2770 } +2771 $next-mu-token:done: +2772 # out->end = &in->data[in->read] +2773 8b/-> *(esi+4) 1/r32/ecx +2774 8d/copy-address *(esi+ecx+0xc) 0/r32/eax +2775 89/<- *(edi+4) 0/r32/eax +2776 $next-mu-token:end: +2777 # . restore registers +2778 5f/pop-to-edi +2779 5e/pop-to-esi +2780 59/pop-to-ecx +2781 58/pop-to-eax +2782 # . epilogue +2783 89/<- %esp 5/r32/ebp +2784 5d/pop-to-ebp +2785 c3/return +2786 +2787 # return the index in an array of strings matching 's' +2788 # index is denominated in elements, not bytes +2789 pos-slice: # arr: (addr stream (handle array byte)), s: (addr slice) -> index/eax: int +2790 # . prologue +2791 55/push-ebp +2792 89/<- %ebp 4/r32/esp +2793 # . save registers +2794 51/push-ecx +2795 52/push-edx +2796 53/push-ebx +2797 56/push-esi +2798 #? (write-buffered Stderr "pos-slice: ") +2799 #? (write-slice-buffered Stderr *(ebp+0xc)) +2800 #? (write-buffered Stderr "\n") +2801 #? (flush Stderr) +2802 # esi = arr +2803 8b/-> *(ebp+8) 6/r32/esi +2804 # var index/ecx: int = 0 +2805 b9/copy-to-ecx 0/imm32 +2806 # var curr/edx: (addr (addr array byte)) = arr->data +2807 8d/copy-address *(esi+0xc) 2/r32/edx +2808 # var max/ebx: (addr (addr array byte)) = &arr->data[arr->write] +2809 8b/-> *esi 3/r32/ebx +2810 8d/copy-address *(esi+ebx+0xc) 3/r32/ebx +2811 { +2812 #? (write-buffered Stderr " ") +2813 #? (print-int32-buffered Stderr %ecx) +2814 #? (write-buffered Stderr "\n") +2815 #? (flush Stderr) +2816 # if (curr >= max) return -1 +2817 39/compare %edx 3/r32/ebx +2818 b8/copy-to-eax -1/imm32 +2819 73/jump-if-addr>= $pos-slice:end/disp8 +2820 # if (slice-equal?(s, *curr)) break +2821 (slice-equal? *(ebp+0xc) *edx) # => eax +2822 3d/compare-eax-and 0/imm32/false +2823 75/jump-if-!= break/disp8 +2824 # ++index +2825 41/increment-ecx +2826 # curr += 4 +2827 81 0/subop/add %edx 4/imm32 +2828 # +2829 eb/jump loop/disp8 +2830 } +2831 # return index +2832 89/<- %eax 1/r32/ecx +2833 $pos-slice:end: +2834 #? (write-buffered Stderr "=> ") +2835 #? (print-int32-buffered Stderr %eax) +2836 #? (write-buffered Stderr "\n") +2837 # . restore registers +2838 5e/pop-to-esi +2839 5b/pop-to-ebx +2840 5a/pop-to-edx +2841 59/pop-to-ecx +2842 # . epilogue +2843 89/<- %esp 5/r32/ebp +2844 5d/pop-to-ebp +2845 c3/return +2846 +2847 == data +2848 +2849 Type-id: # (stream (address array byte)) +2850 0x18/imm32/write +2851 0/imm32/read +2852 0x100/imm32/length +2853 # data +2854 "literal"/imm32 # 0 +2855 "int"/imm32 # 1 +2856 "addr"/imm32 # 2 +2857 "array"/imm32 # 3 +2858 "handle"/imm32 # 4 +2859 "bool"/imm32 # 5 +2860 0/imm32 +2861 0/imm32 +2862 # 0x20 +2863 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 +2864 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 +2865 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 +2866 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 +2867 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 +2868 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 +2869 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 +2870 +2871 == code +2872 +2873 test-parse-var-with-type: +2874 # . prologue +2875 55/push-ebp +2876 89/<- %ebp 4/r32/esp +2877 # (eax..ecx) = "x:" +2878 b8/copy-to-eax "x:"/imm32 +2879 8b/-> *eax 1/r32/ecx +2880 8d/copy-address *(eax+ecx+4) 1/r32/ecx +2881 05/add-to-eax 4/imm32 +2882 # var slice/ecx: slice = {eax, ecx} +2883 51/push-ecx +2884 50/push-eax +2885 89/<- %ecx 4/r32/esp +2886 # _test-input-stream contains "int" +2887 (clear-stream _test-input-stream) +2888 (write _test-input-stream "int") +2889 # +2890 (parse-var-with-type %ecx _test-input-stream) +2891 8b/-> *eax 2/r32/edx # Var-name +2892 (check-strings-equal %edx "x" "F - test-var-with-type/name") +2893 8b/-> *(eax+4) 2/r32/edx # Var-type +2894 (check-ints-equal *edx 1 "F - test-var-with-type/type") +2895 (check-ints-equal *(edx+4) 0 "F - test-var-with-type/type") +2896 # . epilogue +2897 89/<- %esp 5/r32/ebp +2898 5d/pop-to-ebp +2899 c3/return +2900 +2901 test-parse-var-with-type-and-register: +2902 # . prologue +2903 55/push-ebp +2904 89/<- %ebp 4/r32/esp +2905 # (eax..ecx) = "x/eax:" +2906 b8/copy-to-eax "x/eax:"/imm32 +2907 8b/-> *eax 1/r32/ecx +2908 8d/copy-address *(eax+ecx+4) 1/r32/ecx +2909 05/add-to-eax 4/imm32 +2910 # var slice/ecx: slice = {eax, ecx} +2911 51/push-ecx +2912 50/push-eax +2913 89/<- %ecx 4/r32/esp +2914 # _test-input-stream contains "int" +2915 (clear-stream _test-input-stream) +2916 (write _test-input-stream "int") +2917 # +2918 (parse-var-with-type %ecx _test-input-stream) +2919 8b/-> *eax 2/r32/edx # Var-name +2920 (check-strings-equal %edx "x" "F - test-var-with-type-and-register/name") +2921 8b/-> *(eax+0x10) 2/r32/edx # Var-register +2922 (check-strings-equal %edx "eax" "F - test-var-with-type-and-register/register") +2923 8b/-> *(eax+4) 2/r32/edx # Var-type +2924 (check-ints-equal *edx 1 "F - test-var-with-type-and-register/type") +2925 (check-ints-equal *(edx+4) 0 "F - test-var-with-type-and-register/type") +2926 # . epilogue +2927 89/<- %esp 5/r32/ebp +2928 5d/pop-to-ebp +2929 c3/return +2930 +2931 test-parse-var-with-trailing-characters: +2932 # . prologue +2933 55/push-ebp +2934 89/<- %ebp 4/r32/esp +2935 # (eax..ecx) = "x:" +2936 b8/copy-to-eax "x:"/imm32 +2937 8b/-> *eax 1/r32/ecx +2938 8d/copy-address *(eax+ecx+4) 1/r32/ecx +2939 05/add-to-eax 4/imm32 +2940 # var slice/ecx: slice = {eax, ecx} +2941 51/push-ecx +2942 50/push-eax +2943 89/<- %ecx 4/r32/esp +2944 # _test-input-stream contains "int," +2945 (clear-stream _test-input-stream) +2946 (write _test-input-stream "int,") +2947 # +2948 (parse-var-with-type %ecx _test-input-stream) +2949 8b/-> *eax 2/r32/edx # Var-name +2950 (check-strings-equal %edx "x" "F - test-var-with-trailing-characters/name") +2951 8b/-> *(eax+0x10) 2/r32/edx # Var-register +2952 (check-ints-equal %edx 0 "F - test-var-with-trailing-characters/register") +2953 8b/-> *(eax+4) 2/r32/edx # Var-type +2954 (check-ints-equal *edx 1 "F - test-var-with-trailing-characters/type") +2955 (check-ints-equal *(edx+4) 0 "F - test-var-with-trailing-characters/type") +2956 # . epilogue +2957 89/<- %esp 5/r32/ebp +2958 5d/pop-to-ebp +2959 c3/return +2960 +2961 test-parse-var-with-register-and-trailing-characters: +2962 # . prologue +2963 55/push-ebp +2964 89/<- %ebp 4/r32/esp +2965 # (eax..ecx) = "x/eax:" +2966 b8/copy-to-eax "x/eax:"/imm32 +2967 8b/-> *eax 1/r32/ecx +2968 8d/copy-address *(eax+ecx+4) 1/r32/ecx +2969 05/add-to-eax 4/imm32 +2970 # var slice/ecx: slice = {eax, ecx} +2971 51/push-ecx +2972 50/push-eax +2973 89/<- %ecx 4/r32/esp +2974 # _test-input-stream contains "int," +2975 (clear-stream _test-input-stream) +2976 (write _test-input-stream "int,") +2977 # +2978 (parse-var-with-type %ecx _test-input-stream) +2979 8b/-> *eax 2/r32/edx # Var-name +2980 (check-strings-equal %edx "x" "F - test-var-with-register-and-trailing-characters/name") +2981 8b/-> *(eax+0x10) 2/r32/edx # Var-register +2982 (check-strings-equal %edx "eax" "F - test-var-with-register-and-trailing-characters/register") +2983 8b/-> *(eax+4) 2/r32/edx # Var-type +2984 (check-ints-equal *edx 1 "F - test-var-with-register-and-trailing-characters/type") +2985 (check-ints-equal *(edx+4) 0 "F - test-var-with-register-and-trailing-characters/type") +2986 # . epilogue +2987 89/<- %esp 5/r32/ebp +2988 5d/pop-to-ebp +2989 c3/return +2990 +2991 test-parse-var-with-compound-type: +2992 # . prologue +2993 55/push-ebp +2994 89/<- %ebp 4/r32/esp +2995 # (eax..ecx) = "x:" +2996 b8/copy-to-eax "x:"/imm32 +2997 8b/-> *eax 1/r32/ecx +2998 8d/copy-address *(eax+ecx+4) 1/r32/ecx +2999 05/add-to-eax 4/imm32 +3000 # var slice/ecx: slice = {eax, ecx} +3001 51/push-ecx +3002 50/push-eax +3003 89/<- %ecx 4/r32/esp +3004 # _test-input-stream contains "(addr int)" +3005 (clear-stream _test-input-stream) +3006 (write _test-input-stream "(addr int)") +3007 # +3008 (parse-var-with-type %ecx _test-input-stream) +3009 8b/-> *eax 2/r32/edx # Var-name +3010 (check-strings-equal %edx "x" "F - test-var-with-compound-type/name") +3011 8b/-> *(eax+0x10) 2/r32/edx # Var-register +3012 (check-ints-equal %edx 0 "F - test-var-with-compound-type/register") +3013 # var type/edx: (handle tree type-id) = var->type +3014 8b/-> *(eax+4) 2/r32/edx # Var-type +3015 # type->left == atom(addr) +3016 8b/-> *edx 0/r32/eax # Atom-value +3017 (check-ints-equal *eax 2 "F - test-var-with-compound-type/type:0") # Tree-left +3018 # type->right->left == atom(int) +3019 8b/-> *(edx+4) 2/r32/edx # Tree-right +3020 8b/-> *edx 0/r32/eax # Tree-left +3021 (check-ints-equal *eax 1 "F - test-var-with-compound-type/type:1") # Atom-value +3022 # type->right->right == null +3023 (check-ints-equal *(edx+4) 0 "F - test-var-with-compound-type/type:2") # Tree-right +3024 # . epilogue +3025 89/<- %esp 5/r32/ebp +3026 5d/pop-to-ebp +3027 c3/return +3028 +3029 # identifier starts with a letter or '$' or '_' +3030 # no constraints at the moment on later letters +3031 # all we really want to do so far is exclude '{', '}' and '->' +3032 is-identifier?: # in: (addr slice) -> result/eax: boolean +3033 # . prologue +3034 55/push-ebp +3035 89/<- %ebp 4/r32/esp +3036 # if (slice-empty?(in)) return false +3037 (slice-empty? *(ebp+8)) # => eax +3038 3d/compare-eax-and 0/imm32/false +3039 75/jump-if-!= $is-identifier?:false/disp8 +3040 # var c/eax: byte = *in->start +3041 8b/-> *(ebp+8) 0/r32/eax +3042 8b/-> *eax 0/r32/eax +3043 8a/copy-byte *eax 0/r32/AL +3044 81 4/subop/and %eax 0xff/imm32 +3045 # if (c == '$') return true +3046 3d/compare-eax-and 0x24/imm32/$ +3047 74/jump-if-= $is-identifier?:true/disp8 +3048 # if (c == '_') return true +3049 3d/compare-eax-and 0x5f/imm32/_ +3050 74/jump-if-= $is-identifier?:true/disp8 +3051 # drop case +3052 25/and-eax-with 0x5f/imm32 +3053 # if (c < 'A') return false +3054 3d/compare-eax-and 0x41/imm32/A +3055 7c/jump-if-< $is-identifier?:false/disp8 +3056 # if (c > 'Z') return false +3057 3d/compare-eax-and 0x5a/imm32/Z +3058 7f/jump-if-> $is-identifier?:false/disp8 +3059 # otherwise return true +3060 $is-identifier?:true: +3061 b8/copy-to-eax 1/imm32/true +3062 eb/jump $is-identifier?:end/disp8 +3063 $is-identifier?:false: +3064 b8/copy-to-eax 0/imm32/false +3065 $is-identifier?:end: +3066 # . epilogue +3067 89/<- %esp 5/r32/ebp +3068 5d/pop-to-ebp +3069 c3/return +3070 +3071 test-is-identifier-dollar: +3072 # . prologue +3073 55/push-ebp +3074 89/<- %ebp 4/r32/esp +3075 # (eax..ecx) = "$a" +3076 b8/copy-to-eax "$a"/imm32 +3077 8b/-> *eax 1/r32/ecx +3078 8d/copy-address *(eax+ecx+4) 1/r32/ecx +3079 05/add-to-eax 4/imm32 +3080 # var slice/ecx: slice = {eax, ecx} +3081 51/push-ecx +3082 50/push-eax +3083 89/<- %ecx 4/r32/esp +3084 # +3085 (is-identifier? %ecx) +3086 (check-ints-equal %eax 1 "F - test-is-identifier-dollar") +3087 # . epilogue +3088 89/<- %esp 5/r32/ebp +3089 5d/pop-to-ebp +3090 c3/return +3091 +3092 test-is-identifier-underscore: +3093 # . prologue +3094 55/push-ebp +3095 89/<- %ebp 4/r32/esp +3096 # (eax..ecx) = "_a" +3097 b8/copy-to-eax "_a"/imm32 +3098 8b/-> *eax 1/r32/ecx +3099 8d/copy-address *(eax+ecx+4) 1/r32/ecx +3100 05/add-to-eax 4/imm32 +3101 # var slice/ecx: slice = {eax, ecx} +3102 51/push-ecx +3103 50/push-eax +3104 89/<- %ecx 4/r32/esp +3105 # +3106 (is-identifier? %ecx) +3107 (check-ints-equal %eax 1 "F - test-is-identifier-underscore") +3108 # . epilogue +3109 89/<- %esp 5/r32/ebp +3110 5d/pop-to-ebp +3111 c3/return +3112 +3113 test-is-identifier-a: +3114 # . prologue +3115 55/push-ebp +3116 89/<- %ebp 4/r32/esp +3117 # (eax..ecx) = "a$" +3118 b8/copy-to-eax "a$"/imm32 +3119 8b/-> *eax 1/r32/ecx +3120 8d/copy-address *(eax+ecx+4) 1/r32/ecx +3121 05/add-to-eax 4/imm32 +3122 # var slice/ecx: slice = {eax, ecx} +3123 51/push-ecx +3124 50/push-eax +3125 89/<- %ecx 4/r32/esp +3126 # +3127 (is-identifier? %ecx) +3128 (check-ints-equal %eax 1 "F - test-is-identifier-a") +3129 # . epilogue +3130 89/<- %esp 5/r32/ebp +3131 5d/pop-to-ebp +3132 c3/return +3133 +3134 test-is-identifier-z: +3135 # . prologue +3136 55/push-ebp +3137 89/<- %ebp 4/r32/esp +3138 # (eax..ecx) = "z$" +3139 b8/copy-to-eax "z$"/imm32 +3140 8b/-> *eax 1/r32/ecx +3141 8d/copy-address *(eax+ecx+4) 1/r32/ecx +3142 05/add-to-eax 4/imm32 +3143 # var slice/ecx: slice = {eax, ecx} +3144 51/push-ecx +3145 50/push-eax +3146 89/<- %ecx 4/r32/esp +3147 # +3148 (is-identifier? %ecx) +3149 (check-ints-equal %eax 1 "F - test-is-identifier-z") +3150 # . epilogue +3151 89/<- %esp 5/r32/ebp +3152 5d/pop-to-ebp +3153 c3/return +3154 +3155 test-is-identifier-A: +3156 # . prologue +3157 55/push-ebp +3158 89/<- %ebp 4/r32/esp +3159 # (eax..ecx) = "A$" +3160 b8/copy-to-eax "A$"/imm32 +3161 8b/-> *eax 1/r32/ecx +3162 8d/copy-address *(eax+ecx+4) 1/r32/ecx +3163 05/add-to-eax 4/imm32 +3164 # var slice/ecx: slice = {eax, ecx} +3165 51/push-ecx +3166 50/push-eax +3167 89/<- %ecx 4/r32/esp +3168 # +3169 (is-identifier? %ecx) +3170 (check-ints-equal %eax 1 "F - test-is-identifier-A") +3171 # . epilogue +3172 89/<- %esp 5/r32/ebp +3173 5d/pop-to-ebp +3174 c3/return +3175 +3176 test-is-identifier-Z: 3177 # . prologue 3178 55/push-ebp 3179 89/<- %ebp 4/r32/esp -3180 # (eax..ecx) = "[a" -3181 b8/copy-to-eax "[a"/imm32 +3180 # (eax..ecx) = "Z$" +3181 b8/copy-to-eax "Z$"/imm32 3182 8b/-> *eax 1/r32/ecx 3183 8d/copy-address *(eax+ecx+4) 1/r32/ecx 3184 05/add-to-eax 4/imm32 @@ -3109,20 +3104,20 @@ if ('onhashchange' in window) { 3187 50/push-eax 3188 89/<- %ecx 4/r32/esp 3189 # -3190 (is-identifier? %ecx) -3191 (check-ints-equal %eax 0 "F - test-is-identifier-@") +3190 (is-identifier? %ecx) +3191 (check-ints-equal %eax 1 "F - test-is-identifier-Z") 3192 # . epilogue 3193 89/<- %esp 5/r32/ebp 3194 5d/pop-to-ebp 3195 c3/return 3196 -3197 test-is-identifier-backtick: -3198 # character before 'a' is invalid +3197 test-is-identifier-@: +3198 # character before 'A' is invalid 3199 # . prologue 3200 55/push-ebp 3201 89/<- %ebp 4/r32/esp -3202 # (eax..ecx) = "`a" -3203 b8/copy-to-eax "`a"/imm32 +3202 # (eax..ecx) = "@a" +3203 b8/copy-to-eax "@a"/imm32 3204 8b/-> *eax 1/r32/ecx 3205 8d/copy-address *(eax+ecx+4) 1/r32/ecx 3206 05/add-to-eax 4/imm32 @@ -3131,20 +3126,20 @@ if ('onhashchange' in window) { 3209 50/push-eax 3210 89/<- %ecx 4/r32/esp 3211 # -3212 (is-identifier? %ecx) -3213 (check-ints-equal %eax 0 "F - test-is-identifier-backtick") +3212 (is-identifier? %ecx) +3213 (check-ints-equal %eax 0 "F - test-is-identifier-@") 3214 # . epilogue 3215 89/<- %esp 5/r32/ebp 3216 5d/pop-to-ebp 3217 c3/return 3218 -3219 test-is-identifier-curly-brace-open: -3220 # character after 'z' is invalid; also used for blocks +3219 test-is-identifier-square-bracket: +3220 # character after 'Z' is invalid 3221 # . prologue 3222 55/push-ebp 3223 89/<- %ebp 4/r32/esp -3224 # (eax..ecx) = "{a" -3225 b8/copy-to-eax "{a"/imm32 +3224 # (eax..ecx) = "[a" +3225 b8/copy-to-eax "[a"/imm32 3226 8b/-> *eax 1/r32/ecx 3227 8d/copy-address *(eax+ecx+4) 1/r32/ecx 3228 05/add-to-eax 4/imm32 @@ -3153,5615 +3148,5678 @@ if ('onhashchange' in window) { 3231 50/push-eax 3232 89/<- %ecx 4/r32/esp 3233 # -3234 (is-identifier? %ecx) -3235 (check-ints-equal %eax 0 "F - test-is-identifier-curly-brace-open") +3234 (is-identifier? %ecx) +3235 (check-ints-equal %eax 0 "F - test-is-identifier-@") 3236 # . epilogue 3237 89/<- %esp 5/r32/ebp 3238 5d/pop-to-ebp 3239 c3/return 3240 -3241 test-is-identifier-curly-brace-close: -3242 # . prologue -3243 55/push-ebp -3244 89/<- %ebp 4/r32/esp -3245 # (eax..ecx) = "}a" -3246 b8/copy-to-eax "}a"/imm32 -3247 8b/-> *eax 1/r32/ecx -3248 8d/copy-address *(eax+ecx+4) 1/r32/ecx -3249 05/add-to-eax 4/imm32 -3250 # var slice/ecx: slice = {eax, ecx} -3251 51/push-ecx -3252 50/push-eax -3253 89/<- %ecx 4/r32/esp -3254 # -3255 (is-identifier? %ecx) -3256 (check-ints-equal %eax 0 "F - test-is-identifier-curly-brace-close") -3257 # . epilogue -3258 89/<- %esp 5/r32/ebp -3259 5d/pop-to-ebp -3260 c3/return -3261 -3262 test-is-identifier-hyphen: -3263 # disallow leading '-' since '->' has special meaning -3264 # . prologue -3265 55/push-ebp -3266 89/<- %ebp 4/r32/esp -3267 # (eax..ecx) = "-a" -3268 b8/copy-to-eax "-a"/imm32 -3269 8b/-> *eax 1/r32/ecx -3270 8d/copy-address *(eax+ecx+4) 1/r32/ecx -3271 05/add-to-eax 4/imm32 -3272 # var slice/ecx: slice = {eax, ecx} -3273 51/push-ecx -3274 50/push-eax -3275 89/<- %ecx 4/r32/esp -3276 # -3277 (is-identifier? %ecx) -3278 (check-ints-equal %eax 0 "F - test-is-identifier-hyphen") -3279 # . epilogue -3280 89/<- %esp 5/r32/ebp -3281 5d/pop-to-ebp -3282 c3/return -3283 -3284 populate-mu-function-body: # in: (addr buffered-file), out: (handle function), vars: (addr stack (handle var)) -3285 # . prologue -3286 55/push-ebp -3287 89/<- %ebp 4/r32/esp -3288 # . save registers -3289 50/push-eax -3290 56/push-esi -3291 57/push-edi -3292 # esi = in -3293 8b/-> *(ebp+8) 6/r32/esi -3294 # edi = out -3295 8b/-> *(ebp+0xc) 7/r32/edi -3296 # initialize some global state -3297 c7 0/subop/copy *Curr-block-depth 1/imm32 -3298 c7 0/subop/copy *Next-local-stack-offset -4/imm32 -3299 # var eax: (handle block) = parse-mu-block(in, vars, fn) -3300 (parse-mu-block %esi *(ebp+0x10) %edi) # => eax -3301 # out->body = eax -3302 89/<- *(edi+0x10) 0/r32/eax # Function-body -3303 $populate-mu-function-body:end: -3304 # . restore registers -3305 5f/pop-to-edi -3306 5e/pop-to-esi -3307 58/pop-to-eax -3308 # . epilogue -3309 89/<- %esp 5/r32/ebp -3310 5d/pop-to-ebp -3311 c3/return -3312 -3313 == data -3314 -3315 # Global state added to each var record when parsing a function -3316 -3317 Curr-block-depth: # (addr int) -3318 0/imm32 -3319 Next-local-stack-offset: # (addr int) -3320 -4/imm32 -3321 -3322 Next-block-index: # (addr int) -3323 1/imm32 -3324 -3325 == code -3326 -3327 # parses a block, assuming that the leading '{' has already been read by the caller -3328 parse-mu-block: # in: (addr buffered-file), vars: (addr stack (handle var)), fn: (handle function) -> result/eax: (handle block) -3329 # pseudocode: -3330 # var line: (stream byte 512) -3331 # var word-slice: slice -3332 # increment *Curr-block-depth -3333 # result/eax = allocate(Heap, Stmt-size) -3334 # result->tag = 0/block -3335 # result->name = some unique name -3336 # while true # line loop -3337 # clear-stream(line) -3338 # read-line-buffered(in, line) -3339 # if (line->write == 0) break # end of file -3340 # word-slice = next-mu-token(line) -3341 # if slice-empty?(word-slice) # end of line -3342 # continue -3343 # else if slice-starts-with?(word-slice, "#") -3344 # continue -3345 # else if slice-equal?(word-slice, "{") -3346 # assert(no-tokens-in(line)) -3347 # block = parse-mu-block(in, vars, fn) -3348 # append-to-block(result, block) -3349 # else if slice-equal?(word-slice, "}") -3350 # break -3351 # else if slice-ends-with?(word-slice, ":") -3352 # # TODO: error-check the rest of 'line' -3353 # --word-slice->end to skip ':' -3354 # named-block = parse-mu-named-block(word-slice, in, vars, fn) -3355 # append-to-block(result, named-block) -3356 # else if slice-equal?(word-slice, "var") -3357 # var-def = parse-mu-var-def(line, vars) -3358 # append-to-block(result, var-def) -3359 # else -3360 # stmt = parse-mu-stmt(line, vars, fn) -3361 # append-to-block(result, stmt) -3362 # decrement *Curr-block-depth -3363 # return result -3364 # -3365 # . prologue -3366 55/push-ebp -3367 89/<- %ebp 4/r32/esp -3368 # . save registers -3369 51/push-ecx -3370 52/push-edx -3371 53/push-ebx -3372 57/push-edi -3373 # var line/ecx: (stream byte 512) -3374 81 5/subop/subtract %esp 0x200/imm32 -3375 68/push 0x200/imm32/length -3376 68/push 0/imm32/read -3377 68/push 0/imm32/write -3378 89/<- %ecx 4/r32/esp -3379 # var word-slice/edx: slice -3380 68/push 0/imm32/end -3381 68/push 0/imm32/start -3382 89/<- %edx 4/r32/esp -3383 # edi = result -3384 (allocate Heap *Stmt-size) # => eax -3385 (zero-out %eax *Stmt-size) -3386 89/<- %edi 0/r32/eax -3387 # set result->tag -3388 c7 0/subop/copy *edi 0/imm32/block # Stmt-tag -3389 # set result->var -3390 (new-block-name *(ebp+0x10)) # => eax -3391 89/<- *(edi+8) 0/r32/eax # Block-var -3392 # push result->var to vars -3393 (push *(ebp+0xc) %eax) -3394 # increment *Curr-block-depth -3395 ff 0/subop/increment *Curr-block-depth -3396 { -3397 $parse-mu-block:line-loop: -3398 # line = read-line-buffered(in) -3399 (clear-stream %ecx) -3400 (read-line-buffered *(ebp+8) %ecx) -3401 #? (write-buffered Stderr "line: ") -3402 #? (write-stream-data Stderr %ecx) -3403 #? (write-buffered Stderr Newline) -3404 #? (flush Stderr) -3405 # if (line->write == 0) break -3406 81 7/subop/compare *ecx 0/imm32 -3407 0f 84/jump-if-= break/disp32 -3408 # word-slice = next-mu-token(line) -3409 (next-mu-token %ecx %edx) -3410 #? (write-buffered Stderr "word: ") -3411 #? (write-slice-buffered Stderr %edx) -3412 #? (write-buffered Stderr Newline) -3413 #? (flush Stderr) -3414 # if slice-empty?(word-slice) continue -3415 (slice-empty? %edx) -3416 3d/compare-eax-and 0/imm32/false -3417 0f 85/jump-if-!= loop/disp32 -3418 # if (slice-starts-with?(word-slice, '#') continue -3419 # . eax = *word-slice->start -3420 8b/-> *edx 0/r32/eax -3421 8a/copy-byte *eax 0/r32/AL -3422 81 4/subop/and %eax 0xff/imm32 -3423 # . if (eax == '#') continue -3424 3d/compare-eax-and 0x23/imm32/hash -3425 0f 84/jump-if-= loop/disp32 -3426 # if slice-equal?(word-slice, "{") -3427 { -3428 $parse-mu-block:check-for-block: -3429 (slice-equal? %edx "{") -3430 3d/compare-eax-and 0/imm32/false -3431 74/jump-if-= break/disp8 -3432 (check-no-tokens-left %ecx) -3433 # parse new block and append -3434 (parse-mu-block *(ebp+8) *(ebp+0xc) *(ebp+0x10)) # => eax -3435 (append-to-block Heap %edi %eax) -3436 e9/jump $parse-mu-block:line-loop/disp32 -3437 } -3438 # if slice-equal?(word-slice, "}") break -3439 $parse-mu-block:check-for-end: -3440 (slice-equal? %edx "}") -3441 3d/compare-eax-and 0/imm32/false -3442 0f 85/jump-if-!= break/disp32 -3443 # if slice-ends-with?(word-slice, ":") parse named block and append -3444 { -3445 $parse-mu-block:check-for-named-block: -3446 # . eax = *(word-slice->end-1) -3447 8b/-> *(edx+4) 0/r32/eax -3448 48/decrement-eax -3449 8a/copy-byte *eax 0/r32/AL -3450 81 4/subop/and %eax 0xff/imm32 -3451 # . if (eax != ':') break -3452 3d/compare-eax-and 0x3a/imm32/colon -3453 0f 85/jump-if-!= break/disp32 -3454 # TODO: error-check the rest of 'line' -3455 # -3456 # skip ':' -3457 ff 1/subop/decrement *(edx+4) # Slice-end -3458 # -3459 (parse-mu-named-block %edx *(ebp+8) *(ebp+0xc) *(ebp+0x10)) # => eax -3460 (append-to-block Heap %edi %eax) -3461 e9/jump $parse-mu-block:line-loop/disp32 -3462 } -3463 # if slice-equal?(word-slice, "var") -3464 { -3465 $parse-mu-block:check-for-var: -3466 (slice-equal? %edx "var") -3467 3d/compare-eax-and 0/imm32/false -3468 74/jump-if-= break/disp8 -3469 # -3470 (parse-mu-var-def %ecx *(ebp+0xc)) # => eax -3471 (append-to-block Heap %edi %eax) -3472 e9/jump $parse-mu-block:line-loop/disp32 -3473 } -3474 $parse-mu-block:regular-stmt: -3475 # otherwise -3476 (parse-mu-stmt %ecx *(ebp+0xc) *(ebp+0x10)) # => eax -3477 (append-to-block Heap %edi %eax) -3478 e9/jump loop/disp32 -3479 } # end line loop -3480 # decrement *Curr-block-depth -3481 ff 1/subop/decrement *Curr-block-depth -3482 # -3483 (pop *(ebp+0xc)) # => eax -3484 # return result -3485 89/<- %eax 7/r32/edi -3486 $parse-mu-block:end: -3487 # . reclaim locals -3488 81 0/subop/add %esp 0x214/imm32 -3489 # . restore registers -3490 5f/pop-to-edi -3491 5b/pop-to-ebx -3492 5a/pop-to-edx -3493 59/pop-to-ecx -3494 # . epilogue -3495 89/<- %esp 5/r32/ebp -3496 5d/pop-to-ebp -3497 c3/return -3498 -3499 $parse-mu-block:abort: -3500 # error("'{' or '}' should be on its own line, but got '") -3501 (write-buffered Stderr "'{' or '}' should be on its own line, but got '") -3502 (rewind-stream %ecx) -3503 (write-stream 2 %ecx) -3504 (write-buffered Stderr "'\n") -3505 (flush Stderr) -3506 # . syscall(exit, 1) -3507 bb/copy-to-ebx 1/imm32 -3508 b8/copy-to-eax 1/imm32/exit -3509 cd/syscall 0x80/imm8 -3510 # never gets here -3511 -3512 new-block-name: # fn: (handle function) -> result/eax: (handle var) -3513 # . prologue -3514 55/push-ebp -3515 89/<- %ebp 4/r32/esp -3516 # . save registers -3517 51/push-ecx -3518 52/push-edx -3519 # var n/ecx: int = len(fn->name) + 10 for an int + 2 for '$:' -3520 8b/-> *(ebp+8) 0/r32/eax -3521 8b/-> *eax 0/r32/eax # Function-name -3522 8b/-> *eax 0/r32/eax # String-length -3523 05/add-to-eax 0xd/imm32 # 10 + 2 for '$:' -3524 89/<- %ecx 0/r32/eax -3525 # var name/edx: (stream byte n) -3526 29/subtract %esp 1/r32/ecx -3527 ff 6/subop/push %ecx -3528 68/push 0/imm32/read -3529 68/push 0/imm32/write -3530 89/<- %edx 4/r32/esp -3531 (clear-stream %edx) -3532 # eax = fn->name -3533 8b/-> *(ebp+8) 0/r32/eax -3534 8b/-> *eax 0/r32/eax # Function-name -3535 # construct result using Next-block-index (and increment it) -3536 (write %edx "$") -3537 (write %edx %eax) -3538 (write %edx ":") -3539 (print-int32 %edx *Next-block-index) -3540 ff 0/subop/increment *Next-block-index -3541 # var s/eax: slice = {name->data, name->data + name->write} (clobbering edx) -3542 # . eax = name->write -3543 8b/-> *edx 0/r32/eax -3544 # . edx = name->data -3545 8d/copy-address *(edx+0xc) 2/r32/edx -3546 # . eax = name->write + name->data -3547 01/add %eax 2/r32/edx -3548 # . push {edx, eax} -3549 ff 6/subop/push %eax -3550 ff 6/subop/push %edx -3551 89/<- %eax 4/r32/esp -3552 # var final-name/edx: (addr array byte) = slice-to-string(s) -3553 (slice-to-string Heap %eax) # => eax -3554 89/<- %edx 0/r32/eax -3555 # set result->var -3556 # . var type/eax: (handle tree type-id) = literal -3557 (allocate Heap *Tree-size) # => eax -3558 (zero-out %eax *Tree-size) # default type is 'literal' -3559 # . var result/eax: (handle var) = new-var(final-name, type) -3560 (new-var Heap %edx %eax *Curr-block-depth 0 0) # => eax -3561 $new-block-name:end: -3562 # . reclaim locals -3563 81 0/subop/add %ecx 0xc/imm32 # name.{read/write/len} -3564 81 0/subop/add %ecx 8/imm32 # slice -3565 01/add %esp 1/r32/ecx -3566 # . restore registers -3567 5a/pop-to-edx -3568 59/pop-to-ecx -3569 # . epilogue -3570 89/<- %esp 5/r32/ebp -3571 5d/pop-to-ebp -3572 c3/return -3573 -3574 check-no-tokens-left: # line: (addr stream byte) -3575 # . prologue -3576 55/push-ebp -3577 89/<- %ebp 4/r32/esp -3578 # . save registers -3579 50/push-eax -3580 51/push-ecx -3581 # var s/ecx: slice -3582 68/push 0/imm32/end -3583 68/push 0/imm32/start -3584 89/<- %ecx 4/r32/esp -3585 # -3586 (next-mu-token *(ebp+8) %ecx) -3587 # if slice-empty?(s) return -3588 (slice-empty? %ecx) -3589 3d/compare-eax-and 0/imm32/false -3590 75/jump-if-!= $check-no-tokens-left:end/disp8 -3591 # if (slice-starts-with?(s, '#') return -3592 # . eax = *s->start -3593 8b/-> *edx 0/r32/eax -3594 8a/copy-byte *eax 0/r32/AL -3595 81 4/subop/and %eax 0xff/imm32 -3596 # . if (eax == '#') continue -3597 3d/compare-eax-and 0x23/imm32/hash -3598 74/jump-if-= $check-no-tokens-left:end/disp8 -3599 # abort -3600 (write-buffered Stderr "'{' or '}' should be on its own line, but got '") -3601 (rewind-stream %ecx) -3602 (write-stream 2 %ecx) -3603 (write-buffered Stderr "'\n") -3604 (flush Stderr) -3605 # . syscall(exit, 1) -3606 bb/copy-to-ebx 1/imm32 -3607 b8/copy-to-eax 1/imm32/exit -3608 cd/syscall 0x80/imm8 -3609 # never gets here -3610 $check-no-tokens-left:end: -3611 # . reclaim locals -3612 81 0/subop/add %esp 8/imm32 -3613 # . restore registers -3614 59/pop-to-ecx -3615 58/pop-to-eax -3616 # . epilogue -3617 89/<- %esp 5/r32/ebp -3618 5d/pop-to-ebp -3619 c3/return -3620 -3621 parse-mu-named-block: # name: (addr slice), in: (addr buffered-file), vars: (addr stack (handle var)), fn: (handle function) -> result/eax: (handle stmt) -3622 # pseudocode: -3623 # var s: (addr array byte) = slice-to-string(name) -3624 # var v: (handle var) = new-var(s, 0) -3625 # v->block-depth = *Curr-block-depth # containing block depth -3626 # push(vars, v) -3627 # result = parse-mu-block(in, vars, fn) -3628 # pop(vars) -3629 # result->name = s -3630 # return result -3631 # -3632 # . prologue -3633 55/push-ebp -3634 89/<- %ebp 4/r32/esp -3635 # . save registers -3636 51/push-ecx -3637 # var s/ecx: (addr array byte) = slice-to-string(name) -3638 (slice-to-string Heap *(ebp+8)) # => eax -3639 89/<- %ecx 0/r32/eax -3640 # var type/eax: (handle tree type-id) = literal -3641 (allocate Heap *Tree-size) # => eax -3642 (zero-out %eax *Tree-size) # default type is 'literal' -3643 # var v/ecx: (handle var) = new-var(s, type) -3644 (new-var Heap %ecx %eax *Curr-block-depth 0 0) # => eax -3645 89/<- %ecx 0/r32/eax -3646 # push(vars, v) -3647 (push *(ebp+0x10) %ecx) -3648 # eax = result -3649 (parse-mu-block *(ebp+0xc) *(ebp+0x10) *(ebp+0x14)) # => eax -3650 # pop the var -3651 50/push-eax -3652 (pop *(ebp+0x10)) # => eax -3653 58/pop-to-eax -3654 # result->tag = named-block -3655 c7 0/subop/copy *eax 0/imm32/block # Stmt-tag -3656 # result->var = v -3657 89/<- *(eax+8) 1/r32/ecx # Block-var -3658 $parse-mu-named-block:end: -3659 # . restore registers -3660 59/pop-to-ecx -3661 # . epilogue -3662 89/<- %esp 5/r32/ebp -3663 5d/pop-to-ebp -3664 c3/return -3665 -3666 parse-mu-var-def: # line: (addr stream byte), vars: (addr stack (handle var)) -> result/eax: (handle stmt) -3667 # . prologue -3668 55/push-ebp -3669 89/<- %ebp 4/r32/esp -3670 # . save registers -3671 51/push-ecx -3672 52/push-edx -3673 # var word-slice/ecx: slice -3674 68/push 0/imm32/end -3675 68/push 0/imm32/start -3676 89/<- %ecx 4/r32/esp -3677 # var v/edx: (handle var) = parse-var-with-type(line) -3678 (next-mu-token *(ebp+8) %ecx) -3679 (parse-var-with-type %ecx *(ebp+8)) # => eax -3680 89/<- %edx 0/r32/eax -3681 # v->block-depth = *Curr-block-depth -3682 8b/-> *Curr-block-depth 0/r32/eax -3683 89/<- *(edx+8) 0/r32/eax -3684 # -3685 (push *(ebp+0xc) %edx) -3686 # either v has no register and there's no more to this line -3687 8b/-> *(edx+0x10) 0/r32/eax # Var-register -3688 3d/compare-eax-and 0/imm32 -3689 { -3690 75/jump-if-!= break/disp8 -3691 # v->stack-offset = *Next-local-stack-offset -3692 8b/-> *Next-local-stack-offset 0/r32/eax -3693 89/<- *(edx+0xc) 0/r32/eax # Var-stack-offset -3694 # TODO: ensure that there's nothing else on this line -3695 (new-vardef Heap %edx) # => eax -3696 eb/jump $parse-mu-var-def:end/disp8 -3697 } -3698 # or v has a register and there's more to this line -3699 { -3700 74/jump-if-= break/disp8 -3701 # ensure that the next word is '<-' -3702 (next-mu-token *(ebp+8) %ecx) -3703 (slice-equal? %ecx "<-") # => eax -3704 3d/compare-eax-and 0/imm32/false -3705 74/jump-if-= $parse-mu-var-def:abort/disp8 -3706 # -3707 (new-regvardef Heap %edx) # => eax -3708 (add-operation-and-inputs-to-stmt %eax *(ebp+8) *(ebp+0xc)) -3709 } -3710 $parse-mu-var-def:end: -3711 # *Next-local-stack-offset -= size-of(v) -3712 50/push-eax -3713 (size-of %edx) # => eax -3714 29/subtract-from *Next-local-stack-offset 0/r32/eax -3715 58/pop-to-eax -3716 # . reclaim locals -3717 81 0/subop/add %esp 8/imm32 -3718 # . restore registers -3719 5a/pop-to-edx -3720 59/pop-to-ecx -3721 # . epilogue -3722 89/<- %esp 5/r32/ebp -3723 5d/pop-to-ebp -3724 c3/return -3725 -3726 $parse-mu-var-def:abort: -3727 (rewind-stream *(ebp+8)) -3728 # error("register variable requires a valid instruction to initialize but got '" line "'\n") -3729 (write-buffered Stderr "register variable requires a valid instruction to initialize but got '") -3730 (flush Stderr) -3731 (write-stream 2 *(ebp+8)) -3732 (write-buffered Stderr "'\n") -3733 (flush Stderr) -3734 # . syscall(exit, 1) -3735 bb/copy-to-ebx 1/imm32 -3736 b8/copy-to-eax 1/imm32/exit -3737 cd/syscall 0x80/imm8 -3738 # never gets here -3739 -3740 test-parse-mu-var-def: -3741 # 'var n: int' -3742 # . prologue -3743 55/push-ebp -3744 89/<- %ebp 4/r32/esp -3745 # setup -3746 (clear-stream _test-input-stream) -3747 (write _test-input-stream "n: int\n") # caller has consumed the 'var' -3748 c7 0/subop/copy *Curr-block-depth 1/imm32 -3749 c7 0/subop/copy *Next-local-stack-offset -4/imm32 -3750 # var vars/ecx: (stack (addr var) 4) -3751 81 5/subop/subtract %esp 0x10/imm32 -3752 68/push 0x10/imm32/length -3753 68/push 0/imm32/top -3754 89/<- %ecx 4/r32/esp -3755 (clear-stack %ecx) -3756 # convert -3757 (parse-mu-var-def _test-input-stream %ecx) # => eax -3758 # check result -3759 (check-ints-equal *eax 2 "F - test-parse-mu-var-def/tag") # Stmt-tag is vardef -3760 8b/-> *(eax+4) 0/r32/eax # Vardef-var -3761 (check-strings-equal *eax "n" "F - test-parse-mu-var-def/var-name") # Var-name -3762 (check-ints-equal *(eax+0x10) 0 "F - test-parse-mu-var-def/var-register") # Var-register -3763 (check-ints-equal *(eax+8) 1 "F - test-parse-mu-reg-var-def/output-block-depth") # Var-block-depth -3764 (check-ints-equal *(eax+0xc) -4 "F - test-parse-mu-reg-var-def/output-stack-offset") # Var-stack-offset -3765 # ensure type is int -3766 8b/-> *(eax+4) 0/r32/eax # Var-type -3767 (check-ints-equal *eax 1 "F - test-parse-mu-var-def/var-type:0") # Tree-left -3768 (check-ints-equal *(eax+4) 0 "F - test-parse-mu-var-def/var-type:0") # Tree-right -3769 # globals -3770 (check-ints-equal *Next-local-stack-offset -8 "F - test-parse-mu-reg-var-def/Next-local-stack-offset") -3771 # . epilogue -3772 89/<- %esp 5/r32/ebp -3773 5d/pop-to-ebp -3774 c3/return -3775 -3776 test-parse-mu-reg-var-def: -3777 # 'var n/eax: int <- copy 0' -3778 # . prologue -3779 55/push-ebp -3780 89/<- %ebp 4/r32/esp -3781 # setup -3782 (clear-stream _test-input-stream) -3783 (write _test-input-stream "n/eax: int <- copy 0\n") # caller has consumed the 'var' -3784 c7 0/subop/copy *Curr-block-depth 1/imm32 -3785 c7 0/subop/copy *Next-local-stack-offset -4/imm32 -3786 # var vars/ecx: (stack (addr var) 4) -3787 81 5/subop/subtract %esp 0x10/imm32 -3788 68/push 0x10/imm32/length -3789 68/push 0/imm32/top -3790 89/<- %ecx 4/r32/esp -3791 (clear-stack %ecx) -3792 # convert -3793 (parse-mu-var-def _test-input-stream %ecx) # => eax -3794 # check result -3795 (check-ints-equal *eax 3 "F - test-parse-mu-reg-var-def/tag") # Stmt-tag is regvardef -3796 8b/-> *(eax+0xc) 0/r32/eax # Regvardef-outputs -3797 (check-ints-equal *(eax+4) 0 "F - test-parse-mu-reg-var-def/single-output") # List-next -3798 8b/-> *eax 0/r32/eax # Stmt-var-value -3799 (check-strings-equal *eax "n" "F - test-parse-mu-reg-var-def/output-name") # Var-name -3800 (check-strings-equal *(eax+0x10) "eax" "F - test-parse-mu-reg-var-def/output-register") # Var-register -3801 (check-ints-equal *(eax+8) 1 "F - test-parse-mu-reg-var-def/output-block-depth") # Var-block-depth -3802 (check-ints-equal *(eax+0xc) 0 "F - test-parse-mu-reg-var-def/output-stack-offset") # Var-stack-offset -3803 # ensure type is int -3804 8b/-> *(eax+4) 0/r32/eax # Var-type -3805 (check-ints-equal *eax 1 "F - test-parse-mu-reg-var-def/output-type:0") # Tree-left -3806 (check-ints-equal *(eax+4) 0 "F - test-parse-mu-reg-var-def/output-type:0") # Tree-right -3807 # globals -3808 (check-ints-equal *Next-local-stack-offset -8 "F - test-parse-mu-reg-var-def/Next-local-stack-offset") -3809 # . epilogue -3810 89/<- %esp 5/r32/ebp -3811 5d/pop-to-ebp -3812 c3/return -3813 -3814 parse-mu-stmt: # line: (addr stream byte), vars: (addr stack (handle var)), fn: (handle function) -> result/eax: (handle stmt) -3815 # pseudocode: -3816 # var name: slice -3817 # result = allocate(Heap, Stmt-size) -3818 # if stmt-has-outputs?(line) -3819 # while true -3820 # name = next-mu-token(line) -3821 # if (name == '<-') break -3822 # assert(is-identifier?(name)) -3823 # var v: (handle var) = lookup-or-define-var(name, vars, fn) # regular stmts may define vars in fn outputs -3824 # result->outputs = append(result->outputs, v) -3825 # add-operation-and-inputs-to-stmt(result, line, vars) -3826 # -3827 # . prologue -3828 55/push-ebp -3829 89/<- %ebp 4/r32/esp -3830 # . save registers -3831 51/push-ecx -3832 52/push-edx -3833 57/push-edi -3834 # var name/ecx: slice -3835 68/push 0/imm32/end -3836 68/push 0/imm32/start -3837 89/<- %ecx 4/r32/esp -3838 # var is-deref?/edx: boolean = false -3839 ba/copy-to-edx 0/imm32/false -3840 # result/edi: (handle stmt) -3841 (allocate Heap *Stmt-size) # => eax -3842 (zero-out %eax *Stmt-size) -3843 89/<- %edi 0/r32/eax -3844 # result->tag = 1/stmt -3845 c7 0/subop/copy *edi 1/imm32/stmt1 # Stmt-tag -3846 { -3847 (stmt-has-outputs? *(ebp+8)) -3848 3d/compare-eax-and 0/imm32/false -3849 0f 84/jump-if-= break/disp32 -3850 { -3851 $parse-mu-stmt:read-outputs: -3852 # name = next-mu-token(line) -3853 (next-mu-token *(ebp+8) %ecx) -3854 # if slice-empty?(word-slice) break -3855 (slice-empty? %ecx) # => eax -3856 3d/compare-eax-and 0/imm32/false -3857 0f 85/jump-if-!= break/disp32 -3858 # if (name == "<-") break -3859 (slice-equal? %ecx "<-") # => eax -3860 3d/compare-eax-and 0/imm32/false -3861 0f 85/jump-if-!= break/disp32 -3862 # is-deref? = false -3863 ba/copy-to-edx 0/imm32/false -3864 # if (slice-starts-with?(name, '*')) ++name->start and set is-deref? -3865 8b/-> *ecx 0/r32/eax # Slice-start -3866 8a/copy-byte *eax 0/r32/AL -3867 81 4/subop/and %eax 0xff/imm32 -3868 3d/compare-eax-and 0x2a/imm32/asterisk -3869 { -3870 75/jump-if-!= break/disp8 -3871 ff 0/subop/increment *ecx -3872 ba/copy-to-edx 1/imm32/true -3873 } -3874 # assert(is-identifier?(name)) -3875 (is-identifier? %ecx) # => eax -3876 3d/compare-eax-and 0/imm32/false -3877 0f 84/jump-if-= $parse-mu-stmt:abort/disp32 -3878 # result->outputs = new stmt-var(lookup(name, vars, fn), result->outputs, is-deref?) -3879 (lookup-or-define-var %ecx *(ebp+0xc) *(ebp+0x10)) # => eax -3880 (append-stmt-var Heap %eax *(edi+0xc) %edx) # Stmt1-outputs => eax -3881 89/<- *(edi+0xc) 0/r32/eax # Stmt1-outputs -3882 e9/jump loop/disp32 -3883 } -3884 } -3885 (add-operation-and-inputs-to-stmt %edi *(ebp+8) *(ebp+0xc)) -3886 $parse-mu-stmt:end: -3887 # return result -3888 89/<- %eax 7/r32/edi -3889 # . reclaim locals -3890 81 0/subop/add %esp 8/imm32 -3891 # . restore registers -3892 5f/pop-to-edi -3893 5a/pop-to-edx -3894 59/pop-to-ecx -3895 # . epilogue -3896 89/<- %esp 5/r32/ebp -3897 5d/pop-to-ebp -3898 c3/return -3899 -3900 $parse-mu-stmt:abort: -3901 # error("invalid identifier '" name "'\n") -3902 (write-buffered Stderr "invalid identifier '") -3903 (write-slice-buffered Stderr %ecx) -3904 (write-buffered Stderr "'\n") -3905 (flush Stderr) -3906 # . syscall(exit, 1) -3907 bb/copy-to-ebx 1/imm32 -3908 b8/copy-to-eax 1/imm32/exit -3909 cd/syscall 0x80/imm8 -3910 # never gets here -3911 -3912 add-operation-and-inputs-to-stmt: # stmt: (handle stmt), line: (addr stream byte), vars: (addr stack (handle var)) -3913 # pseudocode: -3914 # stmt->name = slice-to-string(next-mu-token(line)) -3915 # while true -3916 # name = next-mu-token(line) -3917 # v = lookup-var-or-literal(name) -3918 # stmt->inouts = append(stmt->inouts, v) -3919 # -3920 # . prologue -3921 55/push-ebp -3922 89/<- %ebp 4/r32/esp -3923 # . save registers -3924 50/push-eax -3925 51/push-ecx -3926 52/push-edx -3927 57/push-edi -3928 # edi = stmt -3929 8b/-> *(ebp+8) 7/r32/edi -3930 # var name/ecx: slice -3931 68/push 0/imm32/end -3932 68/push 0/imm32/start -3933 89/<- %ecx 4/r32/esp -3934 # var is-deref?/edx: boolean = false -3935 ba/copy-to-edx 0/imm32/false -3936 $add-operation-and-inputs-to-stmt:read-operation: -3937 (next-mu-token *(ebp+0xc) %ecx) -3938 (slice-to-string Heap %ecx) # => eax -3939 89/<- *(edi+4) 0/r32/eax # Stmt1-operation or Regvardef-operation -3940 { -3941 $add-operation-and-inputs-to-stmt:read-inouts: -3942 # name = next-mu-token(line) -3943 (next-mu-token *(ebp+0xc) %ecx) -3944 # if slice-empty?(word-slice) break -3945 (slice-empty? %ecx) # => eax -3946 3d/compare-eax-and 0/imm32/false -3947 0f 85/jump-if-!= break/disp32 -3948 # if (name == "<-") abort -3949 (slice-equal? %ecx "<-") -3950 3d/compare-eax-and 0/imm32/false -3951 0f 85/jump-if-!= $add-operation-and-inputs-to-stmt:abort/disp32 -3952 # is-deref? = false -3953 ba/copy-to-edx 0/imm32/false -3954 # if (slice-starts-with?(name, '*')) ++name->start and set is-deref? -3955 8b/-> *ecx 0/r32/eax # Slice-start -3956 8a/copy-byte *eax 0/r32/AL -3957 81 4/subop/and %eax 0xff/imm32 -3958 3d/compare-eax-and 0x2a/imm32/asterisk -3959 { -3960 75/jump-if-!= break/disp8 -3961 ff 0/subop/increment *ecx -3962 ba/copy-to-edx 1/imm32/true -3963 } -3964 (lookup-var-or-literal %ecx *(ebp+0x10)) # => eax -3965 (append-list Heap %eax *(edi+8)) # Stmt1-inouts or Regvardef-inouts => eax -3966 89/<- *(edi+8) 0/r32/eax # Stmt1-inouts or Regvardef-inouts -3967 e9/jump loop/disp32 -3968 } -3969 $add-operation-and-inputs-to-stmt:end: -3970 # . reclaim locals -3971 81 0/subop/add %esp 8/imm32 -3972 # . restore registers -3973 5f/pop-to-edi -3974 5a/pop-to-edx -3975 59/pop-to-ecx -3976 58/pop-to-eax -3977 # . epilogue -3978 89/<- %esp 5/r32/ebp -3979 5d/pop-to-ebp -3980 c3/return -3981 -3982 $add-operation-and-inputs-to-stmt:abort: -3983 # error("invalid statement '" line "'\n") -3984 (rewind-stream *(ebp+8)) -3985 (write-buffered Stderr "invalid identifier '") -3986 (flush Stderr) -3987 (write-stream 2 *(ebp+8)) -3988 (write-buffered Stderr "'\n") -3989 (flush Stderr) -3990 # . syscall(exit, 1) -3991 bb/copy-to-ebx 1/imm32 -3992 b8/copy-to-eax 1/imm32/exit -3993 cd/syscall 0x80/imm8 -3994 # never gets here -3995 -3996 stmt-has-outputs?: # line: (addr stream byte) -> result/eax: boolean -3997 # . prologue -3998 55/push-ebp -3999 89/<- %ebp 4/r32/esp -4000 # . save registers -4001 51/push-ecx -4002 # var word-slice/ecx: slice -4003 68/push 0/imm32/end -4004 68/push 0/imm32/start -4005 89/<- %ecx 4/r32/esp -4006 # result = false -4007 b8/copy-to-eax 0/imm32/false -4008 (rewind-stream *(ebp+8)) -4009 { -4010 (next-mu-token *(ebp+8) %ecx) -4011 # if slice-empty?(word-slice) break -4012 (slice-empty? %ecx) -4013 3d/compare-eax-and 0/imm32/false -4014 b8/copy-to-eax 0/imm32/false/result # restore result (if we're here it's still false) -4015 0f 85/jump-if-!= break/disp32 -4016 # if slice-starts-with?(word-slice, '#') break -4017 # . eax = *word-slice->start -4018 8b/-> *ecx 0/r32/eax -4019 8a/copy-byte *eax 0/r32/AL -4020 81 4/subop/and %eax 0xff/imm32 -4021 # . if (eax == '#') break -4022 3d/compare-eax-and 0x23/imm32/hash -4023 b8/copy-to-eax 0/imm32/false/result # restore result (if we're here it's still false) -4024 0f 84/jump-if-= break/disp32 -4025 # if slice-equal?(word-slice, '<-') return true -4026 (slice-equal? %ecx "<-") -4027 3d/compare-eax-and 0/imm32/false -4028 74/jump-if-= loop/disp8 -4029 b8/copy-to-eax 1/imm32/true -4030 } -4031 $stmt-has-outputs:end: -4032 (rewind-stream *(ebp+8)) -4033 # . reclaim locals -4034 81 0/subop/add %esp 8/imm32 -4035 # . restore registers -4036 59/pop-to-ecx -4037 # . epilogue -4038 89/<- %esp 5/r32/ebp -4039 5d/pop-to-ebp -4040 c3/return -4041 -4042 # if 'name' starts with a digit, create a new literal var for it -4043 # otherwise return first 'name' from the top (back) of 'vars' and abort if not found -4044 lookup-var-or-literal: # name: (addr slice), vars: (addr stack (handle var)) -> result/eax: (handle var) -4045 # . prologue -4046 55/push-ebp -4047 89/<- %ebp 4/r32/esp -4048 # . save registers -4049 51/push-ecx -4050 56/push-esi -4051 # esi = name -4052 8b/-> *(ebp+8) 6/r32/esi -4053 # if slice-empty?(name) abort -4054 (slice-empty? %esi) # => eax -4055 3d/compare-eax-and 0/imm32/false -4056 0f 85/jump-if-!= $lookup-var-or-literal:abort/disp32 -4057 # var c/ecx: byte = *name->start -4058 8b/-> *esi 1/r32/ecx -4059 8a/copy-byte *ecx 1/r32/CL -4060 81 4/subop/and %ecx 0xff/imm32 -4061 # if is-decimal-digit?(c) return new var(name) -4062 { -4063 (is-decimal-digit? %ecx) # => eax -4064 81 7/subop/compare %eax 0/imm32/false -4065 74/jump-if-= break/disp8 -4066 (new-literal-integer Heap %esi) # => eax -4067 eb/jump $lookup-var-or-literal:end/disp8 -4068 } -4069 # else if (c == '"') return new var(name) -4070 { -4071 81 7/subop/compare %ecx 0x22/imm32/dquote -4072 75/jump-if-!= break/disp8 -4073 (new-literal-string Heap %esi) # => eax -4074 eb/jump $lookup-var-or-literal:end/disp8 +3241 test-is-identifier-backtick: +3242 # character before 'a' is invalid +3243 # . prologue +3244 55/push-ebp +3245 89/<- %ebp 4/r32/esp +3246 # (eax..ecx) = "`a" +3247 b8/copy-to-eax "`a"/imm32 +3248 8b/-> *eax 1/r32/ecx +3249 8d/copy-address *(eax+ecx+4) 1/r32/ecx +3250 05/add-to-eax 4/imm32 +3251 # var slice/ecx: slice = {eax, ecx} +3252 51/push-ecx +3253 50/push-eax +3254 89/<- %ecx 4/r32/esp +3255 # +3256 (is-identifier? %ecx) +3257 (check-ints-equal %eax 0 "F - test-is-identifier-backtick") +3258 # . epilogue +3259 89/<- %esp 5/r32/ebp +3260 5d/pop-to-ebp +3261 c3/return +3262 +3263 test-is-identifier-curly-brace-open: +3264 # character after 'z' is invalid; also used for blocks +3265 # . prologue +3266 55/push-ebp +3267 89/<- %ebp 4/r32/esp +3268 # (eax..ecx) = "{a" +3269 b8/copy-to-eax "{a"/imm32 +3270 8b/-> *eax 1/r32/ecx +3271 8d/copy-address *(eax+ecx+4) 1/r32/ecx +3272 05/add-to-eax 4/imm32 +3273 # var slice/ecx: slice = {eax, ecx} +3274 51/push-ecx +3275 50/push-eax +3276 89/<- %ecx 4/r32/esp +3277 # +3278 (is-identifier? %ecx) +3279 (check-ints-equal %eax 0 "F - test-is-identifier-curly-brace-open") +3280 # . epilogue +3281 89/<- %esp 5/r32/ebp +3282 5d/pop-to-ebp +3283 c3/return +3284 +3285 test-is-identifier-curly-brace-close: +3286 # . prologue +3287 55/push-ebp +3288 89/<- %ebp 4/r32/esp +3289 # (eax..ecx) = "}a" +3290 b8/copy-to-eax "}a"/imm32 +3291 8b/-> *eax 1/r32/ecx +3292 8d/copy-address *(eax+ecx+4) 1/r32/ecx +3293 05/add-to-eax 4/imm32 +3294 # var slice/ecx: slice = {eax, ecx} +3295 51/push-ecx +3296 50/push-eax +3297 89/<- %ecx 4/r32/esp +3298 # +3299 (is-identifier? %ecx) +3300 (check-ints-equal %eax 0 "F - test-is-identifier-curly-brace-close") +3301 # . epilogue +3302 89/<- %esp 5/r32/ebp +3303 5d/pop-to-ebp +3304 c3/return +3305 +3306 test-is-identifier-hyphen: +3307 # disallow leading '-' since '->' has special meaning +3308 # . prologue +3309 55/push-ebp +3310 89/<- %ebp 4/r32/esp +3311 # (eax..ecx) = "-a" +3312 b8/copy-to-eax "-a"/imm32 +3313 8b/-> *eax 1/r32/ecx +3314 8d/copy-address *(eax+ecx+4) 1/r32/ecx +3315 05/add-to-eax 4/imm32 +3316 # var slice/ecx: slice = {eax, ecx} +3317 51/push-ecx +3318 50/push-eax +3319 89/<- %ecx 4/r32/esp +3320 # +3321 (is-identifier? %ecx) +3322 (check-ints-equal %eax 0 "F - test-is-identifier-hyphen") +3323 # . epilogue +3324 89/<- %esp 5/r32/ebp +3325 5d/pop-to-ebp +3326 c3/return +3327 +3328 populate-mu-function-body: # in: (addr buffered-file), out: (handle function), vars: (addr stack (handle var)) +3329 # . prologue +3330 55/push-ebp +3331 89/<- %ebp 4/r32/esp +3332 # . save registers +3333 50/push-eax +3334 56/push-esi +3335 57/push-edi +3336 # esi = in +3337 8b/-> *(ebp+8) 6/r32/esi +3338 # edi = out +3339 8b/-> *(ebp+0xc) 7/r32/edi +3340 # initialize some global state +3341 c7 0/subop/copy *Curr-block-depth 1/imm32 +3342 c7 0/subop/copy *Next-local-stack-offset -4/imm32 +3343 # var eax: (handle block) = parse-mu-block(in, vars, fn) +3344 (parse-mu-block %esi *(ebp+0x10) %edi) # => eax +3345 # out->body = eax +3346 89/<- *(edi+0x10) 0/r32/eax # Function-body +3347 $populate-mu-function-body:end: +3348 # . restore registers +3349 5f/pop-to-edi +3350 5e/pop-to-esi +3351 58/pop-to-eax +3352 # . epilogue +3353 89/<- %esp 5/r32/ebp +3354 5d/pop-to-ebp +3355 c3/return +3356 +3357 == data +3358 +3359 # Global state added to each var record when parsing a function +3360 +3361 Curr-block-depth: # (addr int) +3362 0/imm32 +3363 Next-local-stack-offset: # (addr int) +3364 -4/imm32 +3365 +3366 Next-block-index: # (addr int) +3367 1/imm32 +3368 +3369 == code +3370 +3371 # parses a block, assuming that the leading '{' has already been read by the caller +3372 parse-mu-block: # in: (addr buffered-file), vars: (addr stack (handle var)), fn: (handle function) -> result/eax: (handle block) +3373 # pseudocode: +3374 # var line: (stream byte 512) +3375 # var word-slice: slice +3376 # increment *Curr-block-depth +3377 # result/eax = allocate(Heap, Stmt-size) +3378 # result->tag = 0/block +3379 # result->name = some unique name +3380 # while true # line loop +3381 # clear-stream(line) +3382 # read-line-buffered(in, line) +3383 # if (line->write == 0) break # end of file +3384 # word-slice = next-mu-token(line) +3385 # if slice-empty?(word-slice) # end of line +3386 # continue +3387 # else if slice-starts-with?(word-slice, "#") +3388 # continue +3389 # else if slice-equal?(word-slice, "{") +3390 # assert(no-tokens-in(line)) +3391 # block = parse-mu-block(in, vars, fn) +3392 # append-to-block(result, block) +3393 # else if slice-equal?(word-slice, "}") +3394 # break +3395 # else if slice-ends-with?(word-slice, ":") +3396 # # TODO: error-check the rest of 'line' +3397 # --word-slice->end to skip ':' +3398 # named-block = parse-mu-named-block(word-slice, in, vars, fn) +3399 # append-to-block(result, named-block) +3400 # else if slice-equal?(word-slice, "var") +3401 # var-def = parse-mu-var-def(line, vars) +3402 # append-to-block(result, var-def) +3403 # else +3404 # stmt = parse-mu-stmt(line, vars, fn) +3405 # append-to-block(result, stmt) +3406 # decrement *Curr-block-depth +3407 # return result +3408 # +3409 # . prologue +3410 55/push-ebp +3411 89/<- %ebp 4/r32/esp +3412 # . save registers +3413 51/push-ecx +3414 52/push-edx +3415 53/push-ebx +3416 57/push-edi +3417 # var line/ecx: (stream byte 512) +3418 81 5/subop/subtract %esp 0x200/imm32 +3419 68/push 0x200/imm32/length +3420 68/push 0/imm32/read +3421 68/push 0/imm32/write +3422 89/<- %ecx 4/r32/esp +3423 # var word-slice/edx: slice +3424 68/push 0/imm32/end +3425 68/push 0/imm32/start +3426 89/<- %edx 4/r32/esp +3427 # edi = result +3428 (allocate Heap *Stmt-size) # => eax +3429 (zero-out %eax *Stmt-size) +3430 89/<- %edi 0/r32/eax +3431 # set result->tag +3432 c7 0/subop/copy *edi 0/imm32/block # Stmt-tag +3433 # set result->var +3434 (new-block-name *(ebp+0x10)) # => eax +3435 89/<- *(edi+8) 0/r32/eax # Block-var +3436 # push result->var to vars +3437 (push *(ebp+0xc) %eax) +3438 # increment *Curr-block-depth +3439 ff 0/subop/increment *Curr-block-depth +3440 { +3441 $parse-mu-block:line-loop: +3442 # line = read-line-buffered(in) +3443 (clear-stream %ecx) +3444 (read-line-buffered *(ebp+8) %ecx) +3445 #? (write-buffered Stderr "line: ") +3446 #? (write-stream-data Stderr %ecx) +3447 #? (write-buffered Stderr Newline) +3448 #? (flush Stderr) +3449 # if (line->write == 0) break +3450 81 7/subop/compare *ecx 0/imm32 +3451 0f 84/jump-if-= break/disp32 +3452 # word-slice = next-mu-token(line) +3453 (next-mu-token %ecx %edx) +3454 #? (write-buffered Stderr "word: ") +3455 #? (write-slice-buffered Stderr %edx) +3456 #? (write-buffered Stderr Newline) +3457 #? (flush Stderr) +3458 # if slice-empty?(word-slice) continue +3459 (slice-empty? %edx) +3460 3d/compare-eax-and 0/imm32/false +3461 0f 85/jump-if-!= loop/disp32 +3462 # if (slice-starts-with?(word-slice, '#') continue +3463 # . eax = *word-slice->start +3464 8b/-> *edx 0/r32/eax +3465 8a/copy-byte *eax 0/r32/AL +3466 81 4/subop/and %eax 0xff/imm32 +3467 # . if (eax == '#') continue +3468 3d/compare-eax-and 0x23/imm32/hash +3469 0f 84/jump-if-= loop/disp32 +3470 # if slice-equal?(word-slice, "{") +3471 { +3472 $parse-mu-block:check-for-block: +3473 (slice-equal? %edx "{") +3474 3d/compare-eax-and 0/imm32/false +3475 74/jump-if-= break/disp8 +3476 (check-no-tokens-left %ecx) +3477 # parse new block and append +3478 (parse-mu-block *(ebp+8) *(ebp+0xc) *(ebp+0x10)) # => eax +3479 (append-to-block Heap %edi %eax) +3480 e9/jump $parse-mu-block:line-loop/disp32 +3481 } +3482 # if slice-equal?(word-slice, "}") break +3483 $parse-mu-block:check-for-end: +3484 (slice-equal? %edx "}") +3485 3d/compare-eax-and 0/imm32/false +3486 0f 85/jump-if-!= break/disp32 +3487 # if slice-ends-with?(word-slice, ":") parse named block and append +3488 { +3489 $parse-mu-block:check-for-named-block: +3490 # . eax = *(word-slice->end-1) +3491 8b/-> *(edx+4) 0/r32/eax +3492 48/decrement-eax +3493 8a/copy-byte *eax 0/r32/AL +3494 81 4/subop/and %eax 0xff/imm32 +3495 # . if (eax != ':') break +3496 3d/compare-eax-and 0x3a/imm32/colon +3497 0f 85/jump-if-!= break/disp32 +3498 # TODO: error-check the rest of 'line' +3499 # +3500 # skip ':' +3501 ff 1/subop/decrement *(edx+4) # Slice-end +3502 # +3503 (parse-mu-named-block %edx *(ebp+8) *(ebp+0xc) *(ebp+0x10)) # => eax +3504 (append-to-block Heap %edi %eax) +3505 e9/jump $parse-mu-block:line-loop/disp32 +3506 } +3507 # if slice-equal?(word-slice, "var") +3508 { +3509 $parse-mu-block:check-for-var: +3510 (slice-equal? %edx "var") +3511 3d/compare-eax-and 0/imm32/false +3512 74/jump-if-= break/disp8 +3513 # +3514 (parse-mu-var-def %ecx *(ebp+0xc)) # => eax +3515 (append-to-block Heap %edi %eax) +3516 e9/jump $parse-mu-block:line-loop/disp32 +3517 } +3518 $parse-mu-block:regular-stmt: +3519 # otherwise +3520 (parse-mu-stmt %ecx *(ebp+0xc) *(ebp+0x10)) # => eax +3521 (append-to-block Heap %edi %eax) +3522 e9/jump loop/disp32 +3523 } # end line loop +3524 # decrement *Curr-block-depth +3525 ff 1/subop/decrement *Curr-block-depth +3526 # +3527 (pop *(ebp+0xc)) # => eax +3528 # return result +3529 89/<- %eax 7/r32/edi +3530 $parse-mu-block:end: +3531 # . reclaim locals +3532 81 0/subop/add %esp 0x214/imm32 +3533 # . restore registers +3534 5f/pop-to-edi +3535 5b/pop-to-ebx +3536 5a/pop-to-edx +3537 59/pop-to-ecx +3538 # . epilogue +3539 89/<- %esp 5/r32/ebp +3540 5d/pop-to-ebp +3541 c3/return +3542 +3543 $parse-mu-block:abort: +3544 # error("'{' or '}' should be on its own line, but got '") +3545 (write-buffered Stderr "'{' or '}' should be on its own line, but got '") +3546 (rewind-stream %ecx) +3547 (write-stream 2 %ecx) +3548 (write-buffered Stderr "'\n") +3549 (flush Stderr) +3550 # . syscall(exit, 1) +3551 bb/copy-to-ebx 1/imm32 +3552 b8/copy-to-eax 1/imm32/exit +3553 cd/syscall 0x80/imm8 +3554 # never gets here +3555 +3556 new-block-name: # fn: (handle function) -> result/eax: (handle var) +3557 # . prologue +3558 55/push-ebp +3559 89/<- %ebp 4/r32/esp +3560 # . save registers +3561 51/push-ecx +3562 52/push-edx +3563 # var n/ecx: int = len(fn->name) + 10 for an int + 2 for '$:' +3564 8b/-> *(ebp+8) 0/r32/eax +3565 8b/-> *eax 0/r32/eax # Function-name +3566 8b/-> *eax 0/r32/eax # String-length +3567 05/add-to-eax 0xd/imm32 # 10 + 2 for '$:' +3568 89/<- %ecx 0/r32/eax +3569 # var name/edx: (stream byte n) +3570 29/subtract %esp 1/r32/ecx +3571 ff 6/subop/push %ecx +3572 68/push 0/imm32/read +3573 68/push 0/imm32/write +3574 89/<- %edx 4/r32/esp +3575 (clear-stream %edx) +3576 # eax = fn->name +3577 8b/-> *(ebp+8) 0/r32/eax +3578 8b/-> *eax 0/r32/eax # Function-name +3579 # construct result using Next-block-index (and increment it) +3580 (write %edx "$") +3581 (write %edx %eax) +3582 (write %edx ":") +3583 (print-int32 %edx *Next-block-index) +3584 ff 0/subop/increment *Next-block-index +3585 # var s/eax: slice = {name->data, name->data + name->write} (clobbering edx) +3586 # . eax = name->write +3587 8b/-> *edx 0/r32/eax +3588 # . edx = name->data +3589 8d/copy-address *(edx+0xc) 2/r32/edx +3590 # . eax = name->write + name->data +3591 01/add %eax 2/r32/edx +3592 # . push {edx, eax} +3593 ff 6/subop/push %eax +3594 ff 6/subop/push %edx +3595 89/<- %eax 4/r32/esp +3596 # var final-name/edx: (addr array byte) = slice-to-string(s) +3597 (slice-to-string Heap %eax) # => eax +3598 89/<- %edx 0/r32/eax +3599 # set result->var +3600 # . var type/eax: (handle tree type-id) = literal +3601 (allocate Heap *Tree-size) # => eax +3602 (zero-out %eax *Tree-size) # default type is 'literal' +3603 # . var result/eax: (handle var) = new-var(final-name, type) +3604 (new-var Heap %edx %eax *Curr-block-depth 0 0) # => eax +3605 $new-block-name:end: +3606 # . reclaim locals +3607 81 0/subop/add %ecx 0xc/imm32 # name.{read/write/len} +3608 81 0/subop/add %ecx 8/imm32 # slice +3609 01/add %esp 1/r32/ecx +3610 # . restore registers +3611 5a/pop-to-edx +3612 59/pop-to-ecx +3613 # . epilogue +3614 89/<- %esp 5/r32/ebp +3615 5d/pop-to-ebp +3616 c3/return +3617 +3618 check-no-tokens-left: # line: (addr stream byte) +3619 # . prologue +3620 55/push-ebp +3621 89/<- %ebp 4/r32/esp +3622 # . save registers +3623 50/push-eax +3624 51/push-ecx +3625 # var s/ecx: slice +3626 68/push 0/imm32/end +3627 68/push 0/imm32/start +3628 89/<- %ecx 4/r32/esp +3629 # +3630 (next-mu-token *(ebp+8) %ecx) +3631 # if slice-empty?(s) return +3632 (slice-empty? %ecx) +3633 3d/compare-eax-and 0/imm32/false +3634 75/jump-if-!= $check-no-tokens-left:end/disp8 +3635 # if (slice-starts-with?(s, '#') return +3636 # . eax = *s->start +3637 8b/-> *edx 0/r32/eax +3638 8a/copy-byte *eax 0/r32/AL +3639 81 4/subop/and %eax 0xff/imm32 +3640 # . if (eax == '#') continue +3641 3d/compare-eax-and 0x23/imm32/hash +3642 74/jump-if-= $check-no-tokens-left:end/disp8 +3643 # abort +3644 (write-buffered Stderr "'{' or '}' should be on its own line, but got '") +3645 (rewind-stream %ecx) +3646 (write-stream 2 %ecx) +3647 (write-buffered Stderr "'\n") +3648 (flush Stderr) +3649 # . syscall(exit, 1) +3650 bb/copy-to-ebx 1/imm32 +3651 b8/copy-to-eax 1/imm32/exit +3652 cd/syscall 0x80/imm8 +3653 # never gets here +3654 $check-no-tokens-left:end: +3655 # . reclaim locals +3656 81 0/subop/add %esp 8/imm32 +3657 # . restore registers +3658 59/pop-to-ecx +3659 58/pop-to-eax +3660 # . epilogue +3661 89/<- %esp 5/r32/ebp +3662 5d/pop-to-ebp +3663 c3/return +3664 +3665 parse-mu-named-block: # name: (addr slice), in: (addr buffered-file), vars: (addr stack (handle var)), fn: (handle function) -> result/eax: (handle stmt) +3666 # pseudocode: +3667 # var s: (addr array byte) = slice-to-string(name) +3668 # var v: (handle var) = new-var(s, 0) +3669 # v->block-depth = *Curr-block-depth # containing block depth +3670 # push(vars, v) +3671 # result = parse-mu-block(in, vars, fn) +3672 # pop(vars) +3673 # result->name = s +3674 # return result +3675 # +3676 # . prologue +3677 55/push-ebp +3678 89/<- %ebp 4/r32/esp +3679 # . save registers +3680 51/push-ecx +3681 # var s/ecx: (addr array byte) = slice-to-string(name) +3682 (slice-to-string Heap *(ebp+8)) # => eax +3683 89/<- %ecx 0/r32/eax +3684 # var type/eax: (handle tree type-id) = literal +3685 (allocate Heap *Tree-size) # => eax +3686 (zero-out %eax *Tree-size) # default type is 'literal' +3687 # var v/ecx: (handle var) = new-var(s, type) +3688 (new-var Heap %ecx %eax *Curr-block-depth 0 0) # => eax +3689 89/<- %ecx 0/r32/eax +3690 # push(vars, v) +3691 (push *(ebp+0x10) %ecx) +3692 # eax = result +3693 (parse-mu-block *(ebp+0xc) *(ebp+0x10) *(ebp+0x14)) # => eax +3694 # pop the var +3695 50/push-eax +3696 (pop *(ebp+0x10)) # => eax +3697 58/pop-to-eax +3698 # result->tag = named-block +3699 c7 0/subop/copy *eax 0/imm32/block # Stmt-tag +3700 # result->var = v +3701 89/<- *(eax+8) 1/r32/ecx # Block-var +3702 $parse-mu-named-block:end: +3703 # . restore registers +3704 59/pop-to-ecx +3705 # . epilogue +3706 89/<- %esp 5/r32/ebp +3707 5d/pop-to-ebp +3708 c3/return +3709 +3710 parse-mu-var-def: # line: (addr stream byte), vars: (addr stack (handle var)) -> result/eax: (handle stmt) +3711 # . prologue +3712 55/push-ebp +3713 89/<- %ebp 4/r32/esp +3714 # . save registers +3715 51/push-ecx +3716 52/push-edx +3717 # var word-slice/ecx: slice +3718 68/push 0/imm32/end +3719 68/push 0/imm32/start +3720 89/<- %ecx 4/r32/esp +3721 # var v/edx: (handle var) = parse-var-with-type(line) +3722 (next-mu-token *(ebp+8) %ecx) +3723 (parse-var-with-type %ecx *(ebp+8)) # => eax +3724 89/<- %edx 0/r32/eax +3725 # v->block-depth = *Curr-block-depth +3726 8b/-> *Curr-block-depth 0/r32/eax +3727 89/<- *(edx+8) 0/r32/eax +3728 # +3729 (push *(ebp+0xc) %edx) +3730 # either v has no register and there's no more to this line +3731 8b/-> *(edx+0x10) 0/r32/eax # Var-register +3732 3d/compare-eax-and 0/imm32 +3733 { +3734 75/jump-if-!= break/disp8 +3735 # v->stack-offset = *Next-local-stack-offset +3736 8b/-> *Next-local-stack-offset 0/r32/eax +3737 89/<- *(edx+0xc) 0/r32/eax # Var-stack-offset +3738 # TODO: ensure that there's nothing else on this line +3739 (new-vardef Heap %edx) # => eax +3740 eb/jump $parse-mu-var-def:end/disp8 +3741 } +3742 # or v has a register and there's more to this line +3743 { +3744 74/jump-if-= break/disp8 +3745 # ensure that the next word is '<-' +3746 (next-mu-token *(ebp+8) %ecx) +3747 (slice-equal? %ecx "<-") # => eax +3748 3d/compare-eax-and 0/imm32/false +3749 74/jump-if-= $parse-mu-var-def:abort/disp8 +3750 # +3751 (new-regvardef Heap %edx) # => eax +3752 (add-operation-and-inputs-to-stmt %eax *(ebp+8) *(ebp+0xc)) +3753 } +3754 $parse-mu-var-def:end: +3755 # *Next-local-stack-offset -= size-of(v) +3756 50/push-eax +3757 (size-of %edx) # => eax +3758 29/subtract-from *Next-local-stack-offset 0/r32/eax +3759 58/pop-to-eax +3760 # . reclaim locals +3761 81 0/subop/add %esp 8/imm32 +3762 # . restore registers +3763 5a/pop-to-edx +3764 59/pop-to-ecx +3765 # . epilogue +3766 89/<- %esp 5/r32/ebp +3767 5d/pop-to-ebp +3768 c3/return +3769 +3770 $parse-mu-var-def:abort: +3771 (rewind-stream *(ebp+8)) +3772 # error("register variable requires a valid instruction to initialize but got '" line "'\n") +3773 (write-buffered Stderr "register variable requires a valid instruction to initialize but got '") +3774 (flush Stderr) +3775 (write-stream 2 *(ebp+8)) +3776 (write-buffered Stderr "'\n") +3777 (flush Stderr) +3778 # . syscall(exit, 1) +3779 bb/copy-to-ebx 1/imm32 +3780 b8/copy-to-eax 1/imm32/exit +3781 cd/syscall 0x80/imm8 +3782 # never gets here +3783 +3784 test-parse-mu-var-def: +3785 # 'var n: int' +3786 # . prologue +3787 55/push-ebp +3788 89/<- %ebp 4/r32/esp +3789 # setup +3790 (clear-stream _test-input-stream) +3791 (write _test-input-stream "n: int\n") # caller has consumed the 'var' +3792 c7 0/subop/copy *Curr-block-depth 1/imm32 +3793 c7 0/subop/copy *Next-local-stack-offset -4/imm32 +3794 # var vars/ecx: (stack (addr var) 4) +3795 81 5/subop/subtract %esp 0x10/imm32 +3796 68/push 0x10/imm32/length +3797 68/push 0/imm32/top +3798 89/<- %ecx 4/r32/esp +3799 (clear-stack %ecx) +3800 # convert +3801 (parse-mu-var-def _test-input-stream %ecx) # => eax +3802 # check result +3803 (check-ints-equal *eax 2 "F - test-parse-mu-var-def/tag") # Stmt-tag is vardef +3804 8b/-> *(eax+4) 0/r32/eax # Vardef-var +3805 (check-strings-equal *eax "n" "F - test-parse-mu-var-def/var-name") # Var-name +3806 (check-ints-equal *(eax+0x10) 0 "F - test-parse-mu-var-def/var-register") # Var-register +3807 (check-ints-equal *(eax+8) 1 "F - test-parse-mu-reg-var-def/output-block-depth") # Var-block-depth +3808 (check-ints-equal *(eax+0xc) -4 "F - test-parse-mu-reg-var-def/output-stack-offset") # Var-stack-offset +3809 # ensure type is int +3810 8b/-> *(eax+4) 0/r32/eax # Var-type +3811 (check-ints-equal *eax 1 "F - test-parse-mu-var-def/var-type:0") # Tree-left +3812 (check-ints-equal *(eax+4) 0 "F - test-parse-mu-var-def/var-type:0") # Tree-right +3813 # globals +3814 (check-ints-equal *Next-local-stack-offset -8 "F - test-parse-mu-reg-var-def/Next-local-stack-offset") +3815 # . epilogue +3816 89/<- %esp 5/r32/ebp +3817 5d/pop-to-ebp +3818 c3/return +3819 +3820 test-parse-mu-reg-var-def: +3821 # 'var n/eax: int <- copy 0' +3822 # . prologue +3823 55/push-ebp +3824 89/<- %ebp 4/r32/esp +3825 # setup +3826 (clear-stream _test-input-stream) +3827 (write _test-input-stream "n/eax: int <- copy 0\n") # caller has consumed the 'var' +3828 c7 0/subop/copy *Curr-block-depth 1/imm32 +3829 c7 0/subop/copy *Next-local-stack-offset -4/imm32 +3830 # var vars/ecx: (stack (addr var) 4) +3831 81 5/subop/subtract %esp 0x10/imm32 +3832 68/push 0x10/imm32/length +3833 68/push 0/imm32/top +3834 89/<- %ecx 4/r32/esp +3835 (clear-stack %ecx) +3836 # convert +3837 (parse-mu-var-def _test-input-stream %ecx) # => eax +3838 # check result +3839 (check-ints-equal *eax 3 "F - test-parse-mu-reg-var-def/tag") # Stmt-tag is regvardef +3840 8b/-> *(eax+0xc) 0/r32/eax # Regvardef-outputs +3841 (check-ints-equal *(eax+4) 0 "F - test-parse-mu-reg-var-def/single-output") # List-next +3842 8b/-> *eax 0/r32/eax # Stmt-var-value +3843 (check-strings-equal *eax "n" "F - test-parse-mu-reg-var-def/output-name") # Var-name +3844 (check-strings-equal *(eax+0x10) "eax" "F - test-parse-mu-reg-var-def/output-register") # Var-register +3845 (check-ints-equal *(eax+8) 1 "F - test-parse-mu-reg-var-def/output-block-depth") # Var-block-depth +3846 (check-ints-equal *(eax+0xc) 0 "F - test-parse-mu-reg-var-def/output-stack-offset") # Var-stack-offset +3847 # ensure type is int +3848 8b/-> *(eax+4) 0/r32/eax # Var-type +3849 (check-ints-equal *eax 1 "F - test-parse-mu-reg-var-def/output-type:0") # Tree-left +3850 (check-ints-equal *(eax+4) 0 "F - test-parse-mu-reg-var-def/output-type:0") # Tree-right +3851 # globals +3852 (check-ints-equal *Next-local-stack-offset -8 "F - test-parse-mu-reg-var-def/Next-local-stack-offset") +3853 # . epilogue +3854 89/<- %esp 5/r32/ebp +3855 5d/pop-to-ebp +3856 c3/return +3857 +3858 parse-mu-stmt: # line: (addr stream byte), vars: (addr stack (handle var)), fn: (handle function) -> result/eax: (handle stmt) +3859 # pseudocode: +3860 # var name: slice +3861 # result = allocate(Heap, Stmt-size) +3862 # if stmt-has-outputs?(line) +3863 # while true +3864 # name = next-mu-token(line) +3865 # if (name == '<-') break +3866 # assert(is-identifier?(name)) +3867 # var v: (handle var) = lookup-or-define-var(name, vars, fn) # regular stmts may define vars in fn outputs +3868 # result->outputs = append(result->outputs, v) +3869 # add-operation-and-inputs-to-stmt(result, line, vars) +3870 # +3871 # . prologue +3872 55/push-ebp +3873 89/<- %ebp 4/r32/esp +3874 # . save registers +3875 51/push-ecx +3876 52/push-edx +3877 57/push-edi +3878 # var name/ecx: slice +3879 68/push 0/imm32/end +3880 68/push 0/imm32/start +3881 89/<- %ecx 4/r32/esp +3882 # var is-deref?/edx: boolean = false +3883 ba/copy-to-edx 0/imm32/false +3884 # result/edi: (handle stmt) +3885 (allocate Heap *Stmt-size) # => eax +3886 (zero-out %eax *Stmt-size) +3887 89/<- %edi 0/r32/eax +3888 # result->tag = 1/stmt +3889 c7 0/subop/copy *edi 1/imm32/stmt1 # Stmt-tag +3890 { +3891 (stmt-has-outputs? *(ebp+8)) +3892 3d/compare-eax-and 0/imm32/false +3893 0f 84/jump-if-= break/disp32 +3894 { +3895 $parse-mu-stmt:read-outputs: +3896 # name = next-mu-token(line) +3897 (next-mu-token *(ebp+8) %ecx) +3898 # if slice-empty?(word-slice) break +3899 (slice-empty? %ecx) # => eax +3900 3d/compare-eax-and 0/imm32/false +3901 0f 85/jump-if-!= break/disp32 +3902 # if (name == "<-") break +3903 (slice-equal? %ecx "<-") # => eax +3904 3d/compare-eax-and 0/imm32/false +3905 0f 85/jump-if-!= break/disp32 +3906 # is-deref? = false +3907 ba/copy-to-edx 0/imm32/false +3908 # if (slice-starts-with?(name, '*')) ++name->start and set is-deref? +3909 8b/-> *ecx 0/r32/eax # Slice-start +3910 8a/copy-byte *eax 0/r32/AL +3911 81 4/subop/and %eax 0xff/imm32 +3912 3d/compare-eax-and 0x2a/imm32/asterisk +3913 { +3914 75/jump-if-!= break/disp8 +3915 ff 0/subop/increment *ecx +3916 ba/copy-to-edx 1/imm32/true +3917 } +3918 # assert(is-identifier?(name)) +3919 (is-identifier? %ecx) # => eax +3920 3d/compare-eax-and 0/imm32/false +3921 0f 84/jump-if-= $parse-mu-stmt:abort/disp32 +3922 # result->outputs = new stmt-var(lookup(name, vars, fn), result->outputs, is-deref?) +3923 (lookup-or-define-var %ecx *(ebp+0xc) *(ebp+0x10)) # => eax +3924 (append-stmt-var Heap %eax *(edi+0xc) %edx) # Stmt1-outputs => eax +3925 89/<- *(edi+0xc) 0/r32/eax # Stmt1-outputs +3926 e9/jump loop/disp32 +3927 } +3928 } +3929 (add-operation-and-inputs-to-stmt %edi *(ebp+8) *(ebp+0xc)) +3930 $parse-mu-stmt:end: +3931 # return result +3932 89/<- %eax 7/r32/edi +3933 # . reclaim locals +3934 81 0/subop/add %esp 8/imm32 +3935 # . restore registers +3936 5f/pop-to-edi +3937 5a/pop-to-edx +3938 59/pop-to-ecx +3939 # . epilogue +3940 89/<- %esp 5/r32/ebp +3941 5d/pop-to-ebp +3942 c3/return +3943 +3944 $parse-mu-stmt:abort: +3945 # error("invalid identifier '" name "'\n") +3946 (write-buffered Stderr "invalid identifier '") +3947 (write-slice-buffered Stderr %ecx) +3948 (write-buffered Stderr "'\n") +3949 (flush Stderr) +3950 # . syscall(exit, 1) +3951 bb/copy-to-ebx 1/imm32 +3952 b8/copy-to-eax 1/imm32/exit +3953 cd/syscall 0x80/imm8 +3954 # never gets here +3955 +3956 add-operation-and-inputs-to-stmt: # stmt: (handle stmt), line: (addr stream byte), vars: (addr stack (handle var)) +3957 # pseudocode: +3958 # stmt->name = slice-to-string(next-mu-token(line)) +3959 # while true +3960 # name = next-mu-token(line) +3961 # v = lookup-var-or-literal(name) +3962 # stmt->inouts = append(stmt->inouts, v) +3963 # +3964 # . prologue +3965 55/push-ebp +3966 89/<- %ebp 4/r32/esp +3967 # . save registers +3968 50/push-eax +3969 51/push-ecx +3970 52/push-edx +3971 57/push-edi +3972 # edi = stmt +3973 8b/-> *(ebp+8) 7/r32/edi +3974 # var name/ecx: slice +3975 68/push 0/imm32/end +3976 68/push 0/imm32/start +3977 89/<- %ecx 4/r32/esp +3978 # var is-deref?/edx: boolean = false +3979 ba/copy-to-edx 0/imm32/false +3980 $add-operation-and-inputs-to-stmt:read-operation: +3981 (next-mu-token *(ebp+0xc) %ecx) +3982 (slice-to-string Heap %ecx) # => eax +3983 89/<- *(edi+4) 0/r32/eax # Stmt1-operation or Regvardef-operation +3984 { +3985 $add-operation-and-inputs-to-stmt:read-inouts: +3986 # name = next-mu-token(line) +3987 (next-mu-token *(ebp+0xc) %ecx) +3988 # if slice-empty?(word-slice) break +3989 (slice-empty? %ecx) # => eax +3990 3d/compare-eax-and 0/imm32/false +3991 0f 85/jump-if-!= break/disp32 +3992 # if (name == "<-") abort +3993 (slice-equal? %ecx "<-") +3994 3d/compare-eax-and 0/imm32/false +3995 0f 85/jump-if-!= $add-operation-and-inputs-to-stmt:abort/disp32 +3996 # is-deref? = false +3997 ba/copy-to-edx 0/imm32/false +3998 # if (slice-starts-with?(name, '*')) ++name->start and set is-deref? +3999 8b/-> *ecx 0/r32/eax # Slice-start +4000 8a/copy-byte *eax 0/r32/AL +4001 81 4/subop/and %eax 0xff/imm32 +4002 3d/compare-eax-and 0x2a/imm32/asterisk +4003 { +4004 75/jump-if-!= break/disp8 +4005 $add-operation-and-inputs-to-stmt:inout-is-deref: +4006 ff 0/subop/increment *ecx +4007 ba/copy-to-edx 1/imm32/true +4008 } +4009 (lookup-var-or-literal %ecx *(ebp+0x10)) # => eax +4010 (append-stmt-var Heap %eax *(edi+8) %edx) # Stmt1-inouts or Regvardef-inouts => eax +4011 89/<- *(edi+8) 0/r32/eax # Stmt1-inouts or Regvardef-inouts +4012 e9/jump loop/disp32 +4013 } +4014 $add-operation-and-inputs-to-stmt:end: +4015 # . reclaim locals +4016 81 0/subop/add %esp 8/imm32 +4017 # . restore registers +4018 5f/pop-to-edi +4019 5a/pop-to-edx +4020 59/pop-to-ecx +4021 58/pop-to-eax +4022 # . epilogue +4023 89/<- %esp 5/r32/ebp +4024 5d/pop-to-ebp +4025 c3/return +4026 +4027 $add-operation-and-inputs-to-stmt:abort: +4028 # error("invalid statement '" line "'\n") +4029 (rewind-stream *(ebp+8)) +4030 (write-buffered Stderr "invalid identifier '") +4031 (flush Stderr) +4032 (write-stream 2 *(ebp+8)) +4033 (write-buffered Stderr "'\n") +4034 (flush Stderr) +4035 # . syscall(exit, 1) +4036 bb/copy-to-ebx 1/imm32 +4037 b8/copy-to-eax 1/imm32/exit +4038 cd/syscall 0x80/imm8 +4039 # never gets here +4040 +4041 stmt-has-outputs?: # line: (addr stream byte) -> result/eax: boolean +4042 # . prologue +4043 55/push-ebp +4044 89/<- %ebp 4/r32/esp +4045 # . save registers +4046 51/push-ecx +4047 # var word-slice/ecx: slice +4048 68/push 0/imm32/end +4049 68/push 0/imm32/start +4050 89/<- %ecx 4/r32/esp +4051 # result = false +4052 b8/copy-to-eax 0/imm32/false +4053 (rewind-stream *(ebp+8)) +4054 { +4055 (next-mu-token *(ebp+8) %ecx) +4056 # if slice-empty?(word-slice) break +4057 (slice-empty? %ecx) +4058 3d/compare-eax-and 0/imm32/false +4059 b8/copy-to-eax 0/imm32/false/result # restore result (if we're here it's still false) +4060 0f 85/jump-if-!= break/disp32 +4061 # if slice-starts-with?(word-slice, '#') break +4062 # . eax = *word-slice->start +4063 8b/-> *ecx 0/r32/eax +4064 8a/copy-byte *eax 0/r32/AL +4065 81 4/subop/and %eax 0xff/imm32 +4066 # . if (eax == '#') break +4067 3d/compare-eax-and 0x23/imm32/hash +4068 b8/copy-to-eax 0/imm32/false/result # restore result (if we're here it's still false) +4069 0f 84/jump-if-= break/disp32 +4070 # if slice-equal?(word-slice, '<-') return true +4071 (slice-equal? %ecx "<-") +4072 3d/compare-eax-and 0/imm32/false +4073 74/jump-if-= loop/disp8 +4074 b8/copy-to-eax 1/imm32/true 4075 } -4076 # otherwise return lookup-var(name, vars) -4077 { -4078 (lookup-var %esi *(ebp+0xc)) # => eax -4079 } -4080 $lookup-var-or-literal:end: -4081 # . restore registers -4082 5e/pop-to-esi -4083 59/pop-to-ecx -4084 # . epilogue -4085 89/<- %esp 5/r32/ebp -4086 5d/pop-to-ebp -4087 c3/return -4088 -4089 $lookup-var-or-literal:abort: -4090 (write-buffered Stderr "empty variable!") -4091 (flush Stderr) -4092 # . syscall(exit, 1) -4093 bb/copy-to-ebx 1/imm32 -4094 b8/copy-to-eax 1/imm32/exit -4095 cd/syscall 0x80/imm8 -4096 # never gets here -4097 -4098 # return first 'name' from the top (back) of 'vars' and abort if not found -4099 lookup-var: # name: (addr slice), vars: (addr stack (handle var)) -> result/eax: (handle var) -4100 # . prologue -4101 55/push-ebp -4102 89/<- %ebp 4/r32/esp -4103 # var target/eax: (handle array byte) = slice-to-string(name) -4104 (slice-to-string Heap *(ebp+8)) # => eax -4105 # -4106 (lookup-var-helper %eax *(ebp+0xc)) # => eax -4107 # if (result == 0) abort -4108 3d/compare-eax-and 0/imm32 -4109 74/jump-if-= $lookup-var:abort/disp8 -4110 $lookup-var:end: -4111 # . epilogue -4112 89/<- %esp 5/r32/ebp -4113 5d/pop-to-ebp -4114 c3/return -4115 -4116 $lookup-var:abort: -4117 (write-buffered Stderr "unknown variable '") -4118 (write-slice-buffered Stderr *(ebp+8)) -4119 (write-buffered Stderr "'\n") -4120 (flush Stderr) -4121 # . syscall(exit, 1) -4122 bb/copy-to-ebx 1/imm32 -4123 b8/copy-to-eax 1/imm32/exit -4124 cd/syscall 0x80/imm8 -4125 # never gets here -4126 -4127 # return first 'name' from the top (back) of 'vars', and 0/null if not found -4128 lookup-var-helper: # name: (addr array byte), vars: (addr stack (handle var)) -> result/eax: (handle var) -4129 # pseudocode: -4130 # var curr: (addr handle var) = &vars->data[vars->top - 4] -4131 # var min = vars->data -4132 # while curr >= min -4133 # var v: (handle var) = *curr -4134 # if v->name == name -4135 # return v -4136 # return 0 -4137 # -4138 # . prologue -4139 55/push-ebp -4140 89/<- %ebp 4/r32/esp -4141 # . save registers -4142 52/push-edx -4143 53/push-ebx -4144 56/push-esi -4145 # esi = vars -4146 8b/-> *(ebp+0xc) 6/r32/esi -4147 # ebx = vars->top -4148 8b/-> *esi 3/r32/ebx -4149 # if (vars->top > vars->length) abort -4150 3b/compare 0/r32/eax *(esi+4) -4151 0f 8f/jump-if-> $lookup-var-helper:error1/disp32 -4152 # var min/edx: (addr handle var) = vars->data -4153 8d/copy-address *(esi+8) 2/r32/edx -4154 # var curr/ebx: (addr handle var) = &vars->data[vars->top - 4] -4155 81 5/subop/subtract %ebx 4/imm32 -4156 8d/copy-address *(esi+ebx+8) 3/r32/ebx -4157 { -4158 # if (curr < min) return 0 -4159 39/compare %ebx 2/r32/edx -4160 b8/copy-to-eax 0/imm32 -4161 0f 82/jump-if-addr< break/disp32 -4162 # var v/eax: (handle var) = *curr -4163 8b/-> *ebx 0/r32/eax -4164 # if (v->name == name) return v -4165 (string-equal? *eax *(ebp+8)) # Var-name -4166 3d/compare-eax-and 0/imm32/false -4167 8b/-> *ebx 0/r32/eax -4168 75/jump-if-!= break/disp8 -4169 # curr -= 4 -4170 81 5/subop/subtract %ebx 4/imm32 -4171 e9/jump loop/disp32 -4172 } -4173 $lookup-var-helper:end: -4174 # . restore registers -4175 5e/pop-to-esi -4176 5b/pop-to-ebx -4177 5a/pop-to-edx -4178 # . epilogue -4179 89/<- %esp 5/r32/ebp -4180 5d/pop-to-ebp -4181 c3/return -4182 -4183 $lookup-var-helper:error1: -4184 (write-buffered Stderr "malformed stack when looking up '") -4185 (write-slice-buffered Stderr *(ebp+8)) -4186 (write-buffered Stderr "'\n") -4187 (flush Stderr) -4188 # . syscall(exit, 1) -4189 bb/copy-to-ebx 1/imm32 -4190 b8/copy-to-eax 1/imm32/exit -4191 cd/syscall 0x80/imm8 -4192 # never gets here -4193 -4194 # return first 'name' from the top (back) of 'vars' and create a new var for a fn output if not found -4195 lookup-or-define-var: # name: (addr slice), vars: (addr stack (handle var)), fn: (handle function) -> result/eax: (handle var) -4196 # . prologue -4197 55/push-ebp -4198 89/<- %ebp 4/r32/esp -4199 # . save registers -4200 51/push-ecx -4201 # var target/ecx: (handle array byte) = slice-to-string(name) -4202 (slice-to-string Heap *(ebp+8)) # => eax -4203 89/<- %ecx 0/r32/eax -4204 # -4205 (lookup-var-helper %ecx *(ebp+0xc)) # => eax -4206 { -4207 # if (result != 0) return -4208 3d/compare-eax-and 0/imm32 -4209 75/jump-if-!= break/disp8 -4210 # if name is one of fn's outputs, return it -4211 { -4212 (find-in-function-outputs *(ebp+0x10) %ecx) # => eax -4213 3d/compare-eax-and 0/imm32 -4214 # otherwise abort -4215 0f 84/jump-if-!= $lookup-var:abort/disp32 -4216 } +4076 $stmt-has-outputs:end: +4077 (rewind-stream *(ebp+8)) +4078 # . reclaim locals +4079 81 0/subop/add %esp 8/imm32 +4080 # . restore registers +4081 59/pop-to-ecx +4082 # . epilogue +4083 89/<- %esp 5/r32/ebp +4084 5d/pop-to-ebp +4085 c3/return +4086 +4087 # if 'name' starts with a digit, create a new literal var for it +4088 # otherwise return first 'name' from the top (back) of 'vars' and abort if not found +4089 lookup-var-or-literal: # name: (addr slice), vars: (addr stack (handle var)) -> result/eax: (handle var) +4090 # . prologue +4091 55/push-ebp +4092 89/<- %ebp 4/r32/esp +4093 # . save registers +4094 51/push-ecx +4095 56/push-esi +4096 # esi = name +4097 8b/-> *(ebp+8) 6/r32/esi +4098 # if slice-empty?(name) abort +4099 (slice-empty? %esi) # => eax +4100 3d/compare-eax-and 0/imm32/false +4101 0f 85/jump-if-!= $lookup-var-or-literal:abort/disp32 +4102 # var c/ecx: byte = *name->start +4103 8b/-> *esi 1/r32/ecx +4104 8a/copy-byte *ecx 1/r32/CL +4105 81 4/subop/and %ecx 0xff/imm32 +4106 # if is-decimal-digit?(c) return new var(name) +4107 { +4108 (is-decimal-digit? %ecx) # => eax +4109 81 7/subop/compare %eax 0/imm32/false +4110 74/jump-if-= break/disp8 +4111 (new-literal-integer Heap %esi) # => eax +4112 eb/jump $lookup-var-or-literal:end/disp8 +4113 } +4114 # else if (c == '"') return new var(name) +4115 { +4116 81 7/subop/compare %ecx 0x22/imm32/dquote +4117 75/jump-if-!= break/disp8 +4118 (new-literal-string Heap %esi) # => eax +4119 eb/jump $lookup-var-or-literal:end/disp8 +4120 } +4121 # otherwise return lookup-var(name, vars) +4122 { +4123 (lookup-var %esi *(ebp+0xc)) # => eax +4124 } +4125 $lookup-var-or-literal:end: +4126 # . restore registers +4127 5e/pop-to-esi +4128 59/pop-to-ecx +4129 # . epilogue +4130 89/<- %esp 5/r32/ebp +4131 5d/pop-to-ebp +4132 c3/return +4133 +4134 $lookup-var-or-literal:abort: +4135 (write-buffered Stderr "empty variable!") +4136 (flush Stderr) +4137 # . syscall(exit, 1) +4138 bb/copy-to-ebx 1/imm32 +4139 b8/copy-to-eax 1/imm32/exit +4140 cd/syscall 0x80/imm8 +4141 # never gets here +4142 +4143 # return first 'name' from the top (back) of 'vars' and abort if not found +4144 lookup-var: # name: (addr slice), vars: (addr stack (handle var)) -> result/eax: (handle var) +4145 # . prologue +4146 55/push-ebp +4147 89/<- %ebp 4/r32/esp +4148 # var target/eax: (handle array byte) = slice-to-string(name) +4149 (slice-to-string Heap *(ebp+8)) # => eax +4150 # +4151 (lookup-var-helper %eax *(ebp+0xc)) # => eax +4152 # if (result == 0) abort +4153 3d/compare-eax-and 0/imm32 +4154 74/jump-if-= $lookup-var:abort/disp8 +4155 $lookup-var:end: +4156 # . epilogue +4157 89/<- %esp 5/r32/ebp +4158 5d/pop-to-ebp +4159 c3/return +4160 +4161 $lookup-var:abort: +4162 (write-buffered Stderr "unknown variable '") +4163 (write-slice-buffered Stderr *(ebp+8)) +4164 (write-buffered Stderr "'\n") +4165 (flush Stderr) +4166 # . syscall(exit, 1) +4167 bb/copy-to-ebx 1/imm32 +4168 b8/copy-to-eax 1/imm32/exit +4169 cd/syscall 0x80/imm8 +4170 # never gets here +4171 +4172 # return first 'name' from the top (back) of 'vars', and 0/null if not found +4173 lookup-var-helper: # name: (addr array byte), vars: (addr stack (handle var)) -> result/eax: (handle var) +4174 # pseudocode: +4175 # var curr: (addr handle var) = &vars->data[vars->top - 4] +4176 # var min = vars->data +4177 # while curr >= min +4178 # var v: (handle var) = *curr +4179 # if v->name == name +4180 # return v +4181 # return 0 +4182 # +4183 # . prologue +4184 55/push-ebp +4185 89/<- %ebp 4/r32/esp +4186 # . save registers +4187 52/push-edx +4188 53/push-ebx +4189 56/push-esi +4190 # esi = vars +4191 8b/-> *(ebp+0xc) 6/r32/esi +4192 # ebx = vars->top +4193 8b/-> *esi 3/r32/ebx +4194 # if (vars->top > vars->length) abort +4195 3b/compare 0/r32/eax *(esi+4) +4196 0f 8f/jump-if-> $lookup-var-helper:error1/disp32 +4197 # var min/edx: (addr handle var) = vars->data +4198 8d/copy-address *(esi+8) 2/r32/edx +4199 # var curr/ebx: (addr handle var) = &vars->data[vars->top - 4] +4200 81 5/subop/subtract %ebx 4/imm32 +4201 8d/copy-address *(esi+ebx+8) 3/r32/ebx +4202 { +4203 # if (curr < min) return 0 +4204 39/compare %ebx 2/r32/edx +4205 b8/copy-to-eax 0/imm32 +4206 0f 82/jump-if-addr< break/disp32 +4207 # var v/eax: (handle var) = *curr +4208 8b/-> *ebx 0/r32/eax +4209 # if (v->name == name) return v +4210 (string-equal? *eax *(ebp+8)) # Var-name +4211 3d/compare-eax-and 0/imm32/false +4212 8b/-> *ebx 0/r32/eax +4213 75/jump-if-!= break/disp8 +4214 # curr -= 4 +4215 81 5/subop/subtract %ebx 4/imm32 +4216 e9/jump loop/disp32 4217 } -4218 $lookup-or-define-var:end: +4218 $lookup-var-helper:end: 4219 # . restore registers -4220 59/pop-to-ecx -4221 # . epilogue -4222 89/<- %esp 5/r32/ebp -4223 5d/pop-to-ebp -4224 c3/return -4225 -4226 find-in-function-outputs: # fn: (handle function), name: (handle array byte) -> result/eax: (handle var) -4227 # . prologue -4228 55/push-ebp -4229 89/<- %ebp 4/r32/esp -4230 # . save registers -4231 51/push-ecx -4232 # var curr/ecx: (handle list var) = fn->outputs -4233 8b/-> *(ebp+8) 1/r32/ecx -4234 8b/-> *(ecx+0xc) 1/r32/ecx -4235 # while curr != null -4236 { -4237 81 7/subop/compare %ecx 0/imm32 -4238 74/jump-if-= break/disp8 -4239 # var v: (handle var) = *curr -4240 8b/-> *ecx 0/r32/eax # List-value -4241 # if (curr->name == name) return curr -4242 50/push-eax -4243 (string-equal? *eax *(ebp+0xc)) -4244 3d/compare-eax-and 0/imm32/false -4245 58/pop-to-eax -4246 75/jump-if-!= $find-in-function-outputs:end/disp8 -4247 # curr = curr->next -4248 8b/-> *(ecx+4) 1/r32/ecx # List-next -4249 eb/jump loop/disp8 -4250 } -4251 b8/copy-to-eax 0/imm32 -4252 $find-in-function-outputs:end: -4253 # . restore registers -4254 59/pop-to-ecx -4255 # . epilogue -4256 89/<- %esp 5/r32/ebp -4257 5d/pop-to-ebp -4258 c3/return -4259 -4260 test-parse-mu-stmt: -4261 # . prologue -4262 55/push-ebp -4263 89/<- %ebp 4/r32/esp -4264 # setup -4265 (clear-stream _test-input-stream) -4266 (write _test-input-stream "increment n\n") -4267 # var vars/ecx: (stack (addr var) 4) -4268 81 5/subop/subtract %esp 0x10/imm32 -4269 68/push 0x10/imm32/length -4270 68/push 0/imm32/top -4271 89/<- %ecx 4/r32/esp -4272 (clear-stack %ecx) -4273 # var v/edx: var -4274 81 5/subop/subtract %esp 0x14/imm32 # Var-size -4275 89/<- %edx 4/r32/esp -4276 (zero-out %edx 0x14) # Var-size -4277 # v->name = "n" -4278 c7 0/subop/copy *edx "n"/imm32 # Var-name -4279 # -4280 (push %ecx %edx) -4281 # convert -4282 (parse-mu-stmt _test-input-stream %ecx) # => eax -4283 # check result -4284 (check-ints-equal *eax 1 "F - test-parse-mu-stmt/tag") # Stmt-tag is Stmt1 -4285 (check-strings-equal *(eax+4) "increment" "F - test-parse-mu-stmt/name") # Stmt1-operation -4286 # edx: (handle list var) = result->inouts -4287 8b/-> *(eax+8) 2/r32/edx # Stmt1-inouts -4288 # ebx: (handle var) = result->inouts->value -4289 8b/-> *edx 3/r32/ebx # Stmt-var-value -4290 (check-strings-equal *ebx "n" "F - test-parse-mu-stmt/inout:0") # Var-name -4291 # . epilogue -4292 89/<- %esp 5/r32/ebp -4293 5d/pop-to-ebp -4294 c3/return -4295 -4296 test-parse-mu-stmt-with-comma: -4297 # . prologue -4298 55/push-ebp -4299 89/<- %ebp 4/r32/esp -4300 # setup -4301 (clear-stream _test-input-stream) -4302 (write _test-input-stream "copy-to n, 3\n") -4303 # var vars/ecx: (stack (addr var) 4) -4304 81 5/subop/subtract %esp 0x10/imm32 -4305 68/push 0x10/imm32/length -4306 68/push 0/imm32/top -4307 89/<- %ecx 4/r32/esp -4308 (clear-stack %ecx) -4309 # var v/edx: var -4310 81 5/subop/subtract %esp 0x14/imm32 # Var-size -4311 89/<- %edx 4/r32/esp -4312 (zero-out %edx 0x14) # Var-size -4313 # v->name = "n" -4314 c7 0/subop/copy *edx "n"/imm32 # Var-name -4315 # -4316 (push %ecx %edx) -4317 # convert -4318 (parse-mu-stmt _test-input-stream %ecx) # => eax -4319 # check result -4320 (check-ints-equal *eax 1 "F - test-parse-mu-stmt-with-comma/tag") # Stmt-tag is Stmt1 -4321 (check-strings-equal *(eax+4) "copy-to" "F - test-parse-mu-stmt-with-comma/name") # Stmt1-operation -4322 # edx: (handle list var) = result->inouts -4323 8b/-> *(eax+8) 2/r32/edx # Stmt1-inouts -4324 # ebx: (handle var) = result->inouts->value -4325 8b/-> *edx 3/r32/ebx # Stmt-var-value -4326 (check-strings-equal *ebx "n" "F - test-parse-mu-stmt-with-comma/inout:0") # Var-name -4327 # . epilogue -4328 89/<- %esp 5/r32/ebp -4329 5d/pop-to-ebp -4330 c3/return -4331 -4332 new-function: # ad: (addr allocation-descriptor), name: (addr array byte), subx-name: (addr array byte), inouts: (handle list var), outputs: (handle list var), body: (handle block), next: (handle function) -> result/eax: (handle function) -4333 # . prologue -4334 55/push-ebp -4335 89/<- %ebp 4/r32/esp -4336 # . save registers -4337 51/push-ecx -4338 # -4339 (allocate *(ebp+8) *Function-size) # => eax -4340 8b/-> *(ebp+0xc) 1/r32/ecx -4341 89/<- *eax 1/r32/ecx # Function-name -4342 8b/-> *(ebp+0x10) 1/r32/ecx -4343 89/<- *(eax+4) 1/r32/ecx # Function-subx-name -4344 8b/-> *(ebp+0x14) 1/r32/ecx -4345 89/<- *(eax+8) 1/r32/ecx # Function-inouts -4346 8b/-> *(ebp+0x18) 1/r32/ecx -4347 89/<- *(eax+0xc) 1/r32/ecx # Function-outputs -4348 8b/-> *(ebp+0x1c) 1/r32/ecx -4349 89/<- *(eax+0x10) 1/r32/ecx # Function-body -4350 8b/-> *(ebp+0x20) 1/r32/ecx -4351 89/<- *(eax+0x14) 1/r32/ecx # Function-next -4352 $new-function:end: -4353 # . restore registers -4354 59/pop-to-ecx -4355 # . epilogue -4356 89/<- %esp 5/r32/ebp -4357 5d/pop-to-ebp -4358 c3/return -4359 -4360 new-var: # ad: (addr allocation-descriptor), name: (addr array byte), type: (addr tree type-id), block: int, stack-offset: int, register: (addr array byte) -> result/eax: (handle var) -4361 # . prologue -4362 55/push-ebp -4363 89/<- %ebp 4/r32/esp -4364 # . save registers -4365 51/push-ecx -4366 # -4367 (allocate *(ebp+8) *Var-size) # => eax -4368 8b/-> *(ebp+0xc) 1/r32/ecx -4369 89/<- *eax 1/r32/ecx # Var-name -4370 8b/-> *(ebp+0x10) 1/r32/ecx -4371 89/<- *(eax+4) 1/r32/ecx # Var-type -4372 8b/-> *(ebp+0x14) 1/r32/ecx -4373 89/<- *(eax+8) 1/r32/ecx # Var-block-depth -4374 8b/-> *(ebp+0x18) 1/r32/ecx -4375 89/<- *(eax+0xc) 1/r32/ecx # Var-stack-offset -4376 8b/-> *(ebp+0x1c) 1/r32/ecx -4377 89/<- *(eax+0x10) 1/r32/ecx # Var-register -4378 $new-var:end: -4379 # . restore registers -4380 59/pop-to-ecx -4381 # . epilogue -4382 89/<- %esp 5/r32/ebp -4383 5d/pop-to-ebp -4384 c3/return -4385 -4386 new-literal-integer: # ad: (addr allocation-descriptor), name: (addr slice) -> result/eax: (handle var) -4387 # . prologue -4388 55/push-ebp -4389 89/<- %ebp 4/r32/esp -4390 # . save registers -4391 51/push-ecx -4392 # if (!is-hex-int?(name)) abort -4393 (is-hex-int? *(ebp+0xc)) # => eax -4394 3d/compare-eax-and 0/imm32/false -4395 0f 84/jump-if-= $new-literal-integer:abort/disp32 -4396 # var s/ecx: (addr array byte) -4397 (slice-to-string Heap *(ebp+0xc)) # => eax -4398 89/<- %ecx 0/r32/eax -4399 # result/ecx = new var(s) -4400 (allocate *(ebp+8) *Var-size) # => eax -4401 (zero-out %eax *Var-size) -4402 89/<- *eax 1/r32/ecx # Var-name -4403 89/<- %ecx 0/r32/eax -4404 # result->type = new type() -4405 (allocate *(ebp+8) *Tree-size) # => eax -4406 (zero-out %eax *Tree-size) # default type is 'literal' -4407 89/<- *(ecx+4) 0/r32/eax # Var-type -4408 # move result to eax -4409 89/<- %eax 1/r32/ecx -4410 $new-literal-integer:end: -4411 # . restore registers -4412 59/pop-to-ecx -4413 # . epilogue -4414 89/<- %esp 5/r32/ebp -4415 5d/pop-to-ebp -4416 c3/return -4417 -4418 $new-literal-integer:abort: -4419 (write-buffered Stderr "variable cannot begin with a digit '") -4420 (write-slice-buffered Stderr *(ebp+0xc)) -4421 (write-buffered Stderr "'\n") -4422 (flush Stderr) -4423 # . syscall(exit, 1) -4424 bb/copy-to-ebx 1/imm32 -4425 b8/copy-to-eax 1/imm32/exit -4426 cd/syscall 0x80/imm8 -4427 # never gets here -4428 -4429 new-literal-string: # ad: (addr allocation-descriptor), name: (addr slice) -> result/eax: (handle var) -4430 # . prologue -4431 55/push-ebp -4432 89/<- %ebp 4/r32/esp -4433 # . save registers -4434 51/push-ecx -4435 # var s/ecx: (addr array byte) -4436 (slice-to-string Heap *(ebp+0xc)) # => eax -4437 89/<- %ecx 0/r32/eax -4438 # result/ecx = new var(s) -4439 (allocate *(ebp+8) *Var-size) # => eax -4440 (zero-out %eax *Var-size) -4441 89/<- *eax 1/r32/ecx # Var-name -4442 89/<- %ecx 0/r32/eax -4443 # result->type = new type() -4444 (allocate *(ebp+8) *Tree-size) # => eax -4445 (zero-out %eax *Tree-size) # default type is 'literal' -4446 89/<- *(ecx+4) 0/r32/eax # Var-type -4447 # move result to eax -4448 89/<- %eax 1/r32/ecx -4449 $new-literal-string:end: -4450 # . restore registers -4451 59/pop-to-ecx -4452 # . epilogue -4453 89/<- %esp 5/r32/ebp -4454 5d/pop-to-ebp -4455 c3/return -4456 -4457 new-label: # ad: (addr allocation-descriptor), name: (addr slice) -> result/eax: (handle var) -4458 # . prologue -4459 55/push-ebp -4460 89/<- %ebp 4/r32/esp -4461 # . save registers -4462 51/push-ecx -4463 # var s/ecx: (addr array byte) -4464 (slice-to-string Heap *(ebp+0xc)) # => eax -4465 89/<- %ecx 0/r32/eax -4466 # -4467 (allocate *(ebp+8) *Var-size) # => eax -4468 89/<- *eax 1/r32/ecx # Var-name -4469 89/<- %ecx 0/r32/eax -4470 (allocate *(ebp+8) *Tree-size) # => eax -4471 (zero-out %eax *Tree-size) # labels are literals -4472 89/<- *(ecx+4) 0/r32/eax # Var-type -4473 89/<- %eax 1/r32/ecx -4474 c7 0/subop/copy *(eax+8) 0/imm32 # Var-block-depth -4475 c7 0/subop/copy *(eax+0xc) 0/imm32 # Var-stack-offset -4476 c7 0/subop/copy *(eax+0x10) 0/imm32 # Var-register -4477 $new-label:end: -4478 # . restore registers -4479 59/pop-to-ecx -4480 # . epilogue -4481 89/<- %esp 5/r32/ebp -4482 5d/pop-to-ebp -4483 c3/return -4484 -4485 new-block: # ad: (addr allocation-descriptor), data: (handle list statement) -> result/eax: (handle statement) -4486 # . prologue -4487 55/push-ebp -4488 89/<- %ebp 4/r32/esp -4489 # . save registers -4490 51/push-ecx -4491 # -4492 (allocate *(ebp+8) *Stmt-size) # => eax -4493 (zero-out %eax *Stmt-size) -4494 c7 0/subop/copy *eax 0/imm32/tag/block # Stmt-tag -4495 8b/-> *(ebp+0xc) 1/r32/ecx -4496 89/<- *(eax+4) 1/r32/ecx # Block-statements -4497 $new-block:end: -4498 # . restore registers -4499 59/pop-to-ecx -4500 # . epilogue -4501 89/<- %esp 5/r32/ebp -4502 5d/pop-to-ebp -4503 c3/return -4504 -4505 new-vardef: # ad: (addr allocation-descriptor), var: (handle var) -> result/eax: (handle statement) -4506 # . prologue -4507 55/push-ebp -4508 89/<- %ebp 4/r32/esp -4509 # . save registers -4510 51/push-ecx +4220 5e/pop-to-esi +4221 5b/pop-to-ebx +4222 5a/pop-to-edx +4223 # . epilogue +4224 89/<- %esp 5/r32/ebp +4225 5d/pop-to-ebp +4226 c3/return +4227 +4228 $lookup-var-helper:error1: +4229 (write-buffered Stderr "malformed stack when looking up '") +4230 (write-slice-buffered Stderr *(ebp+8)) +4231 (write-buffered Stderr "'\n") +4232 (flush Stderr) +4233 # . syscall(exit, 1) +4234 bb/copy-to-ebx 1/imm32 +4235 b8/copy-to-eax 1/imm32/exit +4236 cd/syscall 0x80/imm8 +4237 # never gets here +4238 +4239 # return first 'name' from the top (back) of 'vars' and create a new var for a fn output if not found +4240 lookup-or-define-var: # name: (addr slice), vars: (addr stack (handle var)), fn: (handle function) -> result/eax: (handle var) +4241 # . prologue +4242 55/push-ebp +4243 89/<- %ebp 4/r32/esp +4244 # . save registers +4245 51/push-ecx +4246 # var target/ecx: (handle array byte) = slice-to-string(name) +4247 (slice-to-string Heap *(ebp+8)) # => eax +4248 89/<- %ecx 0/r32/eax +4249 # +4250 (lookup-var-helper %ecx *(ebp+0xc)) # => eax +4251 { +4252 # if (result != 0) return +4253 3d/compare-eax-and 0/imm32 +4254 75/jump-if-!= break/disp8 +4255 # if name is one of fn's outputs, return it +4256 { +4257 (find-in-function-outputs *(ebp+0x10) %ecx) # => eax +4258 3d/compare-eax-and 0/imm32 +4259 # otherwise abort +4260 0f 84/jump-if-!= $lookup-var:abort/disp32 +4261 } +4262 } +4263 $lookup-or-define-var:end: +4264 # . restore registers +4265 59/pop-to-ecx +4266 # . epilogue +4267 89/<- %esp 5/r32/ebp +4268 5d/pop-to-ebp +4269 c3/return +4270 +4271 find-in-function-outputs: # fn: (handle function), name: (handle array byte) -> result/eax: (handle var) +4272 # . prologue +4273 55/push-ebp +4274 89/<- %ebp 4/r32/esp +4275 # . save registers +4276 51/push-ecx +4277 # var curr/ecx: (handle list var) = fn->outputs +4278 8b/-> *(ebp+8) 1/r32/ecx +4279 8b/-> *(ecx+0xc) 1/r32/ecx +4280 # while curr != null +4281 { +4282 81 7/subop/compare %ecx 0/imm32 +4283 74/jump-if-= break/disp8 +4284 # var v: (handle var) = *curr +4285 8b/-> *ecx 0/r32/eax # List-value +4286 # if (curr->name == name) return curr +4287 50/push-eax +4288 (string-equal? *eax *(ebp+0xc)) +4289 3d/compare-eax-and 0/imm32/false +4290 58/pop-to-eax +4291 75/jump-if-!= $find-in-function-outputs:end/disp8 +4292 # curr = curr->next +4293 8b/-> *(ecx+4) 1/r32/ecx # List-next +4294 eb/jump loop/disp8 +4295 } +4296 b8/copy-to-eax 0/imm32 +4297 $find-in-function-outputs:end: +4298 # . restore registers +4299 59/pop-to-ecx +4300 # . epilogue +4301 89/<- %esp 5/r32/ebp +4302 5d/pop-to-ebp +4303 c3/return +4304 +4305 test-parse-mu-stmt: +4306 # . prologue +4307 55/push-ebp +4308 89/<- %ebp 4/r32/esp +4309 # setup +4310 (clear-stream _test-input-stream) +4311 (write _test-input-stream "increment n\n") +4312 # var vars/ecx: (stack (addr var) 4) +4313 81 5/subop/subtract %esp 0x10/imm32 +4314 68/push 0x10/imm32/length +4315 68/push 0/imm32/top +4316 89/<- %ecx 4/r32/esp +4317 (clear-stack %ecx) +4318 # var v/edx: var +4319 81 5/subop/subtract %esp 0x14/imm32 # Var-size +4320 89/<- %edx 4/r32/esp +4321 (zero-out %edx 0x14) # Var-size +4322 # v->name = "n" +4323 c7 0/subop/copy *edx "n"/imm32 # Var-name +4324 # +4325 (push %ecx %edx) +4326 # convert +4327 (parse-mu-stmt _test-input-stream %ecx) # => eax +4328 # check result +4329 (check-ints-equal *eax 1 "F - test-parse-mu-stmt/tag") # Stmt-tag is Stmt1 +4330 (check-strings-equal *(eax+4) "increment" "F - test-parse-mu-stmt/name") # Stmt1-operation +4331 # edx: (handle list var) = result->inouts +4332 8b/-> *(eax+8) 2/r32/edx # Stmt1-inouts +4333 # ebx: (handle var) = result->inouts->value +4334 8b/-> *edx 3/r32/ebx # Stmt-var-value +4335 (check-strings-equal *ebx "n" "F - test-parse-mu-stmt/inout:0") # Var-name +4336 # . epilogue +4337 89/<- %esp 5/r32/ebp +4338 5d/pop-to-ebp +4339 c3/return +4340 +4341 test-parse-mu-stmt-with-comma: +4342 # . prologue +4343 55/push-ebp +4344 89/<- %ebp 4/r32/esp +4345 # setup +4346 (clear-stream _test-input-stream) +4347 (write _test-input-stream "copy-to n, 3\n") +4348 # var vars/ecx: (stack (addr var) 4) +4349 81 5/subop/subtract %esp 0x10/imm32 +4350 68/push 0x10/imm32/length +4351 68/push 0/imm32/top +4352 89/<- %ecx 4/r32/esp +4353 (clear-stack %ecx) +4354 # var v/edx: var +4355 81 5/subop/subtract %esp 0x14/imm32 # Var-size +4356 89/<- %edx 4/r32/esp +4357 (zero-out %edx 0x14) # Var-size +4358 # v->name = "n" +4359 c7 0/subop/copy *edx "n"/imm32 # Var-name +4360 # +4361 (push %ecx %edx) +4362 # convert +4363 (parse-mu-stmt _test-input-stream %ecx) # => eax +4364 # check result +4365 (check-ints-equal *eax 1 "F - test-parse-mu-stmt-with-comma/tag") # Stmt-tag is Stmt1 +4366 (check-strings-equal *(eax+4) "copy-to" "F - test-parse-mu-stmt-with-comma/name") # Stmt1-operation +4367 # edx: (handle list var) = result->inouts +4368 8b/-> *(eax+8) 2/r32/edx # Stmt1-inouts +4369 # ebx: (handle var) = result->inouts->value +4370 8b/-> *edx 3/r32/ebx # Stmt-var-value +4371 (check-strings-equal *ebx "n" "F - test-parse-mu-stmt-with-comma/inout:0") # Var-name +4372 # . epilogue +4373 89/<- %esp 5/r32/ebp +4374 5d/pop-to-ebp +4375 c3/return +4376 +4377 new-function: # ad: (addr allocation-descriptor), name: (addr array byte), subx-name: (addr array byte), inouts: (handle list var), outputs: (handle list var), body: (handle block), next: (handle function) -> result/eax: (handle function) +4378 # . prologue +4379 55/push-ebp +4380 89/<- %ebp 4/r32/esp +4381 # . save registers +4382 51/push-ecx +4383 # +4384 (allocate *(ebp+8) *Function-size) # => eax +4385 8b/-> *(ebp+0xc) 1/r32/ecx +4386 89/<- *eax 1/r32/ecx # Function-name +4387 8b/-> *(ebp+0x10) 1/r32/ecx +4388 89/<- *(eax+4) 1/r32/ecx # Function-subx-name +4389 8b/-> *(ebp+0x14) 1/r32/ecx +4390 89/<- *(eax+8) 1/r32/ecx # Function-inouts +4391 8b/-> *(ebp+0x18) 1/r32/ecx +4392 89/<- *(eax+0xc) 1/r32/ecx # Function-outputs +4393 8b/-> *(ebp+0x1c) 1/r32/ecx +4394 89/<- *(eax+0x10) 1/r32/ecx # Function-body +4395 8b/-> *(ebp+0x20) 1/r32/ecx +4396 89/<- *(eax+0x14) 1/r32/ecx # Function-next +4397 $new-function:end: +4398 # . restore registers +4399 59/pop-to-ecx +4400 # . epilogue +4401 89/<- %esp 5/r32/ebp +4402 5d/pop-to-ebp +4403 c3/return +4404 +4405 new-var: # ad: (addr allocation-descriptor), name: (addr array byte), type: (addr tree type-id), block: int, stack-offset: int, register: (addr array byte) -> result/eax: (handle var) +4406 # . prologue +4407 55/push-ebp +4408 89/<- %ebp 4/r32/esp +4409 # . save registers +4410 51/push-ecx +4411 # +4412 (allocate *(ebp+8) *Var-size) # => eax +4413 8b/-> *(ebp+0xc) 1/r32/ecx +4414 89/<- *eax 1/r32/ecx # Var-name +4415 8b/-> *(ebp+0x10) 1/r32/ecx +4416 89/<- *(eax+4) 1/r32/ecx # Var-type +4417 8b/-> *(ebp+0x14) 1/r32/ecx +4418 89/<- *(eax+8) 1/r32/ecx # Var-block-depth +4419 8b/-> *(ebp+0x18) 1/r32/ecx +4420 89/<- *(eax+0xc) 1/r32/ecx # Var-stack-offset +4421 8b/-> *(ebp+0x1c) 1/r32/ecx +4422 89/<- *(eax+0x10) 1/r32/ecx # Var-register +4423 $new-var:end: +4424 # . restore registers +4425 59/pop-to-ecx +4426 # . epilogue +4427 89/<- %esp 5/r32/ebp +4428 5d/pop-to-ebp +4429 c3/return +4430 +4431 new-literal-integer: # ad: (addr allocation-descriptor), name: (addr slice) -> result/eax: (handle var) +4432 # . prologue +4433 55/push-ebp +4434 89/<- %ebp 4/r32/esp +4435 # . save registers +4436 51/push-ecx +4437 # if (!is-hex-int?(name)) abort +4438 (is-hex-int? *(ebp+0xc)) # => eax +4439 3d/compare-eax-and 0/imm32/false +4440 0f 84/jump-if-= $new-literal-integer:abort/disp32 +4441 # var s/ecx: (addr array byte) +4442 (slice-to-string Heap *(ebp+0xc)) # => eax +4443 89/<- %ecx 0/r32/eax +4444 # result/ecx = new var(s) +4445 (allocate *(ebp+8) *Var-size) # => eax +4446 (zero-out %eax *Var-size) +4447 89/<- *eax 1/r32/ecx # Var-name +4448 89/<- %ecx 0/r32/eax +4449 # result->type = new type() +4450 (allocate *(ebp+8) *Tree-size) # => eax +4451 (zero-out %eax *Tree-size) # default type is 'literal' +4452 89/<- *(ecx+4) 0/r32/eax # Var-type +4453 # move result to eax +4454 89/<- %eax 1/r32/ecx +4455 $new-literal-integer:end: +4456 # . restore registers +4457 59/pop-to-ecx +4458 # . epilogue +4459 89/<- %esp 5/r32/ebp +4460 5d/pop-to-ebp +4461 c3/return +4462 +4463 $new-literal-integer:abort: +4464 (write-buffered Stderr "variable cannot begin with a digit '") +4465 (write-slice-buffered Stderr *(ebp+0xc)) +4466 (write-buffered Stderr "'\n") +4467 (flush Stderr) +4468 # . syscall(exit, 1) +4469 bb/copy-to-ebx 1/imm32 +4470 b8/copy-to-eax 1/imm32/exit +4471 cd/syscall 0x80/imm8 +4472 # never gets here +4473 +4474 new-literal-string: # ad: (addr allocation-descriptor), name: (addr slice) -> result/eax: (handle var) +4475 # . prologue +4476 55/push-ebp +4477 89/<- %ebp 4/r32/esp +4478 # . save registers +4479 51/push-ecx +4480 # var s/ecx: (addr array byte) +4481 (slice-to-string Heap *(ebp+0xc)) # => eax +4482 89/<- %ecx 0/r32/eax +4483 # result/ecx = new var(s) +4484 (allocate *(ebp+8) *Var-size) # => eax +4485 (zero-out %eax *Var-size) +4486 89/<- *eax 1/r32/ecx # Var-name +4487 89/<- %ecx 0/r32/eax +4488 # result->type = new type() +4489 (allocate *(ebp+8) *Tree-size) # => eax +4490 (zero-out %eax *Tree-size) # default type is 'literal' +4491 89/<- *(ecx+4) 0/r32/eax # Var-type +4492 # move result to eax +4493 89/<- %eax 1/r32/ecx +4494 $new-literal-string:end: +4495 # . restore registers +4496 59/pop-to-ecx +4497 # . epilogue +4498 89/<- %esp 5/r32/ebp +4499 5d/pop-to-ebp +4500 c3/return +4501 +4502 new-label: # ad: (addr allocation-descriptor), name: (addr slice) -> result/eax: (handle var) +4503 # . prologue +4504 55/push-ebp +4505 89/<- %ebp 4/r32/esp +4506 # . save registers +4507 51/push-ecx +4508 # var s/ecx: (addr array byte) +4509 (slice-to-string Heap *(ebp+0xc)) # => eax +4510 89/<- %ecx 0/r32/eax 4511 # -4512 (allocate *(ebp+8) *Stmt-size) # => eax -4513 (zero-out %eax *Stmt-size) -4514 c7 0/subop/copy *eax 2/imm32/tag/var-on-stack # Stmt-tag -4515 # result->var = var -4516 8b/-> *(ebp+0xc) 1/r32/ecx -4517 89/<- *(eax+4) 1/r32/ecx # Vardef-var -4518 $new-vardef:end: -4519 # . restore registers -4520 59/pop-to-ecx -4521 # . epilogue -4522 89/<- %esp 5/r32/ebp -4523 5d/pop-to-ebp -4524 c3/return -4525 -4526 new-regvardef: # ad: (addr allocation-descriptor), var: (handle var) -> result/eax: (handle statement) -4527 # . prologue -4528 55/push-ebp -4529 89/<- %ebp 4/r32/esp -4530 # . save registers -4531 51/push-ecx -4532 57/push-edi -4533 # ecx = var -4534 8b/-> *(ebp+0xc) 1/r32/ecx -4535 # edi = result -4536 (allocate *(ebp+8) *Stmt-size) # => eax -4537 89/<- %edi 0/r32/eax -4538 (zero-out %edi *Stmt-size) -4539 # set tag -4540 c7 0/subop/copy *edi 3/imm32/tag/var-in-register # Stmt-tag -4541 # set output -4542 (append-stmt-var Heap %ecx *(edi+0xc) 0) # Regvardef-outputs => eax -4543 89/<- *(edi+0xc) 0/r32/eax # Regvardef-outputs -4544 $new-regvardef:end: -4545 89/<- %eax 7/r32/edi -4546 # . restore registers -4547 5f/pop-to-edi -4548 59/pop-to-ecx -4549 # . epilogue -4550 89/<- %esp 5/r32/ebp -4551 5d/pop-to-ebp -4552 c3/return -4553 -4554 append-list: # ad: (addr allocation-descriptor), value: _type, list: (handle list _type) -> result/eax: (handle list _type) -4555 # . prologue -4556 55/push-ebp -4557 89/<- %ebp 4/r32/esp -4558 # . save registers -4559 51/push-ecx -4560 # -4561 (allocate *(ebp+8) *List-size) # => eax -4562 (zero-out %eax *List-size) -4563 8b/-> *(ebp+0xc) 1/r32/ecx -4564 89/<- *eax 1/r32/ecx # List-value -4565 # if (list == null) return result -4566 81 7/subop/compare *(ebp+0x10) 0/imm32 -4567 74/jump-if-= $append-list:end/disp8 -4568 # otherwise append -4569 # var curr/ecx = list -4570 8b/-> *(ebp+0x10) 1/r32/ecx -4571 # while (curr->next != null) curr = curr->next -4572 { -4573 81 7/subop/compare *(ecx+4) 0/imm32 # List-next -4574 74/jump-if-= break/disp8 -4575 # curr = curr->next -4576 8b/-> *(ecx+4) 1/r32/ecx -4577 eb/jump loop/disp8 -4578 } -4579 # curr->next = result -4580 89/<- *(ecx+4) 0/r32/eax -4581 # return list -4582 8b/-> *(ebp+0x10) 0/r32/eax -4583 $append-list:end: -4584 # . restore registers -4585 59/pop-to-ecx -4586 # . epilogue -4587 89/<- %esp 5/r32/ebp -4588 5d/pop-to-ebp -4589 c3/return -4590 -4591 append-stmt-var: # ad: (addr allocation-descriptor), v: (handle var), vars: (handle stmt-var), is-deref?: boolean -> result/eax: (handle stmt-var) -4592 # . prologue -4593 55/push-ebp -4594 89/<- %ebp 4/r32/esp -4595 # . save registers -4596 51/push-ecx -4597 # -4598 (allocate *(ebp+8) *Stmt-var-size) # => eax -4599 (zero-out %eax *Stmt-var-size) -4600 8b/-> *(ebp+0xc) 1/r32/ecx -4601 89/<- *eax 1/r32/ecx # Stmt-var-value -4602 8b/-> *(ebp+0x14) 1/r32/ecx -4603 89/<- *(eax+8) 1/r32/ecx # Stmt-var-is-deref -4604 # if (list == null) return result -4605 81 7/subop/compare *(ebp+0x10) 0/imm32 -4606 74/jump-if-= $append-stmt-var:end/disp8 -4607 # otherwise append -4608 # var curr/ecx: (handle stmt-var) = vars -4609 8b/-> *(ebp+0x10) 1/r32/ecx -4610 # while (curr->next != null) curr = curr->next -4611 { -4612 81 7/subop/compare *(ecx+4) 0/imm32 # List-next -4613 74/jump-if-= break/disp8 -4614 # curr = curr->next -4615 8b/-> *(ecx+4) 1/r32/ecx -4616 eb/jump loop/disp8 -4617 } -4618 # curr->next = result -4619 89/<- *(ecx+4) 0/r32/eax -4620 # return vars -4621 8b/-> *(ebp+0x10) 0/r32/eax -4622 $append-stmt-var:end: -4623 # . restore registers -4624 59/pop-to-ecx -4625 # . epilogue -4626 89/<- %esp 5/r32/ebp -4627 5d/pop-to-ebp -4628 c3/return -4629 -4630 append-to-block: # ad: (addr allocation-descriptor), block: (handle block), x: (handle stmt) -4631 # . prologue -4632 55/push-ebp -4633 89/<- %ebp 4/r32/esp -4634 # . save registers -4635 56/push-esi -4636 # esi = block -4637 8b/-> *(ebp+0xc) 6/r32/esi -4638 (append-list *(ebp+8) *(ebp+0x10) *(esi+4)) # ad, x, Block-statements -4639 89/<- *(esi+4) 0/r32/eax # Block-statements -4640 $append-to-block:end: -4641 # . restore registers -4642 5e/pop-to-esi -4643 # . epilogue -4644 89/<- %esp 5/r32/ebp -4645 5d/pop-to-ebp -4646 c3/return -4647 -4648 ####################################################### -4649 # Type-checking -4650 ####################################################### -4651 -4652 check-mu-types: -4653 # . prologue -4654 55/push-ebp -4655 89/<- %ebp 4/r32/esp -4656 # -4657 $check-mu-types:end: -4658 # . epilogue -4659 89/<- %esp 5/r32/ebp -4660 5d/pop-to-ebp -4661 c3/return -4662 -4663 size-of: # v: (addr var) -> result/eax: int -4664 # . prologue -4665 55/push-ebp -4666 89/<- %ebp 4/r32/esp -4667 # if v is a literal, return 0 -4668 8b/-> *(ebp+8) 0/r32/eax -4669 8b/-> *(eax+4) 0/r32/eax # Var-type -4670 81 7/subop/compare *eax 0/imm32 # Tree-left -4671 b8/copy-to-eax 0/imm32 -4672 74/jump-if-= $size-of:end/disp8 -4673 # hard-coded since we only support 'int' types for now -4674 b8/copy-to-eax 4/imm32 -4675 $size-of:end: -4676 # . epilogue -4677 89/<- %esp 5/r32/ebp -4678 5d/pop-to-ebp -4679 c3/return -4680 -4681 type-equal?: # a: (handle tree type-id), b: (handle tree type-id) -> result/eax: boolean -4682 # . prologue -4683 55/push-ebp -4684 89/<- %ebp 4/r32/esp -4685 # . save registers -4686 51/push-ecx -4687 52/push-edx -4688 # ecx = a -4689 8b/-> *(ebp+8) 1/r32/ecx -4690 # edx = b -4691 8b/-> *(ebp+0xc) 2/r32/edx -4692 # if (a == b) return true -4693 8b/-> %ecx 0/r32/eax # Var-type -4694 39/compare %edx 0/r32/eax # Var-type -4695 b8/copy-to-eax 1/imm32/true -4696 74/jump-if-= $type-equal?:end/disp8 -4697 # if (a < MAX_TYPE_ID) return false -4698 81 7/subop/compare %ecx 0x10000/imm32 -4699 b8/copy-to-eax 0/imm32/false -4700 72/jump-if-addr< $type-equal?:end/disp8 -4701 # if (b < MAX_TYPE_ID) return false -4702 81 7/subop/compare %edx 0x10000/imm32 -4703 b8/copy-to-eax 0/imm32/false -4704 72/jump-if-addr< $type-equal?:end/disp8 -4705 # if (!type-equal?(a->left, b->left)) return false -4706 (type-equal? *ecx *edx) # Tree-left, Tree-left => eax -4707 3d/compare-eax-and 0/imm32/false -4708 74/jump-if-= $type-equal?:end/disp8 -4709 # return type-equal?(a->right, b->right) -4710 (type-equal? *(ecx+4) *(edx+4)) # Tree-right, Tree-right => eax -4711 $type-equal?:end: -4712 # . restore registers -4713 5a/pop-to-edx -4714 59/pop-to-ecx -4715 # . epilogue -4716 89/<- %esp 5/r32/ebp -4717 5d/pop-to-ebp -4718 c3/return -4719 -4720 == data -4721 -4722 # not yet used, but it will be -4723 Type-size: # (stream int) -4724 0x18/imm32/write -4725 0/imm32/read -4726 0x100/imm32/length -4727 # data -4728 4/imm32 # literal -4729 4/imm32 # int -4730 4/imm32 # addr -4731 0/imm32 # array (logic elsewhere) -4732 8/imm32 # handle (fat pointer) -4733 4/imm32 # bool -4734 0/imm32 -4735 0/imm32 -4736 # 0x20 -4737 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 -4738 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 -4739 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 -4740 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 -4741 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 -4742 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 -4743 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 -4744 -4745 == code -4746 -4747 ####################################################### -4748 # Code-generation -4749 ####################################################### -4750 -4751 emit-subx: # out: (addr buffered-file) -4752 # . prologue -4753 55/push-ebp -4754 89/<- %ebp 4/r32/esp -4755 # . save registers -4756 50/push-eax -4757 51/push-ecx -4758 57/push-edi -4759 # edi = out -4760 8b/-> *(ebp+8) 7/r32/edi -4761 # var curr/ecx: (handle function) = *Program -4762 8b/-> *Program 1/r32/ecx -4763 { -4764 # if (curr == null) break -4765 81 7/subop/compare %ecx 0/imm32 -4766 0f 84/jump-if-= break/disp32 -4767 (emit-subx-function %edi %ecx) -4768 # curr = curr->next -4769 8b/-> *(ecx+0x14) 1/r32/ecx # Function-next -4770 e9/jump loop/disp32 -4771 } -4772 $emit-subx:end: -4773 # . restore registers -4774 5f/pop-to-edi -4775 59/pop-to-ecx -4776 58/pop-to-eax -4777 # . epilogue -4778 89/<- %esp 5/r32/ebp -4779 5d/pop-to-ebp -4780 c3/return -4781 -4782 emit-subx-function: # out: (addr buffered-file), f: (handle function) -4783 # . prologue -4784 55/push-ebp -4785 89/<- %ebp 4/r32/esp -4786 # . save registers -4787 50/push-eax -4788 51/push-ecx -4789 52/push-edx -4790 57/push-edi -4791 # edi = out -4792 8b/-> *(ebp+8) 7/r32/edi -4793 # ecx = f -4794 8b/-> *(ebp+0xc) 1/r32/ecx -4795 # var vars/edx: (stack (addr var) 256) -4796 81 5/subop/subtract %esp 0x400/imm32 -4797 68/push 0x400/imm32/length -4798 68/push 0/imm32/top -4799 89/<- %edx 4/r32/esp -4800 # -4801 (write-buffered %edi *ecx) -4802 (write-buffered %edi ":\n") -4803 # Important: each block's depth during code-generation should be identical -4804 # to what it was during parsing. -4805 c7 0/subop/copy *Curr-block-depth 1/imm32 -4806 (emit-subx-prologue %edi) -4807 (emit-subx-block %edi *(ecx+0x10) %edx) # Function-body -4808 (emit-subx-epilogue %edi) -4809 $emit-subx-function:end: -4810 # . reclaim locals -4811 81 0/subop/add %esp 408/imm32 -4812 # . restore registers -4813 5f/pop-to-edi -4814 5a/pop-to-edx -4815 59/pop-to-ecx -4816 58/pop-to-eax -4817 # . epilogue -4818 89/<- %esp 5/r32/ebp -4819 5d/pop-to-ebp -4820 c3/return -4821 -4822 emit-subx-stmt-list: # out: (addr buffered-file), stmts: (handle list stmt), vars: (addr stack (handle var)) -4823 # . prologue -4824 55/push-ebp -4825 89/<- %ebp 4/r32/esp -4826 # . save registers -4827 50/push-eax -4828 51/push-ecx -4829 52/push-edx -4830 53/push-ebx -4831 56/push-esi -4832 # esi = stmts -4833 8b/-> *(ebp+0xc) 6/r32/esi -4834 # var var-seen?/edx: boolean <- copy false -4835 ba/copy-to-edx 0/imm32/false -4836 # -4837 { -4838 $emit-subx-stmt-list:loop: -4839 81 7/subop/compare %esi 0/imm32 -4840 0f 84/jump-if-= break/disp32 -4841 # var curr-stmt/ecx = stmts->value -4842 8b/-> *esi 1/r32/ecx # List-value -4843 { -4844 $emit-subx-stmt-list:check-for-block: -4845 81 7/subop/compare *ecx 0/imm32/block # Stmt-tag -4846 75/jump-if-!= break/disp8 -4847 $emit-subx-stmt-list:block: -4848 (emit-subx-block *(ebp+8) %ecx *(ebp+0x10)) -4849 } -4850 { -4851 $emit-subx-stmt-list:check-for-stmt: -4852 81 7/subop/compare *ecx 1/imm32/stmt1 # Stmt-tag -4853 0f 85/jump-if-!= break/disp32 -4854 $emit-subx-stmt-list:stmt1: -4855 { -4856 (is-mu-branch? %ecx) # => eax -4857 3d/compare-eax-and 0/imm32/false -4858 0f 84/jump-if-= break/disp32 -4859 $emit-subx-stmt-list:branch-stmt: -4860 # if !var-seen? break -4861 81 7/subop/compare %edx 0/imm32/false -4862 0f 84/jump-if-= break/disp32 -4863 $emit-subx-stmt-list:branch-stmt-and-var-seen: -4864 +-- 26 lines: # unconditional loops ----------------------------------------------------------------------------------------------------------------------------------------------------- -4890 +-- 15 lines: # unconditional breaks ---------------------------------------------------------------------------------------------------------------------------------------------------- -4905 +-- 37 lines: # simple conditional branches without a target ---------------------------------------------------------------------------------------------------------------------------- -4942 +-- 19 lines: # conditional branches with an explicit target ---------------------------------------------------------------------------------------------------------------------------- -4961 } -4962 $emit-subx-stmt-list:1-to-1: -4963 (emit-subx-statement *(ebp+8) %ecx Primitives *Program) -4964 } -4965 { -4966 $emit-subx-stmt-list:check-for-vardef: -4967 81 7/subop/compare *ecx 2/imm32/vardef # Stmt-tag -4968 75/jump-if-!= break/disp8 -4969 $emit-subx-stmt-list:vardef: -4970 (emit-subx-var-def *(ebp+8) %ecx) -4971 (push *(ebp+0x10) *(ecx+4)) # Vardef-var -4972 # var-seen? = true -4973 ba/copy-to-edx 1/imm32/true -4974 } -4975 { -4976 $emit-subx-stmt-list:check-for-regvardef: -4977 81 7/subop/compare *ecx 3/imm32/regvardef # Stmt-tag -4978 0f 85/jump-if-!= break/disp32 -4979 $emit-subx-stmt-list:regvardef: -4980 # TODO: ensure that there's exactly one output -4981 # var output/eax: (handle var) = curr-stmt->outputs->value -4982 8b/-> *(ecx+0xc) 0/r32/eax -4983 8b/-> *eax 0/r32/eax -4984 # ensure that output is in a register -4985 81 7/subop/compare *(eax+0x10) 0/imm32 # Var-register -4986 0f 84/jump-if-= $emit-subx-stmt-list:abort-regvardef-without-register/disp32 -4987 # emit spill -4988 (emit-indent *(ebp+8) *Curr-block-depth) -4989 (write-buffered *(ebp+8) "ff 6/subop/push %") -4990 (write-buffered *(ebp+8) *(eax+0x10)) -4991 (write-buffered *(ebp+8) Newline) -4992 # register variable definition -4993 (push *(ebp+0x10) %eax) -4994 # emit the instruction as usual -4995 (emit-subx-statement *(ebp+8) %ecx Primitives *Program) -4996 # var-seen? = true -4997 ba/copy-to-edx 1/imm32/true -4998 } -4999 $emit-subx-stmt-list:continue: -5000 # TODO: raise an error on unrecognized Stmt-tag -5001 8b/-> *(esi+4) 6/r32/esi # List-next -5002 e9/jump loop/disp32 -5003 } -5004 $emit-subx-stmt-list:emit-cleanup: -5005 (emit-cleanup-code-until-depth *(ebp+8) *(ebp+0x10) *Curr-block-depth) -5006 $emit-subx-stmt-list:cleanup: -5007 (clean-up-blocks *(ebp+0x10) *Curr-block-depth) -5008 $emit-subx-stmt-list:end: -5009 # . restore registers -5010 5e/pop-to-esi -5011 5b/pop-to-ebx -5012 5a/pop-to-edx -5013 59/pop-to-ecx -5014 58/pop-to-eax -5015 # . epilogue -5016 89/<- %esp 5/r32/ebp -5017 5d/pop-to-ebp -5018 c3/return -5019 -5020 $emit-subx-stmt-list:abort-regvardef-without-register: -5021 # error("var '" var->name "' initialized from an instruction must live in a register\n") -5022 (write-buffered Stderr "var '") -5023 (write-buffered Stderr *eax) # Var-name -5024 (write-buffered Stderr "' initialized from an instruction must live in a register\n") -5025 (flush Stderr) -5026 # . syscall(exit, 1) -5027 bb/copy-to-ebx 1/imm32 -5028 b8/copy-to-eax 1/imm32/exit -5029 cd/syscall 0x80/imm8 -5030 # never gets here -5031 -5032 emit-subx-cleanup-and-unconditional-nonlocal-branch: # out: (addr buffered-file), stmt: (addr stmt1), vars: (addr stack (handle var)) -5033 # . prologue -5034 55/push-ebp -5035 89/<- %ebp 4/r32/esp -5036 # . save registers -5037 50/push-eax -5038 51/push-ecx -5039 52/push-edx -5040 # ecx = stmt -5041 8b/-> *(ebp+0xc) 1/r32/ecx -5042 # var target/edx: (addr array byte) = curr-stmt->inouts->value->name -5043 8b/-> *(ecx+8) 2/r32/edx # Stmt1-inouts -5044 8b/-> *edx 2/r32/edx # Stmt-var-value -5045 8b/-> *edx 2/r32/edx # Var-name -5046 # clean up until target block -5047 (emit-cleanup-code-until-target *(ebp+8) *(ebp+0x10) %edx) -5048 # emit jump to target block -5049 (emit-indent *(ebp+8) *Curr-block-depth) -5050 (write-buffered *(ebp+8) "e9/jump ") -5051 (write-buffered *(ebp+8) %edx) -5052 (string-starts-with? *(ecx+4) "break") -5053 3d/compare-eax-and 0/imm32/false -5054 { -5055 74/jump-if-= break/disp8 -5056 (write-buffered *(ebp+8) ":break/disp32\n") -5057 } -5058 3d/compare-eax-and 0/imm32/false # just in case the function call modified flags -5059 { -5060 75/jump-if-!= break/disp8 -5061 (write-buffered *(ebp+8) ":loop/disp32\n") -5062 } -5063 $emit-subx-cleanup-and-unconditional-nonlocal-branch:end: -5064 # . restore registers -5065 5a/pop-to-edx -5066 59/pop-to-ecx -5067 58/pop-to-eax -5068 # . epilogue -5069 89/<- %esp 5/r32/ebp -5070 5d/pop-to-ebp -5071 c3/return -5072 -5073 is-mu-branch?: # stmt: (addr stmt1) -> result/eax: boolean -5074 # . prologue -5075 55/push-ebp -5076 89/<- %ebp 4/r32/esp -5077 # . save registers -5078 51/push-ecx -5079 # ecx = stmt -5080 8b/-> *(ebp+8) 1/r32/ecx -5081 # if (stmt->operation starts with "loop") return true -5082 (string-starts-with? *(ecx+4) "loop") # Stmt1-operation => eax -5083 3d/compare-eax-and 0/imm32/false -5084 75/jump-if-not-equal $is-mu-branch?:end/disp8 -5085 # otherwise return (stmt->operation starts with "break") -5086 (string-starts-with? *(ecx+4) "break") # Stmt1-operation => eax -5087 $is-mu-branch?:end: -5088 # . restore registers -5089 59/pop-to-ecx -5090 # . epilogue -5091 89/<- %esp 5/r32/ebp -5092 5d/pop-to-ebp -5093 c3/return -5094 -5095 emit-reverse-break: # out: (addr buffered-file), stmt: (addr stmt1) -5096 # . prologue -5097 55/push-ebp -5098 89/<- %ebp 4/r32/esp -5099 # . save registers -5100 50/push-eax -5101 # eax = stmt -5102 8b/-> *(ebp+0xc) 0/r32/eax -5103 # -5104 (get Reverse-branch *(eax+4) 8 "reverse-branch: ") # Stmt1-operation => eax: (addr addr array byte) -5105 (emit-indent *(ebp+8) *Curr-block-depth) -5106 (write-buffered *(ebp+8) *eax) -5107 (write-buffered *(ebp+8) " break/disp32\n") -5108 $emit-reverse-break:end: +4512 (allocate *(ebp+8) *Var-size) # => eax +4513 89/<- *eax 1/r32/ecx # Var-name +4514 89/<- %ecx 0/r32/eax +4515 (allocate *(ebp+8) *Tree-size) # => eax +4516 (zero-out %eax *Tree-size) # labels are literals +4517 89/<- *(ecx+4) 0/r32/eax # Var-type +4518 89/<- %eax 1/r32/ecx +4519 c7 0/subop/copy *(eax+8) 0/imm32 # Var-block-depth +4520 c7 0/subop/copy *(eax+0xc) 0/imm32 # Var-stack-offset +4521 c7 0/subop/copy *(eax+0x10) 0/imm32 # Var-register +4522 $new-label:end: +4523 # . restore registers +4524 59/pop-to-ecx +4525 # . epilogue +4526 89/<- %esp 5/r32/ebp +4527 5d/pop-to-ebp +4528 c3/return +4529 +4530 new-block: # ad: (addr allocation-descriptor), data: (handle list statement) -> result/eax: (handle statement) +4531 # . prologue +4532 55/push-ebp +4533 89/<- %ebp 4/r32/esp +4534 # . save registers +4535 51/push-ecx +4536 # +4537 (allocate *(ebp+8) *Stmt-size) # => eax +4538 (zero-out %eax *Stmt-size) +4539 c7 0/subop/copy *eax 0/imm32/tag/block # Stmt-tag +4540 8b/-> *(ebp+0xc) 1/r32/ecx +4541 89/<- *(eax+4) 1/r32/ecx # Block-statements +4542 $new-block:end: +4543 # . restore registers +4544 59/pop-to-ecx +4545 # . epilogue +4546 89/<- %esp 5/r32/ebp +4547 5d/pop-to-ebp +4548 c3/return +4549 +4550 new-vardef: # ad: (addr allocation-descriptor), var: (handle var) -> result/eax: (handle statement) +4551 # . prologue +4552 55/push-ebp +4553 89/<- %ebp 4/r32/esp +4554 # . save registers +4555 51/push-ecx +4556 # +4557 (allocate *(ebp+8) *Stmt-size) # => eax +4558 (zero-out %eax *Stmt-size) +4559 c7 0/subop/copy *eax 2/imm32/tag/var-on-stack # Stmt-tag +4560 # result->var = var +4561 8b/-> *(ebp+0xc) 1/r32/ecx +4562 89/<- *(eax+4) 1/r32/ecx # Vardef-var +4563 $new-vardef:end: +4564 # . restore registers +4565 59/pop-to-ecx +4566 # . epilogue +4567 89/<- %esp 5/r32/ebp +4568 5d/pop-to-ebp +4569 c3/return +4570 +4571 new-regvardef: # ad: (addr allocation-descriptor), var: (handle var) -> result/eax: (handle statement) +4572 # . prologue +4573 55/push-ebp +4574 89/<- %ebp 4/r32/esp +4575 # . save registers +4576 51/push-ecx +4577 57/push-edi +4578 # ecx = var +4579 8b/-> *(ebp+0xc) 1/r32/ecx +4580 # edi = result +4581 (allocate *(ebp+8) *Stmt-size) # => eax +4582 89/<- %edi 0/r32/eax +4583 (zero-out %edi *Stmt-size) +4584 # set tag +4585 c7 0/subop/copy *edi 3/imm32/tag/var-in-register # Stmt-tag +4586 # set output +4587 (append-stmt-var Heap %ecx *(edi+0xc) 0) # Regvardef-outputs => eax +4588 89/<- *(edi+0xc) 0/r32/eax # Regvardef-outputs +4589 $new-regvardef:end: +4590 89/<- %eax 7/r32/edi +4591 # . restore registers +4592 5f/pop-to-edi +4593 59/pop-to-ecx +4594 # . epilogue +4595 89/<- %esp 5/r32/ebp +4596 5d/pop-to-ebp +4597 c3/return +4598 +4599 append-list: # ad: (addr allocation-descriptor), value: _type, list: (handle list _type) -> result/eax: (handle list _type) +4600 # . prologue +4601 55/push-ebp +4602 89/<- %ebp 4/r32/esp +4603 # . save registers +4604 51/push-ecx +4605 # +4606 (allocate *(ebp+8) *List-size) # => eax +4607 (zero-out %eax *List-size) +4608 8b/-> *(ebp+0xc) 1/r32/ecx +4609 89/<- *eax 1/r32/ecx # List-value +4610 # if (list == null) return result +4611 81 7/subop/compare *(ebp+0x10) 0/imm32 +4612 74/jump-if-= $append-list:end/disp8 +4613 # otherwise append +4614 # var curr/ecx = list +4615 8b/-> *(ebp+0x10) 1/r32/ecx +4616 # while (curr->next != null) curr = curr->next +4617 { +4618 81 7/subop/compare *(ecx+4) 0/imm32 # List-next +4619 74/jump-if-= break/disp8 +4620 # curr = curr->next +4621 8b/-> *(ecx+4) 1/r32/ecx +4622 eb/jump loop/disp8 +4623 } +4624 # curr->next = result +4625 89/<- *(ecx+4) 0/r32/eax +4626 # return list +4627 8b/-> *(ebp+0x10) 0/r32/eax +4628 $append-list:end: +4629 # . restore registers +4630 59/pop-to-ecx +4631 # . epilogue +4632 89/<- %esp 5/r32/ebp +4633 5d/pop-to-ebp +4634 c3/return +4635 +4636 append-stmt-var: # ad: (addr allocation-descriptor), v: (handle var), vars: (handle stmt-var), is-deref?: boolean -> result/eax: (handle stmt-var) +4637 # . prologue +4638 55/push-ebp +4639 89/<- %ebp 4/r32/esp +4640 # . save registers +4641 51/push-ecx +4642 # +4643 (allocate *(ebp+8) *Stmt-var-size) # => eax +4644 (zero-out %eax *Stmt-var-size) +4645 8b/-> *(ebp+0xc) 1/r32/ecx +4646 89/<- *eax 1/r32/ecx # Stmt-var-value +4647 8b/-> *(ebp+0x14) 1/r32/ecx +4648 89/<- *(eax+8) 1/r32/ecx # Stmt-var-is-deref +4649 # if (list == null) return result +4650 81 7/subop/compare *(ebp+0x10) 0/imm32 +4651 74/jump-if-= $append-stmt-var:end/disp8 +4652 # otherwise append +4653 # var curr/ecx: (handle stmt-var) = vars +4654 8b/-> *(ebp+0x10) 1/r32/ecx +4655 # while (curr->next != null) curr = curr->next +4656 { +4657 81 7/subop/compare *(ecx+4) 0/imm32 # List-next +4658 74/jump-if-= break/disp8 +4659 # curr = curr->next +4660 8b/-> *(ecx+4) 1/r32/ecx +4661 eb/jump loop/disp8 +4662 } +4663 # curr->next = result +4664 89/<- *(ecx+4) 0/r32/eax +4665 # return vars +4666 8b/-> *(ebp+0x10) 0/r32/eax +4667 $append-stmt-var:end: +4668 # . restore registers +4669 59/pop-to-ecx +4670 # . epilogue +4671 89/<- %esp 5/r32/ebp +4672 5d/pop-to-ebp +4673 c3/return +4674 +4675 append-to-block: # ad: (addr allocation-descriptor), block: (handle block), x: (handle stmt) +4676 # . prologue +4677 55/push-ebp +4678 89/<- %ebp 4/r32/esp +4679 # . save registers +4680 56/push-esi +4681 # esi = block +4682 8b/-> *(ebp+0xc) 6/r32/esi +4683 (append-list *(ebp+8) *(ebp+0x10) *(esi+4)) # ad, x, Block-statements +4684 89/<- *(esi+4) 0/r32/eax # Block-statements +4685 $append-to-block:end: +4686 # . restore registers +4687 5e/pop-to-esi +4688 # . epilogue +4689 89/<- %esp 5/r32/ebp +4690 5d/pop-to-ebp +4691 c3/return +4692 +4693 ####################################################### +4694 # Type-checking +4695 ####################################################### +4696 +4697 check-mu-types: +4698 # . prologue +4699 55/push-ebp +4700 89/<- %ebp 4/r32/esp +4701 # +4702 $check-mu-types:end: +4703 # . epilogue +4704 89/<- %esp 5/r32/ebp +4705 5d/pop-to-ebp +4706 c3/return +4707 +4708 size-of: # v: (addr var) -> result/eax: int +4709 # . prologue +4710 55/push-ebp +4711 89/<- %ebp 4/r32/esp +4712 # if v is a literal, return 0 +4713 8b/-> *(ebp+8) 0/r32/eax +4714 8b/-> *(eax+4) 0/r32/eax # Var-type +4715 81 7/subop/compare *eax 0/imm32 # Tree-left +4716 b8/copy-to-eax 0/imm32 +4717 74/jump-if-= $size-of:end/disp8 +4718 # hard-coded since we only support 'int' types for now +4719 b8/copy-to-eax 4/imm32 +4720 $size-of:end: +4721 # . epilogue +4722 89/<- %esp 5/r32/ebp +4723 5d/pop-to-ebp +4724 c3/return +4725 +4726 type-equal?: # a: (handle tree type-id), b: (handle tree type-id) -> result/eax: boolean +4727 # . prologue +4728 55/push-ebp +4729 89/<- %ebp 4/r32/esp +4730 # . save registers +4731 51/push-ecx +4732 52/push-edx +4733 # ecx = a +4734 8b/-> *(ebp+8) 1/r32/ecx +4735 # edx = b +4736 8b/-> *(ebp+0xc) 2/r32/edx +4737 # if (a == b) return true +4738 8b/-> %ecx 0/r32/eax # Var-type +4739 39/compare %edx 0/r32/eax # Var-type +4740 b8/copy-to-eax 1/imm32/true +4741 74/jump-if-= $type-equal?:end/disp8 +4742 # if (a < MAX_TYPE_ID) return false +4743 81 7/subop/compare %ecx 0x10000/imm32 +4744 b8/copy-to-eax 0/imm32/false +4745 72/jump-if-addr< $type-equal?:end/disp8 +4746 # if (b < MAX_TYPE_ID) return false +4747 81 7/subop/compare %edx 0x10000/imm32 +4748 b8/copy-to-eax 0/imm32/false +4749 72/jump-if-addr< $type-equal?:end/disp8 +4750 # if (!type-equal?(a->left, b->left)) return false +4751 (type-equal? *ecx *edx) # Tree-left, Tree-left => eax +4752 3d/compare-eax-and 0/imm32/false +4753 74/jump-if-= $type-equal?:end/disp8 +4754 # return type-equal?(a->right, b->right) +4755 (type-equal? *(ecx+4) *(edx+4)) # Tree-right, Tree-right => eax +4756 $type-equal?:end: +4757 # . restore registers +4758 5a/pop-to-edx +4759 59/pop-to-ecx +4760 # . epilogue +4761 89/<- %esp 5/r32/ebp +4762 5d/pop-to-ebp +4763 c3/return +4764 +4765 == data +4766 +4767 # not yet used, but it will be +4768 Type-size: # (stream int) +4769 0x18/imm32/write +4770 0/imm32/read +4771 0x100/imm32/length +4772 # data +4773 4/imm32 # literal +4774 4/imm32 # int +4775 4/imm32 # addr +4776 0/imm32 # array (logic elsewhere) +4777 8/imm32 # handle (fat pointer) +4778 4/imm32 # bool +4779 0/imm32 +4780 0/imm32 +4781 # 0x20 +4782 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 +4783 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 +4784 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 +4785 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 +4786 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 +4787 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 +4788 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 +4789 +4790 == code +4791 +4792 ####################################################### +4793 # Code-generation +4794 ####################################################### +4795 +4796 emit-subx: # out: (addr buffered-file) +4797 # . prologue +4798 55/push-ebp +4799 89/<- %ebp 4/r32/esp +4800 # . save registers +4801 50/push-eax +4802 51/push-ecx +4803 57/push-edi +4804 # edi = out +4805 8b/-> *(ebp+8) 7/r32/edi +4806 # var curr/ecx: (handle function) = *Program +4807 8b/-> *Program 1/r32/ecx +4808 { +4809 # if (curr == null) break +4810 81 7/subop/compare %ecx 0/imm32 +4811 0f 84/jump-if-= break/disp32 +4812 (emit-subx-function %edi %ecx) +4813 # curr = curr->next +4814 8b/-> *(ecx+0x14) 1/r32/ecx # Function-next +4815 e9/jump loop/disp32 +4816 } +4817 $emit-subx:end: +4818 # . restore registers +4819 5f/pop-to-edi +4820 59/pop-to-ecx +4821 58/pop-to-eax +4822 # . epilogue +4823 89/<- %esp 5/r32/ebp +4824 5d/pop-to-ebp +4825 c3/return +4826 +4827 emit-subx-function: # out: (addr buffered-file), f: (handle function) +4828 # . prologue +4829 55/push-ebp +4830 89/<- %ebp 4/r32/esp +4831 # . save registers +4832 50/push-eax +4833 51/push-ecx +4834 52/push-edx +4835 57/push-edi +4836 # edi = out +4837 8b/-> *(ebp+8) 7/r32/edi +4838 # ecx = f +4839 8b/-> *(ebp+0xc) 1/r32/ecx +4840 # var vars/edx: (stack (addr var) 256) +4841 81 5/subop/subtract %esp 0x400/imm32 +4842 68/push 0x400/imm32/length +4843 68/push 0/imm32/top +4844 89/<- %edx 4/r32/esp +4845 # +4846 (write-buffered %edi *ecx) +4847 (write-buffered %edi ":\n") +4848 # Important: each block's depth during code-generation should be identical +4849 # to what it was during parsing. +4850 c7 0/subop/copy *Curr-block-depth 1/imm32 +4851 (emit-subx-prologue %edi) +4852 (emit-subx-block %edi *(ecx+0x10) %edx) # Function-body +4853 (emit-subx-epilogue %edi) +4854 $emit-subx-function:end: +4855 # . reclaim locals +4856 81 0/subop/add %esp 408/imm32 +4857 # . restore registers +4858 5f/pop-to-edi +4859 5a/pop-to-edx +4860 59/pop-to-ecx +4861 58/pop-to-eax +4862 # . epilogue +4863 89/<- %esp 5/r32/ebp +4864 5d/pop-to-ebp +4865 c3/return +4866 +4867 emit-subx-stmt-list: # out: (addr buffered-file), stmts: (handle list stmt), vars: (addr stack (handle var)) +4868 # . prologue +4869 55/push-ebp +4870 89/<- %ebp 4/r32/esp +4871 # . save registers +4872 50/push-eax +4873 51/push-ecx +4874 52/push-edx +4875 53/push-ebx +4876 56/push-esi +4877 # esi = stmts +4878 8b/-> *(ebp+0xc) 6/r32/esi +4879 # var var-seen?/edx: boolean <- copy false +4880 ba/copy-to-edx 0/imm32/false +4881 # +4882 { +4883 $emit-subx-stmt-list:loop: +4884 81 7/subop/compare %esi 0/imm32 +4885 0f 84/jump-if-= break/disp32 +4886 # var curr-stmt/ecx = stmts->value +4887 8b/-> *esi 1/r32/ecx # List-value +4888 { +4889 $emit-subx-stmt-list:check-for-block: +4890 81 7/subop/compare *ecx 0/imm32/block # Stmt-tag +4891 75/jump-if-!= break/disp8 +4892 $emit-subx-stmt-list:block: +4893 (emit-subx-block *(ebp+8) %ecx *(ebp+0x10)) +4894 } +4895 { +4896 $emit-subx-stmt-list:check-for-stmt: +4897 81 7/subop/compare *ecx 1/imm32/stmt1 # Stmt-tag +4898 0f 85/jump-if-!= break/disp32 +4899 $emit-subx-stmt-list:stmt1: +4900 { +4901 (is-mu-branch? %ecx) # => eax +4902 3d/compare-eax-and 0/imm32/false +4903 0f 84/jump-if-= break/disp32 +4904 $emit-subx-stmt-list:branch-stmt: +4905 # if !var-seen? break +4906 81 7/subop/compare %edx 0/imm32/false +4907 0f 84/jump-if-= break/disp32 +4908 $emit-subx-stmt-list:branch-stmt-and-var-seen: +4909 +-- 26 lines: # unconditional loops ----------------------------------------------------------------------------------------------------------------------------------------------------- +4935 +-- 15 lines: # unconditional breaks ---------------------------------------------------------------------------------------------------------------------------------------------------- +4950 +-- 37 lines: # simple conditional branches without a target ---------------------------------------------------------------------------------------------------------------------------- +4987 +-- 19 lines: # conditional branches with an explicit target ---------------------------------------------------------------------------------------------------------------------------- +5006 } +5007 $emit-subx-stmt-list:1-to-1: +5008 (emit-subx-statement *(ebp+8) %ecx Primitives *Program) +5009 } +5010 { +5011 $emit-subx-stmt-list:check-for-vardef: +5012 81 7/subop/compare *ecx 2/imm32/vardef # Stmt-tag +5013 75/jump-if-!= break/disp8 +5014 $emit-subx-stmt-list:vardef: +5015 (emit-subx-var-def *(ebp+8) %ecx) +5016 (push *(ebp+0x10) *(ecx+4)) # Vardef-var +5017 # var-seen? = true +5018 ba/copy-to-edx 1/imm32/true +5019 } +5020 { +5021 $emit-subx-stmt-list:check-for-regvardef: +5022 81 7/subop/compare *ecx 3/imm32/regvardef # Stmt-tag +5023 0f 85/jump-if-!= break/disp32 +5024 $emit-subx-stmt-list:regvardef: +5025 # TODO: ensure that there's exactly one output +5026 # var output/eax: (handle var) = curr-stmt->outputs->value +5027 8b/-> *(ecx+0xc) 0/r32/eax +5028 8b/-> *eax 0/r32/eax +5029 # ensure that output is in a register +5030 81 7/subop/compare *(eax+0x10) 0/imm32 # Var-register +5031 0f 84/jump-if-= $emit-subx-stmt-list:abort-regvardef-without-register/disp32 +5032 # emit spill +5033 (emit-indent *(ebp+8) *Curr-block-depth) +5034 (write-buffered *(ebp+8) "ff 6/subop/push %") +5035 (write-buffered *(ebp+8) *(eax+0x10)) +5036 (write-buffered *(ebp+8) Newline) +5037 # register variable definition +5038 (push *(ebp+0x10) %eax) +5039 # emit the instruction as usual +5040 (emit-subx-statement *(ebp+8) %ecx Primitives *Program) +5041 # var-seen? = true +5042 ba/copy-to-edx 1/imm32/true +5043 } +5044 $emit-subx-stmt-list:continue: +5045 # TODO: raise an error on unrecognized Stmt-tag +5046 8b/-> *(esi+4) 6/r32/esi # List-next +5047 e9/jump loop/disp32 +5048 } +5049 $emit-subx-stmt-list:emit-cleanup: +5050 (emit-cleanup-code-until-depth *(ebp+8) *(ebp+0x10) *Curr-block-depth) +5051 $emit-subx-stmt-list:cleanup: +5052 (clean-up-blocks *(ebp+0x10) *Curr-block-depth) +5053 $emit-subx-stmt-list:end: +5054 # . restore registers +5055 5e/pop-to-esi +5056 5b/pop-to-ebx +5057 5a/pop-to-edx +5058 59/pop-to-ecx +5059 58/pop-to-eax +5060 # . epilogue +5061 89/<- %esp 5/r32/ebp +5062 5d/pop-to-ebp +5063 c3/return +5064 +5065 $emit-subx-stmt-list:abort-regvardef-without-register: +5066 # error("var '" var->name "' initialized from an instruction must live in a register\n") +5067 (write-buffered Stderr "var '") +5068 (write-buffered Stderr *eax) # Var-name +5069 (write-buffered Stderr "' initialized from an instruction must live in a register\n") +5070 (flush Stderr) +5071 # . syscall(exit, 1) +5072 bb/copy-to-ebx 1/imm32 +5073 b8/copy-to-eax 1/imm32/exit +5074 cd/syscall 0x80/imm8 +5075 # never gets here +5076 +5077 emit-subx-cleanup-and-unconditional-nonlocal-branch: # out: (addr buffered-file), stmt: (addr stmt1), vars: (addr stack (handle var)) +5078 # . prologue +5079 55/push-ebp +5080 89/<- %ebp 4/r32/esp +5081 # . save registers +5082 50/push-eax +5083 51/push-ecx +5084 52/push-edx +5085 # ecx = stmt +5086 8b/-> *(ebp+0xc) 1/r32/ecx +5087 # var target/edx: (addr array byte) = curr-stmt->inouts->value->name +5088 8b/-> *(ecx+8) 2/r32/edx # Stmt1-inouts +5089 8b/-> *edx 2/r32/edx # Stmt-var-value +5090 8b/-> *edx 2/r32/edx # Var-name +5091 # clean up until target block +5092 (emit-cleanup-code-until-target *(ebp+8) *(ebp+0x10) %edx) +5093 # emit jump to target block +5094 (emit-indent *(ebp+8) *Curr-block-depth) +5095 (write-buffered *(ebp+8) "e9/jump ") +5096 (write-buffered *(ebp+8) %edx) +5097 (string-starts-with? *(ecx+4) "break") +5098 3d/compare-eax-and 0/imm32/false +5099 { +5100 74/jump-if-= break/disp8 +5101 (write-buffered *(ebp+8) ":break/disp32\n") +5102 } +5103 3d/compare-eax-and 0/imm32/false # just in case the function call modified flags +5104 { +5105 75/jump-if-!= break/disp8 +5106 (write-buffered *(ebp+8) ":loop/disp32\n") +5107 } +5108 $emit-subx-cleanup-and-unconditional-nonlocal-branch:end: 5109 # . restore registers -5110 58/pop-to-eax -5111 # . epilogue -5112 89/<- %esp 5/r32/ebp -5113 5d/pop-to-ebp -5114 c3/return -5115 -5116 == data +5110 5a/pop-to-edx +5111 59/pop-to-ecx +5112 58/pop-to-eax +5113 # . epilogue +5114 89/<- %esp 5/r32/ebp +5115 5d/pop-to-ebp +5116 c3/return 5117 -5118 Reverse-branch: # (table string string) -5119 # a table is a stream -5120 0xa0/imm32/write -5121 0/imm32/read -5122 0xa0/imm32/length -5123 # data -5124 "break-if-="/imm32 "0f 85/jump-if-!="/imm32 -5125 "loop-if-="/imm32 "0f 85/jump-if-!="/imm32 -5126 "break-if-!="/imm32 "0f 84/jump-if-="/imm32 -5127 "loop-if-!="/imm32 "0f 84/jump-if-="/imm32 -5128 "break-if-<"/imm32 "0f 8d/jump-if->="/imm32 -5129 "loop-if-<"/imm32 "0f 8d/jump-if->="/imm32 -5130 "break-if->"/imm32 "0f 8e/jump-if-<="/imm32 -5131 "loop-if->"/imm32 "0f 8e/jump-if-<="/imm32 -5132 "break-if-<="/imm32 "0f 87/jump-if->"/imm32 -5133 "loop-if-<="/imm32 "0f 87/jump-if->"/imm32 -5134 "break-if->="/imm32 "0f 8c/jump-if-<"/imm32 -5135 "loop-if->="/imm32 "0f 8c/jump-if-<"/imm32 -5136 "break-if-addr<"/imm32 "0f 83/jump-if-addr>="/imm32 -5137 "loop-if-addr<"/imm32 "0f 83/jump-if-addr>="/imm32 -5138 "break-if-addr>"/imm32 "0f 86/jump-if-addr<="/imm32 -5139 "loop-if-addr>"/imm32 "0f 86/jump-if-addr<="/imm32 -5140 "break-if-addr<="/imm32 "0f 87/jump-if-addr>"/imm32 -5141 "loop-if-addr<="/imm32 "0f 87/jump-if-addr>"/imm32 -5142 "break-if-addr>="/imm32 "0f 82/jump-if-addr<"/imm32 -5143 "loop-if-addr>="/imm32 "0f 82/jump-if-addr<"/imm32 -5144 -5145 == code -5146 -5147 emit-unconditional-jump-to-depth: # out: (addr buffered-file), vars: (addr stack (handle var)), depth: int, label-suffix: (addr array byte) -5148 # . prologue -5149 55/push-ebp -5150 89/<- %ebp 4/r32/esp -5151 # . save registers -5152 50/push-eax -5153 51/push-ecx -5154 52/push-edx -5155 53/push-ebx -5156 # ecx = vars -5157 8b/-> *(ebp+0xc) 1/r32/ecx -5158 # var eax: int = vars->top -5159 8b/-> *ecx 0/r32/eax -5160 # var min/ecx: (address (handle var)) = vars->data -5161 81 0/subop/add %ecx 8/imm32 -5162 # var curr/eax: (address (handle var)) = &vars->data[vars->top - 4] -5163 81 5/subop/subtract %eax 4/imm32 -5164 8d/copy-address *(ecx+eax) 0/r32/eax -5165 # edx = depth -5166 8b/-> *(ebp+0x10) 2/r32/edx -5167 { -5168 $emit-unconditional-jump-to-depth:loop: -5169 # if (curr < min) break -5170 39/compare %eax 1/r32/ecx -5171 0f 82/jump-if-addr< break/disp32 -5172 # var v/ebx: (handle var) = *curr -5173 8b/-> *eax 3/r32/ebx -5174 # if (v->block-depth < until-block-depth) break -5175 39/compare *(ebx+8) 2/r32/edx # Var-block-depth -5176 0f 8c/jump-if-< break/disp32 -5177 { -5178 $emit-unconditional-jump-to-depth:check: -5179 # if v->block-depth != until-block-depth, continue -5180 39/compare *(ebx+8) 2/r32/edx # Var-block-depth -5181 0f 85/jump-if-!= break/disp32 -5182 $emit-unconditional-jump-to-depth:depth-found: -5183 # if v is not a literal, continue -5184 # . var eax: int = size-of(v) -5185 50/push-eax -5186 (size-of %ebx) # => eax -5187 # . if (eax != 0) continue -5188 3d/compare-eax-and 0/imm32 -5189 58/pop-to-eax -5190 # -5191 0f 85/jump-if-!= break/disp32 -5192 $emit-unconditional-jump-to-depth:label-found: -5193 # emit unconditional jump, then return -5194 (emit-indent *(ebp+8) *Curr-block-depth) -5195 (write-buffered *(ebp+8) "e9/jump ") -5196 (write-buffered *(ebp+8) *ebx) # Var-name -5197 (write-buffered *(ebp+8) ":") -5198 (write-buffered *(ebp+8) *(ebp+0x14)) -5199 (write-buffered *(ebp+8) "/disp32\n") -5200 eb/jump $emit-unconditional-jump-to-depth:end/disp8 -5201 } -5202 # curr -= 4 -5203 2d/subtract-from-eax 4/imm32 -5204 e9/jump loop/disp32 -5205 } -5206 # TODO: error if no label at 'depth' was found -5207 $emit-unconditional-jump-to-depth:end: -5208 # . restore registers -5209 5b/pop-to-ebx -5210 5a/pop-to-edx -5211 59/pop-to-ecx -5212 58/pop-to-eax -5213 # . epilogue -5214 89/<- %esp 5/r32/ebp -5215 5d/pop-to-ebp -5216 c3/return -5217 -5218 # emit clean-up code for 'vars' until some block depth -5219 # doesn't actually modify 'vars' so we need traverse manually inside the stack -5220 emit-cleanup-code-until-depth: # out: (addr buffered-file), vars: (addr stack (handle var)), until-block-depth: int -5221 # . prologue -5222 55/push-ebp -5223 89/<- %ebp 4/r32/esp -5224 # . save registers -5225 50/push-eax -5226 51/push-ecx -5227 52/push-edx -5228 53/push-ebx -5229 # ecx = vars -5230 8b/-> *(ebp+0xc) 1/r32/ecx -5231 # var eax: int = vars->top -5232 8b/-> *ecx 0/r32/eax -5233 # var min/ecx: (address (handle var)) = vars->data -5234 81 0/subop/add %ecx 8/imm32 -5235 # var curr/eax: (address (handle var)) = &vars->data[vars->top - 4] -5236 81 5/subop/subtract %eax 4/imm32 -5237 8d/copy-address *(ecx+eax) 0/r32/eax -5238 # edx = until-block-depth -5239 8b/-> *(ebp+0x10) 2/r32/edx -5240 { -5241 $emit-cleanup-code-until-depth:loop: -5242 # if (curr < min) break -5243 39/compare %eax 1/r32/ecx -5244 0f 82/jump-if-addr< break/disp32 -5245 # var v/ebx: (handle var) = *curr -5246 8b/-> *eax 3/r32/ebx -5247 # if (v->block-depth < until-block-depth) break -5248 39/compare *(ebx+8) 2/r32/edx # Var-block-depth -5249 0f 8c/jump-if-< break/disp32 -5250 # if v is in a register -5251 81 7/subop/compare *(ebx+0x10) 0/imm32 # Var-register -5252 { -5253 74/jump-if-= break/disp8 -5254 $emit-cleanup-code-until-depth:reclaim-var-in-register: -5255 (emit-indent *(ebp+8) *Curr-block-depth) -5256 (write-buffered *(ebp+8) "8f 0/subop/pop %") -5257 (write-buffered *(ebp+8) *(ebx+0x10)) -5258 (write-buffered *(ebp+8) Newline) -5259 } -5260 # otherwise v is on the stack -5261 { -5262 75/jump-if-!= break/disp8 -5263 $emit-cleanup-code-until-depth:reclaim-var-on-stack: -5264 50/push-eax -5265 (size-of %ebx) # => eax -5266 # don't emit code for labels -5267 3d/compare-eax-and 0/imm32 -5268 74/jump-if-= break/disp8 -5269 # -5270 (emit-indent *(ebp+8) *Curr-block-depth) -5271 (write-buffered *(ebp+8) "81 0/subop/add %esp ") -5272 (print-int32-buffered *(ebp+8) %eax) -5273 (write-buffered *(ebp+8) "/imm32\n") -5274 58/pop-to-eax -5275 } -5276 # curr -= 4 -5277 2d/subtract-from-eax 4/imm32 -5278 e9/jump loop/disp32 -5279 } -5280 $emit-cleanup-code-until-depth:end: -5281 # . restore registers -5282 5b/pop-to-ebx -5283 5a/pop-to-edx -5284 59/pop-to-ecx -5285 58/pop-to-eax -5286 # . epilogue -5287 89/<- %esp 5/r32/ebp -5288 5d/pop-to-ebp -5289 c3/return -5290 -5291 # emit clean-up code for 'vars' until a given label is encountered -5292 # doesn't actually modify 'vars' so we need traverse manually inside the stack -5293 emit-cleanup-code-until-target: # out: (addr buffered-file), vars: (addr stack (handle var)), until-block-label: (addr array byte) -5294 # . prologue -5295 55/push-ebp -5296 89/<- %ebp 4/r32/esp -5297 # . save registers -5298 50/push-eax -5299 51/push-ecx -5300 52/push-edx -5301 53/push-ebx -5302 # ecx = vars -5303 8b/-> *(ebp+0xc) 1/r32/ecx -5304 # var eax: int = vars->top -5305 8b/-> *ecx 0/r32/eax -5306 # var min/ecx: (address (handle var)) = vars->data -5307 81 0/subop/add %ecx 8/imm32 -5308 # var curr/edx: (address (handle var)) = &vars->data[vars->top - 4] -5309 81 5/subop/subtract %eax 4/imm32 -5310 8d/copy-address *(ecx+eax) 2/r32/edx -5311 { -5312 $emit-cleanup-code-until-target:loop: -5313 # if (curr < min) break -5314 39/compare %edx 1/r32/ecx -5315 0f 82/jump-if-addr< break/disp32 -5316 # var v/ebx: (handle var) = *curr -5317 8b/-> *edx 3/r32/ebx -5318 # if (v->name == until-block-label) break -5319 (string-equal? *ebx *(ebp+0x10)) # => eax -5320 3d/compare-eax-and 0/imm32/false -5321 0f 85/jump-if-!= break/disp32 -5322 # if v is in a register -5323 81 7/subop/compare *(ebx+0x10) 0/imm32 # Var-register -5324 { -5325 74/jump-if-= break/disp8 -5326 $emit-cleanup-code-until-target:reclaim-var-in-register: -5327 (emit-indent *(ebp+8) *Curr-block-depth) -5328 (write-buffered *(ebp+8) "8f 0/subop/pop %") -5329 (write-buffered *(ebp+8) *(ebx+0x10)) -5330 (write-buffered *(ebp+8) Newline) -5331 } -5332 # otherwise v is on the stack -5333 { -5334 75/jump-if-!= break/disp8 -5335 $emit-cleanup-code-until-target:reclaim-var-on-stack: -5336 (size-of %ebx) # => eax -5337 # don't emit code for labels -5338 3d/compare-eax-and 0/imm32 -5339 74/jump-if-= break/disp8 -5340 # -5341 (emit-indent *(ebp+8) *Curr-block-depth) -5342 (write-buffered *(ebp+8) "81 0/subop/add %esp ") -5343 (print-int32-buffered *(ebp+8) %eax) -5344 (write-buffered *(ebp+8) "/imm32\n") -5345 } -5346 # curr -= 4 -5347 81 5/subop/subtract %edx 4/imm32 -5348 e9/jump loop/disp32 -5349 } -5350 $emit-cleanup-code-until-target:end: -5351 # . restore registers -5352 5b/pop-to-ebx -5353 5a/pop-to-edx -5354 59/pop-to-ecx -5355 58/pop-to-eax -5356 # . epilogue -5357 89/<- %esp 5/r32/ebp -5358 5d/pop-to-ebp -5359 c3/return -5360 -5361 # clean up global state for 'vars' until some block depth -5362 clean-up-blocks: # vars: (addr stack (handle var)), until-block-depth: int -5363 # . prologue -5364 55/push-ebp -5365 89/<- %ebp 4/r32/esp -5366 # . save registers -5367 50/push-eax -5368 51/push-ecx -5369 56/push-esi -5370 # esi = vars -5371 8b/-> *(ebp+8) 6/r32/esi -5372 # ecx = until-block-depth -5373 8b/-> *(ebp+0xc) 1/r32/ecx -5374 { -5375 $clean-up-blocks:reclaim-loop: -5376 # if (vars->top <= 0) break -5377 81 7/subop/compare *esi 0/imm32 # Stack-top -5378 7e/jump-if-<= break/disp8 -5379 # var v/eax: (handle var) = top(vars) -5380 (top %esi) # => eax -5381 # if (v->block-depth < until-block-depth) break -5382 39/compare *(eax+8) 1/r32/ecx # Var-block-depth -5383 7c/jump-if-< break/disp8 -5384 # if v is on the stack, update Next-local-stack-offset -5385 81 7/subop/compare *(eax+0x10) 0/imm32 # Var-register -5386 { -5387 75/jump-if-!= break/disp8 -5388 $clean-up-blocks:reclaim-var-on-stack: -5389 (size-of %eax) # => eax -5390 01/add *Next-local-stack-offset 0/r32/eax -5391 } -5392 (pop %esi) +5118 is-mu-branch?: # stmt: (addr stmt1) -> result/eax: boolean +5119 # . prologue +5120 55/push-ebp +5121 89/<- %ebp 4/r32/esp +5122 # . save registers +5123 51/push-ecx +5124 # ecx = stmt +5125 8b/-> *(ebp+8) 1/r32/ecx +5126 # if (stmt->operation starts with "loop") return true +5127 (string-starts-with? *(ecx+4) "loop") # Stmt1-operation => eax +5128 3d/compare-eax-and 0/imm32/false +5129 75/jump-if-not-equal $is-mu-branch?:end/disp8 +5130 # otherwise return (stmt->operation starts with "break") +5131 (string-starts-with? *(ecx+4) "break") # Stmt1-operation => eax +5132 $is-mu-branch?:end: +5133 # . restore registers +5134 59/pop-to-ecx +5135 # . epilogue +5136 89/<- %esp 5/r32/ebp +5137 5d/pop-to-ebp +5138 c3/return +5139 +5140 emit-reverse-break: # out: (addr buffered-file), stmt: (addr stmt1) +5141 # . prologue +5142 55/push-ebp +5143 89/<- %ebp 4/r32/esp +5144 # . save registers +5145 50/push-eax +5146 # eax = stmt +5147 8b/-> *(ebp+0xc) 0/r32/eax +5148 # +5149 (get Reverse-branch *(eax+4) 8 "reverse-branch: ") # Stmt1-operation => eax: (addr addr array byte) +5150 (emit-indent *(ebp+8) *Curr-block-depth) +5151 (write-buffered *(ebp+8) *eax) +5152 (write-buffered *(ebp+8) " break/disp32\n") +5153 $emit-reverse-break:end: +5154 # . restore registers +5155 58/pop-to-eax +5156 # . epilogue +5157 89/<- %esp 5/r32/ebp +5158 5d/pop-to-ebp +5159 c3/return +5160 +5161 == data +5162 +5163 Reverse-branch: # (table string string) +5164 # a table is a stream +5165 0xa0/imm32/write +5166 0/imm32/read +5167 0xa0/imm32/length +5168 # data +5169 "break-if-="/imm32 "0f 85/jump-if-!="/imm32 +5170 "loop-if-="/imm32 "0f 85/jump-if-!="/imm32 +5171 "break-if-!="/imm32 "0f 84/jump-if-="/imm32 +5172 "loop-if-!="/imm32 "0f 84/jump-if-="/imm32 +5173 "break-if-<"/imm32 "0f 8d/jump-if->="/imm32 +5174 "loop-if-<"/imm32 "0f 8d/jump-if->="/imm32 +5175 "break-if->"/imm32 "0f 8e/jump-if-<="/imm32 +5176 "loop-if->"/imm32 "0f 8e/jump-if-<="/imm32 +5177 "break-if-<="/imm32 "0f 87/jump-if->"/imm32 +5178 "loop-if-<="/imm32 "0f 87/jump-if->"/imm32 +5179 "break-if->="/imm32 "0f 8c/jump-if-<"/imm32 +5180 "loop-if->="/imm32 "0f 8c/jump-if-<"/imm32 +5181 "break-if-addr<"/imm32 "0f 83/jump-if-addr>="/imm32 +5182 "loop-if-addr<"/imm32 "0f 83/jump-if-addr>="/imm32 +5183 "break-if-addr>"/imm32 "0f 86/jump-if-addr<="/imm32 +5184 "loop-if-addr>"/imm32 "0f 86/jump-if-addr<="/imm32 +5185 "break-if-addr<="/imm32 "0f 87/jump-if-addr>"/imm32 +5186 "loop-if-addr<="/imm32 "0f 87/jump-if-addr>"/imm32 +5187 "break-if-addr>="/imm32 "0f 82/jump-if-addr<"/imm32 +5188 "loop-if-addr>="/imm32 "0f 82/jump-if-addr<"/imm32 +5189 +5190 == code +5191 +5192 emit-unconditional-jump-to-depth: # out: (addr buffered-file), vars: (addr stack (handle var)), depth: int, label-suffix: (addr array byte) +5193 # . prologue +5194 55/push-ebp +5195 89/<- %ebp 4/r32/esp +5196 # . save registers +5197 50/push-eax +5198 51/push-ecx +5199 52/push-edx +5200 53/push-ebx +5201 # ecx = vars +5202 8b/-> *(ebp+0xc) 1/r32/ecx +5203 # var eax: int = vars->top +5204 8b/-> *ecx 0/r32/eax +5205 # var min/ecx: (address (handle var)) = vars->data +5206 81 0/subop/add %ecx 8/imm32 +5207 # var curr/eax: (address (handle var)) = &vars->data[vars->top - 4] +5208 81 5/subop/subtract %eax 4/imm32 +5209 8d/copy-address *(ecx+eax) 0/r32/eax +5210 # edx = depth +5211 8b/-> *(ebp+0x10) 2/r32/edx +5212 { +5213 $emit-unconditional-jump-to-depth:loop: +5214 # if (curr < min) break +5215 39/compare %eax 1/r32/ecx +5216 0f 82/jump-if-addr< break/disp32 +5217 # var v/ebx: (handle var) = *curr +5218 8b/-> *eax 3/r32/ebx +5219 # if (v->block-depth < until-block-depth) break +5220 39/compare *(ebx+8) 2/r32/edx # Var-block-depth +5221 0f 8c/jump-if-< break/disp32 +5222 { +5223 $emit-unconditional-jump-to-depth:check: +5224 # if v->block-depth != until-block-depth, continue +5225 39/compare *(ebx+8) 2/r32/edx # Var-block-depth +5226 0f 85/jump-if-!= break/disp32 +5227 $emit-unconditional-jump-to-depth:depth-found: +5228 # if v is not a literal, continue +5229 # . var eax: int = size-of(v) +5230 50/push-eax +5231 (size-of %ebx) # => eax +5232 # . if (eax != 0) continue +5233 3d/compare-eax-and 0/imm32 +5234 58/pop-to-eax +5235 # +5236 0f 85/jump-if-!= break/disp32 +5237 $emit-unconditional-jump-to-depth:label-found: +5238 # emit unconditional jump, then return +5239 (emit-indent *(ebp+8) *Curr-block-depth) +5240 (write-buffered *(ebp+8) "e9/jump ") +5241 (write-buffered *(ebp+8) *ebx) # Var-name +5242 (write-buffered *(ebp+8) ":") +5243 (write-buffered *(ebp+8) *(ebp+0x14)) +5244 (write-buffered *(ebp+8) "/disp32\n") +5245 eb/jump $emit-unconditional-jump-to-depth:end/disp8 +5246 } +5247 # curr -= 4 +5248 2d/subtract-from-eax 4/imm32 +5249 e9/jump loop/disp32 +5250 } +5251 # TODO: error if no label at 'depth' was found +5252 $emit-unconditional-jump-to-depth:end: +5253 # . restore registers +5254 5b/pop-to-ebx +5255 5a/pop-to-edx +5256 59/pop-to-ecx +5257 58/pop-to-eax +5258 # . epilogue +5259 89/<- %esp 5/r32/ebp +5260 5d/pop-to-ebp +5261 c3/return +5262 +5263 # emit clean-up code for 'vars' until some block depth +5264 # doesn't actually modify 'vars' so we need traverse manually inside the stack +5265 emit-cleanup-code-until-depth: # out: (addr buffered-file), vars: (addr stack (handle var)), until-block-depth: int +5266 # . prologue +5267 55/push-ebp +5268 89/<- %ebp 4/r32/esp +5269 # . save registers +5270 50/push-eax +5271 51/push-ecx +5272 52/push-edx +5273 53/push-ebx +5274 # ecx = vars +5275 8b/-> *(ebp+0xc) 1/r32/ecx +5276 # var eax: int = vars->top +5277 8b/-> *ecx 0/r32/eax +5278 # var min/ecx: (address (handle var)) = vars->data +5279 81 0/subop/add %ecx 8/imm32 +5280 # var curr/eax: (address (handle var)) = &vars->data[vars->top - 4] +5281 81 5/subop/subtract %eax 4/imm32 +5282 8d/copy-address *(ecx+eax) 0/r32/eax +5283 # edx = until-block-depth +5284 8b/-> *(ebp+0x10) 2/r32/edx +5285 { +5286 $emit-cleanup-code-until-depth:loop: +5287 # if (curr < min) break +5288 39/compare %eax 1/r32/ecx +5289 0f 82/jump-if-addr< break/disp32 +5290 # var v/ebx: (handle var) = *curr +5291 8b/-> *eax 3/r32/ebx +5292 # if (v->block-depth < until-block-depth) break +5293 39/compare *(ebx+8) 2/r32/edx # Var-block-depth +5294 0f 8c/jump-if-< break/disp32 +5295 # if v is in a register +5296 81 7/subop/compare *(ebx+0x10) 0/imm32 # Var-register +5297 { +5298 74/jump-if-= break/disp8 +5299 $emit-cleanup-code-until-depth:reclaim-var-in-register: +5300 (emit-indent *(ebp+8) *Curr-block-depth) +5301 (write-buffered *(ebp+8) "8f 0/subop/pop %") +5302 (write-buffered *(ebp+8) *(ebx+0x10)) +5303 (write-buffered *(ebp+8) Newline) +5304 } +5305 # otherwise v is on the stack +5306 { +5307 75/jump-if-!= break/disp8 +5308 $emit-cleanup-code-until-depth:reclaim-var-on-stack: +5309 50/push-eax +5310 (size-of %ebx) # => eax +5311 # don't emit code for labels +5312 3d/compare-eax-and 0/imm32 +5313 74/jump-if-= break/disp8 +5314 # +5315 (emit-indent *(ebp+8) *Curr-block-depth) +5316 (write-buffered *(ebp+8) "81 0/subop/add %esp ") +5317 (print-int32-buffered *(ebp+8) %eax) +5318 (write-buffered *(ebp+8) "/imm32\n") +5319 58/pop-to-eax +5320 } +5321 # curr -= 4 +5322 2d/subtract-from-eax 4/imm32 +5323 e9/jump loop/disp32 +5324 } +5325 $emit-cleanup-code-until-depth:end: +5326 # . restore registers +5327 5b/pop-to-ebx +5328 5a/pop-to-edx +5329 59/pop-to-ecx +5330 58/pop-to-eax +5331 # . epilogue +5332 89/<- %esp 5/r32/ebp +5333 5d/pop-to-ebp +5334 c3/return +5335 +5336 # emit clean-up code for 'vars' until a given label is encountered +5337 # doesn't actually modify 'vars' so we need traverse manually inside the stack +5338 emit-cleanup-code-until-target: # out: (addr buffered-file), vars: (addr stack (handle var)), until-block-label: (addr array byte) +5339 # . prologue +5340 55/push-ebp +5341 89/<- %ebp 4/r32/esp +5342 # . save registers +5343 50/push-eax +5344 51/push-ecx +5345 52/push-edx +5346 53/push-ebx +5347 # ecx = vars +5348 8b/-> *(ebp+0xc) 1/r32/ecx +5349 # var eax: int = vars->top +5350 8b/-> *ecx 0/r32/eax +5351 # var min/ecx: (address (handle var)) = vars->data +5352 81 0/subop/add %ecx 8/imm32 +5353 # var curr/edx: (address (handle var)) = &vars->data[vars->top - 4] +5354 81 5/subop/subtract %eax 4/imm32 +5355 8d/copy-address *(ecx+eax) 2/r32/edx +5356 { +5357 $emit-cleanup-code-until-target:loop: +5358 # if (curr < min) break +5359 39/compare %edx 1/r32/ecx +5360 0f 82/jump-if-addr< break/disp32 +5361 # var v/ebx: (handle var) = *curr +5362 8b/-> *edx 3/r32/ebx +5363 # if (v->name == until-block-label) break +5364 (string-equal? *ebx *(ebp+0x10)) # => eax +5365 3d/compare-eax-and 0/imm32/false +5366 0f 85/jump-if-!= break/disp32 +5367 # if v is in a register +5368 81 7/subop/compare *(ebx+0x10) 0/imm32 # Var-register +5369 { +5370 74/jump-if-= break/disp8 +5371 $emit-cleanup-code-until-target:reclaim-var-in-register: +5372 (emit-indent *(ebp+8) *Curr-block-depth) +5373 (write-buffered *(ebp+8) "8f 0/subop/pop %") +5374 (write-buffered *(ebp+8) *(ebx+0x10)) +5375 (write-buffered *(ebp+8) Newline) +5376 } +5377 # otherwise v is on the stack +5378 { +5379 75/jump-if-!= break/disp8 +5380 $emit-cleanup-code-until-target:reclaim-var-on-stack: +5381 (size-of %ebx) # => eax +5382 # don't emit code for labels +5383 3d/compare-eax-and 0/imm32 +5384 74/jump-if-= break/disp8 +5385 # +5386 (emit-indent *(ebp+8) *Curr-block-depth) +5387 (write-buffered *(ebp+8) "81 0/subop/add %esp ") +5388 (print-int32-buffered *(ebp+8) %eax) +5389 (write-buffered *(ebp+8) "/imm32\n") +5390 } +5391 # curr -= 4 +5392 81 5/subop/subtract %edx 4/imm32 5393 e9/jump loop/disp32 5394 } -5395 $clean-up-blocks:end: +5395 $emit-cleanup-code-until-target:end: 5396 # . restore registers -5397 5e/pop-to-esi -5398 59/pop-to-ecx -5399 58/pop-to-eax -5400 # . epilogue -5401 89/<- %esp 5/r32/ebp -5402 5d/pop-to-ebp -5403 c3/return -5404 -5405 emit-subx-var-def: # out: (addr buffered-file), stmt: (handle statement) -5406 # . prologue -5407 55/push-ebp -5408 89/<- %ebp 4/r32/esp -5409 # . save registers -5410 50/push-eax -5411 51/push-ecx -5412 # eax = stmt -5413 8b/-> *(ebp+0xc) 0/r32/eax -5414 # var n/eax: int = size-of(stmt->var) -5415 (size-of *(eax+4)) # Vardef-var => eax -5416 # while n > 0 -5417 { -5418 3d/compare-eax-with 0/imm32 -5419 7e/jump-if-<= break/disp8 -5420 (emit-indent *(ebp+8) *Curr-block-depth) -5421 (write-buffered *(ebp+8) "68/push 0/imm32\n") -5422 # n -= 4 -5423 2d/subtract-from-eax 4/imm32 -5424 # -5425 eb/jump loop/disp8 -5426 } -5427 $emit-subx-var-def:end: -5428 # . restore registers -5429 59/pop-to-ecx -5430 58/pop-to-eax -5431 # . epilogue -5432 89/<- %esp 5/r32/ebp -5433 5d/pop-to-ebp -5434 c3/return -5435 -5436 emit-subx-statement: # out: (addr buffered-file), stmt: (handle statement), primitives: (handle primitive), functions: (handle function) -5437 # . prologue -5438 55/push-ebp -5439 89/<- %ebp 4/r32/esp -5440 # . save registers -5441 50/push-eax -5442 51/push-ecx -5443 # handle some special cases -5444 # ecx = stmt -5445 8b/-> *(ebp+0xc) 1/r32/ecx -5446 +-- 24 lines: # array length ------------------------------------------------------------------------------------------------------------------------------------------------------------ -5470 # if stmt matches a primitive, emit it -5471 { -5472 $emit-subx-statement:check-for-primitive: -5473 (find-matching-primitive *(ebp+0x10) *(ebp+0xc)) # primitives, stmt => curr/eax -5474 3d/compare-eax-and 0/imm32 -5475 74/jump-if-= break/disp8 -5476 $emit-subx-statement:primitive: -5477 (emit-subx-primitive *(ebp+8) *(ebp+0xc) %eax) # out, stmt, curr -5478 e9/jump $emit-subx-statement:end/disp32 -5479 } -5480 # else if stmt matches a function, emit a call to it -5481 { -5482 $emit-subx-statement:check-for-call: -5483 (find-matching-function *(ebp+0x14) *(ebp+0xc)) # functions, stmt => curr/eax -5484 3d/compare-eax-and 0/imm32 -5485 74/jump-if-= break/disp8 -5486 $emit-subx-statement:call: -5487 (emit-subx-call *(ebp+8) *(ebp+0xc) %eax) # out, stmt, curr -5488 e9/jump $emit-subx-statement:end/disp32 -5489 } -5490 # else assume it's a SubX function (TODO: how to type-check?!) -5491 (emit-hailmary-call *(ebp+8) *(ebp+0xc)) -5492 $emit-subx-statement:end: -5493 # . restore registers -5494 59/pop-to-ecx -5495 58/pop-to-eax -5496 # . epilogue -5497 89/<- %esp 5/r32/ebp -5498 5d/pop-to-ebp -5499 c3/return -5500 -5501 $emit-subx-statement:abort: -5502 # error("couldn't translate '" stmt "'\n") -5503 (write-buffered Stderr "couldn't translate an instruction with operation '") -5504 8b/-> *(ebp+0xc) 0/r32/eax -5505 (write-buffered Stderr *(eax+4)) # Stmt1-operation -5506 (write-buffered Stderr "'\n") -5507 (flush Stderr) -5508 # . syscall(exit, 1) -5509 bb/copy-to-ebx 1/imm32 -5510 b8/copy-to-eax 1/imm32/exit -5511 cd/syscall 0x80/imm8 -5512 # never gets here -5513 -5514 emit-subx-block: # out: (addr buffered-file), block: (handle block), vars: (addr stack (handle var)) -5515 # . prologue -5516 55/push-ebp -5517 89/<- %ebp 4/r32/esp -5518 # . save registers -5519 50/push-eax -5520 51/push-ecx -5521 56/push-esi -5522 # esi = block -5523 8b/-> *(ebp+0xc) 6/r32/esi -5524 # var stmts/eax: (handle list statement) = block->statements -5525 8b/-> *(esi+4) 0/r32/eax # Block-statements -5526 # -5527 { -5528 $emit-subx-block:check-empty: -5529 81 7/subop/compare %eax 0/imm32 -5530 0f 84/jump-if-= break/disp32 -5531 (emit-indent *(ebp+8) *Curr-block-depth) -5532 (write-buffered *(ebp+8) "{\n") -5533 # var v/ecx: (addr array byte) = block->var->name -5534 8b/-> *(esi+8) 1/r32/ecx # Block-var -5535 (write-buffered *(ebp+8) *ecx) # Var-name -5536 (write-buffered *(ebp+8) ":loop:\n") -5537 ff 0/subop/increment *Curr-block-depth -5538 (push *(ebp+0x10) %ecx) -5539 (emit-subx-stmt-list *(ebp+8) %eax *(ebp+0x10)) -5540 (pop *(ebp+0x10)) # => eax -5541 ff 1/subop/decrement *Curr-block-depth -5542 (emit-indent *(ebp+8) *Curr-block-depth) -5543 (write-buffered *(ebp+8) "}\n") -5544 (write-buffered *(ebp+8) *ecx) # Var-name -5545 (write-buffered *(ebp+8) ":break:\n") -5546 } -5547 $emit-subx-block:end: -5548 # . restore registers -5549 5e/pop-to-esi -5550 59/pop-to-ecx -5551 58/pop-to-eax -5552 # . epilogue -5553 89/<- %esp 5/r32/ebp -5554 5d/pop-to-ebp -5555 c3/return -5556 -5557 # Primitives supported -5558 # For each operation, put variants with hard-coded registers before flexible ones. -5559 == data -5560 Primitives: -5561 # - increment/decrement -5562 _Primitive-inc-eax: -5563 # var/eax <- increment => 40/increment-eax -5564 "increment"/imm32/name -5565 0/imm32/no-inouts -5566 Single-int-var-in-eax/imm32/outputs -5567 "40/increment-eax"/imm32/subx-name -5568 0/imm32/no-rm32 -5569 0/imm32/no-r32 -5570 0/imm32/no-imm32 -5571 0/imm32/no-disp32 -5572 0/imm32/output-is-write-only -5573 _Primitive-inc-ecx/imm32/next -5574 _Primitive-inc-ecx: -5575 # var/ecx <- increment => 41/increment-ecx -5576 "increment"/imm32/name -5577 0/imm32/no-inouts -5578 Single-int-var-in-ecx/imm32/outputs -5579 "41/increment-ecx"/imm32/subx-name -5580 0/imm32/no-rm32 -5581 0/imm32/no-r32 -5582 0/imm32/no-imm32 -5583 0/imm32/no-disp32 -5584 0/imm32/output-is-write-only -5585 _Primitive-inc-edx/imm32/next -5586 _Primitive-inc-edx: -5587 # var/edx <- increment => 42/increment-edx -5588 "increment"/imm32/name -5589 0/imm32/no-inouts -5590 Single-int-var-in-edx/imm32/outputs -5591 "42/increment-edx"/imm32/subx-name -5592 0/imm32/no-rm32 -5593 0/imm32/no-r32 -5594 0/imm32/no-imm32 -5595 0/imm32/no-disp32 -5596 0/imm32/output-is-write-only -5597 _Primitive-inc-ebx/imm32/next -5598 _Primitive-inc-ebx: -5599 # var/ebx <- increment => 43/increment-ebx -5600 "increment"/imm32/name -5601 0/imm32/no-inouts -5602 Single-int-var-in-ebx/imm32/outputs -5603 "43/increment-ebx"/imm32/subx-name -5604 0/imm32/no-rm32 -5605 0/imm32/no-r32 -5606 0/imm32/no-imm32 -5607 0/imm32/no-disp32 -5608 0/imm32/output-is-write-only -5609 _Primitive-inc-esi/imm32/next -5610 _Primitive-inc-esi: -5611 # var/esi <- increment => 46/increment-esi -5612 "increment"/imm32/name -5613 0/imm32/no-inouts -5614 Single-int-var-in-esi/imm32/outputs -5615 "46/increment-esi"/imm32/subx-name -5616 0/imm32/no-rm32 -5617 0/imm32/no-r32 -5618 0/imm32/no-imm32 -5619 0/imm32/no-disp32 -5620 0/imm32/output-is-write-only -5621 _Primitive-inc-edi/imm32/next -5622 _Primitive-inc-edi: -5623 # var/edi <- increment => 47/increment-edi -5624 "increment"/imm32/name -5625 0/imm32/no-inouts -5626 Single-int-var-in-edi/imm32/outputs -5627 "47/increment-edi"/imm32/subx-name -5628 0/imm32/no-rm32 -5629 0/imm32/no-r32 -5630 0/imm32/no-imm32 -5631 0/imm32/no-disp32 -5632 0/imm32/output-is-write-only -5633 _Primitive-dec-eax/imm32/next -5634 _Primitive-dec-eax: -5635 # var/eax <- decrement => 48/decrement-eax -5636 "decrement"/imm32/name -5637 0/imm32/no-inouts -5638 Single-int-var-in-eax/imm32/outputs -5639 "48/decrement-eax"/imm32/subx-name -5640 0/imm32/no-rm32 -5641 0/imm32/no-r32 -5642 0/imm32/no-imm32 -5643 0/imm32/no-disp32 -5644 0/imm32/output-is-write-only -5645 _Primitive-dec-ecx/imm32/next -5646 _Primitive-dec-ecx: -5647 # var/ecx <- decrement => 49/decrement-ecx -5648 "decrement"/imm32/name -5649 0/imm32/no-inouts -5650 Single-int-var-in-ecx/imm32/outputs -5651 "49/decrement-ecx"/imm32/subx-name -5652 0/imm32/no-rm32 -5653 0/imm32/no-r32 -5654 0/imm32/no-imm32 -5655 0/imm32/no-disp32 -5656 0/imm32/output-is-write-only -5657 _Primitive-dec-edx/imm32/next -5658 _Primitive-dec-edx: -5659 # var/edx <- decrement => 4a/decrement-edx -5660 "decrement"/imm32/name -5661 0/imm32/no-inouts -5662 Single-int-var-in-edx/imm32/outputs -5663 "4a/decrement-edx"/imm32/subx-name -5664 0/imm32/no-rm32 -5665 0/imm32/no-r32 -5666 0/imm32/no-imm32 -5667 0/imm32/no-disp32 -5668 0/imm32/output-is-write-only -5669 _Primitive-dec-ebx/imm32/next -5670 _Primitive-dec-ebx: -5671 # var/ebx <- decrement => 4b/decrement-ebx -5672 "decrement"/imm32/name -5673 0/imm32/no-inouts -5674 Single-int-var-in-ebx/imm32/outputs -5675 "4b/decrement-ebx"/imm32/subx-name -5676 0/imm32/no-rm32 -5677 0/imm32/no-r32 -5678 0/imm32/no-imm32 -5679 0/imm32/no-disp32 -5680 0/imm32/output-is-write-only -5681 _Primitive-dec-esi/imm32/next -5682 _Primitive-dec-esi: -5683 # var/esi <- decrement => 4e/decrement-esi -5684 "decrement"/imm32/name -5685 0/imm32/no-inouts -5686 Single-int-var-in-esi/imm32/outputs -5687 "4e/decrement-esi"/imm32/subx-name -5688 0/imm32/no-rm32 -5689 0/imm32/no-r32 -5690 0/imm32/no-imm32 -5691 0/imm32/no-disp32 -5692 0/imm32/output-is-write-only -5693 _Primitive-dec-edi/imm32/next -5694 _Primitive-dec-edi: -5695 # var/edi <- decrement => 4f/decrement-edi -5696 "decrement"/imm32/name -5697 0/imm32/no-inouts -5698 Single-int-var-in-edi/imm32/outputs -5699 "4f/decrement-edi"/imm32/subx-name -5700 0/imm32/no-rm32 -5701 0/imm32/no-r32 -5702 0/imm32/no-imm32 -5703 0/imm32/no-disp32 -5704 0/imm32/output-is-write-only -5705 _Primitive-inc-mem/imm32/next -5706 _Primitive-inc-mem: -5707 # increment var => ff 0/subop/increment *(ebp+__) -5708 "increment"/imm32/name -5709 Single-int-var-in-mem/imm32/inouts -5710 0/imm32/no-outputs -5711 "ff 0/subop/increment"/imm32/subx-name -5712 1/imm32/rm32-is-first-inout -5713 0/imm32/no-r32 -5714 0/imm32/no-imm32 -5715 0/imm32/no-disp32 -5716 0/imm32/output-is-write-only -5717 _Primitive-inc-reg/imm32/next -5718 _Primitive-inc-reg: -5719 # var/reg <- increment => ff 0/subop/increment %__ -5720 "increment"/imm32/name -5721 0/imm32/no-inouts -5722 Single-int-var-in-some-register/imm32/outputs -5723 "ff 0/subop/increment"/imm32/subx-name -5724 3/imm32/rm32-is-first-output -5725 0/imm32/no-r32 -5726 0/imm32/no-imm32 -5727 0/imm32/no-disp32 -5728 0/imm32/output-is-write-only -5729 _Primitive-dec-mem/imm32/next -5730 _Primitive-dec-mem: -5731 # decrement var => ff 1/subop/decrement *(ebp+__) -5732 "decrement"/imm32/name -5733 Single-int-var-in-mem/imm32/inouts -5734 0/imm32/no-outputs -5735 "ff 1/subop/decrement"/imm32/subx-name -5736 1/imm32/rm32-is-first-inout -5737 0/imm32/no-r32 -5738 0/imm32/no-imm32 -5739 0/imm32/no-disp32 -5740 0/imm32/output-is-write-only -5741 _Primitive-dec-reg/imm32/next -5742 _Primitive-dec-reg: -5743 # var/reg <- decrement => ff 1/subop/decrement %__ -5744 "decrement"/imm32/name -5745 0/imm32/no-inouts -5746 Single-int-var-in-some-register/imm32/outputs -5747 "ff 1/subop/decrement"/imm32/subx-name -5748 3/imm32/rm32-is-first-output -5749 0/imm32/no-r32 -5750 0/imm32/no-imm32 -5751 0/imm32/no-disp32 -5752 0/imm32/output-is-write-only -5753 _Primitive-add-to-eax/imm32/next -5754 # - add -5755 _Primitive-add-to-eax: -5756 # var/eax <- add lit => 05/add-to-eax lit/imm32 -5757 "add"/imm32/name -5758 Single-lit-var/imm32/inouts -5759 Single-int-var-in-eax/imm32/outputs -5760 "05/add-to-eax"/imm32/subx-name -5761 0/imm32/no-rm32 -5762 0/imm32/no-r32 -5763 1/imm32/imm32-is-first-inout -5764 0/imm32/no-disp32 -5765 0/imm32/output-is-write-only -5766 _Primitive-add-reg-to-reg/imm32/next -5767 _Primitive-add-reg-to-reg: -5768 # var1/reg <- add var2/reg => 01/add-to var1/rm32 var2/r32 -5769 "add"/imm32/name -5770 Single-int-var-in-some-register/imm32/inouts -5771 Single-int-var-in-some-register/imm32/outputs -5772 "01/add-to"/imm32/subx-name -5773 3/imm32/rm32-is-first-output -5774 1/imm32/r32-is-first-inout -5775 0/imm32/no-imm32 -5776 0/imm32/no-disp32 -5777 0/imm32/output-is-write-only -5778 _Primitive-add-reg-to-mem/imm32/next -5779 _Primitive-add-reg-to-mem: -5780 # add-to var1 var2/reg => 01/add-to var1 var2/r32 -5781 "add-to"/imm32/name -5782 Two-args-int-stack-int-reg/imm32/inouts -5783 0/imm32/outputs -5784 "01/add-to"/imm32/subx-name -5785 1/imm32/rm32-is-first-inout -5786 2/imm32/r32-is-second-inout -5787 0/imm32/no-imm32 -5788 0/imm32/no-disp32 -5789 0/imm32/output-is-write-only -5790 _Primitive-add-mem-to-reg/imm32/next -5791 _Primitive-add-mem-to-reg: -5792 # var1/reg <- add var2 => 03/add var2/rm32 var1/r32 -5793 "add"/imm32/name -5794 Single-int-var-in-mem/imm32/inouts -5795 Single-int-var-in-some-register/imm32/outputs -5796 "03/add"/imm32/subx-name -5797 1/imm32/rm32-is-first-inout -5798 3/imm32/r32-is-first-output -5799 0/imm32/no-imm32 -5800 0/imm32/no-disp32 -5801 0/imm32/output-is-write-only -5802 _Primitive-add-lit-to-reg/imm32/next -5803 _Primitive-add-lit-to-reg: -5804 # var1/reg <- add lit => 81 0/subop/add var1/rm32 lit/imm32 -5805 "add"/imm32/name -5806 Single-lit-var/imm32/inouts -5807 Single-int-var-in-some-register/imm32/outputs -5808 "81 0/subop/add"/imm32/subx-name -5809 3/imm32/rm32-is-first-output -5810 0/imm32/no-r32 -5811 1/imm32/imm32-is-first-inout -5812 0/imm32/no-disp32 -5813 0/imm32/output-is-write-only -5814 _Primitive-add-lit-to-mem/imm32/next -5815 _Primitive-add-lit-to-mem: -5816 # add-to var1, lit => 81 0/subop/add var1/rm32 lit/imm32 -5817 "add-to"/imm32/name -5818 Int-var-and-literal/imm32/inouts -5819 0/imm32/outputs -5820 "81 0/subop/add"/imm32/subx-name -5821 1/imm32/rm32-is-first-inout -5822 0/imm32/no-r32 -5823 2/imm32/imm32-is-second-inout -5824 0/imm32/no-disp32 -5825 0/imm32/output-is-write-only -5826 _Primitive-subtract-from-eax/imm32/next -5827 # - subtract -5828 _Primitive-subtract-from-eax: -5829 # var/eax <- subtract lit => 2d/subtract-from-eax lit/imm32 -5830 "subtract"/imm32/name -5831 Single-lit-var/imm32/inouts -5832 Single-int-var-in-eax/imm32/outputs -5833 "2d/subtract-from-eax"/imm32/subx-name -5834 0/imm32/no-rm32 -5835 0/imm32/no-r32 -5836 1/imm32/imm32-is-first-inout -5837 0/imm32/no-disp32 -5838 0/imm32/output-is-write-only -5839 _Primitive-subtract-reg-from-reg/imm32/next -5840 _Primitive-subtract-reg-from-reg: -5841 # var1/reg <- subtract var2/reg => 29/subtract-from var1/rm32 var2/r32 -5842 "subtract"/imm32/name -5843 Single-int-var-in-some-register/imm32/inouts -5844 Single-int-var-in-some-register/imm32/outputs -5845 "29/subtract-from"/imm32/subx-name -5846 3/imm32/rm32-is-first-output -5847 1/imm32/r32-is-first-inout -5848 0/imm32/no-imm32 -5849 0/imm32/no-disp32 -5850 0/imm32/output-is-write-only -5851 _Primitive-subtract-reg-from-mem/imm32/next -5852 _Primitive-subtract-reg-from-mem: -5853 # subtract-from var1 var2/reg => 29/subtract-from var1 var2/r32 -5854 "subtract-from"/imm32/name -5855 Two-args-int-stack-int-reg/imm32/inouts -5856 0/imm32/outputs -5857 "29/subtract-from"/imm32/subx-name -5858 1/imm32/rm32-is-first-inout -5859 2/imm32/r32-is-second-inout -5860 0/imm32/no-imm32 -5861 0/imm32/no-disp32 -5862 0/imm32/output-is-write-only -5863 _Primitive-subtract-mem-from-reg/imm32/next -5864 _Primitive-subtract-mem-from-reg: -5865 # var1/reg <- subtract var2 => 2b/subtract var2/rm32 var1/r32 -5866 "subtract"/imm32/name -5867 Single-int-var-in-mem/imm32/inouts -5868 Single-int-var-in-some-register/imm32/outputs -5869 "2b/subtract"/imm32/subx-name -5870 1/imm32/rm32-is-first-inout -5871 3/imm32/r32-is-first-output -5872 0/imm32/no-imm32 -5873 0/imm32/no-disp32 -5874 0/imm32/output-is-write-only -5875 _Primitive-subtract-lit-from-reg/imm32/next -5876 _Primitive-subtract-lit-from-reg: -5877 # var1/reg <- subtract lit => 81 5/subop/subtract var1/rm32 lit/imm32 -5878 "subtract"/imm32/name -5879 Single-lit-var/imm32/inouts -5880 Single-int-var-in-some-register/imm32/outputs -5881 "81 5/subop/subtract"/imm32/subx-name -5882 3/imm32/rm32-is-first-output -5883 0/imm32/no-r32 -5884 1/imm32/imm32-is-first-inout -5885 0/imm32/no-disp32 -5886 0/imm32/output-is-write-only -5887 _Primitive-subtract-lit-from-mem/imm32/next -5888 _Primitive-subtract-lit-from-mem: -5889 # subtract-from var1, lit => 81 5/subop/subtract var1/rm32 lit/imm32 -5890 "subtract-from"/imm32/name -5891 Int-var-and-literal/imm32/inouts -5892 0/imm32/outputs -5893 "81 5/subop/subtract"/imm32/subx-name -5894 1/imm32/rm32-is-first-inout -5895 0/imm32/no-r32 -5896 2/imm32/imm32-is-first-inout -5897 0/imm32/no-disp32 -5898 0/imm32/output-is-write-only -5899 _Primitive-and-with-eax/imm32/next -5900 # - and -5901 _Primitive-and-with-eax: -5902 # var/eax <- and lit => 25/and-with-eax lit/imm32 -5903 "and"/imm32/name -5904 Single-lit-var/imm32/inouts -5905 Single-int-var-in-eax/imm32/outputs -5906 "25/and-with-eax"/imm32/subx-name -5907 0/imm32/no-rm32 -5908 0/imm32/no-r32 -5909 1/imm32/imm32-is-first-inout -5910 0/imm32/no-disp32 -5911 0/imm32/output-is-write-only -5912 _Primitive-and-reg-with-reg/imm32/next -5913 _Primitive-and-reg-with-reg: -5914 # var1/reg <- and var2/reg => 21/and-with var1/rm32 var2/r32 -5915 "and"/imm32/name -5916 Single-int-var-in-some-register/imm32/inouts -5917 Single-int-var-in-some-register/imm32/outputs -5918 "21/and-with"/imm32/subx-name -5919 3/imm32/rm32-is-first-output -5920 1/imm32/r32-is-first-inout -5921 0/imm32/no-imm32 -5922 0/imm32/no-disp32 -5923 0/imm32/output-is-write-only -5924 _Primitive-and-reg-with-mem/imm32/next -5925 _Primitive-and-reg-with-mem: -5926 # and-with var1 var2/reg => 21/and-with var1 var2/r32 -5927 "and-with"/imm32/name -5928 Two-args-int-stack-int-reg/imm32/inouts -5929 0/imm32/outputs -5930 "21/and-with"/imm32/subx-name -5931 1/imm32/rm32-is-first-inout -5932 2/imm32/r32-is-second-inout -5933 0/imm32/no-imm32 -5934 0/imm32/no-disp32 -5935 0/imm32/output-is-write-only -5936 _Primitive-and-mem-with-reg/imm32/next -5937 _Primitive-and-mem-with-reg: -5938 # var1/reg <- and var2 => 23/and var2/rm32 var1/r32 -5939 "and"/imm32/name -5940 Single-int-var-in-mem/imm32/inouts -5941 Single-int-var-in-some-register/imm32/outputs -5942 "23/and"/imm32/subx-name -5943 1/imm32/rm32-is-first-inout -5944 3/imm32/r32-is-first-output -5945 0/imm32/no-imm32 -5946 0/imm32/no-disp32 -5947 0/imm32/output-is-write-only -5948 _Primitive-and-lit-with-reg/imm32/next -5949 _Primitive-and-lit-with-reg: -5950 # var1/reg <- and lit => 81 4/subop/and var1/rm32 lit/imm32 -5951 "and"/imm32/name -5952 Single-lit-var/imm32/inouts -5953 Single-int-var-in-some-register/imm32/outputs -5954 "81 4/subop/and"/imm32/subx-name -5955 3/imm32/rm32-is-first-output -5956 0/imm32/no-r32 -5957 1/imm32/imm32-is-first-inout -5958 0/imm32/no-disp32 -5959 0/imm32/output-is-write-only -5960 _Primitive-and-lit-with-mem/imm32/next -5961 _Primitive-and-lit-with-mem: -5962 # and-with var1, lit => 81 4/subop/and var1/rm32 lit/imm32 -5963 "and-with"/imm32/name -5964 Int-var-and-literal/imm32/inouts -5965 0/imm32/outputs -5966 "81 4/subop/and"/imm32/subx-name -5967 1/imm32/rm32-is-first-inout -5968 0/imm32/no-r32 -5969 2/imm32/imm32-is-first-inout -5970 0/imm32/no-disp32 -5971 0/imm32/output-is-write-only -5972 _Primitive-or-with-eax/imm32/next -5973 # - or -5974 _Primitive-or-with-eax: -5975 # var/eax <- or lit => 0d/or-with-eax lit/imm32 -5976 "or"/imm32/name -5977 Single-lit-var/imm32/inouts -5978 Single-int-var-in-eax/imm32/outputs -5979 "0d/or-with-eax"/imm32/subx-name -5980 0/imm32/no-rm32 -5981 0/imm32/no-r32 -5982 1/imm32/imm32-is-first-inout -5983 0/imm32/no-disp32 -5984 0/imm32/output-is-write-only -5985 _Primitive-or-reg-with-reg/imm32/next -5986 _Primitive-or-reg-with-reg: -5987 # var1/reg <- or var2/reg => 09/or-with var1/rm32 var2/r32 -5988 "or"/imm32/name -5989 Single-int-var-in-some-register/imm32/inouts -5990 Single-int-var-in-some-register/imm32/outputs -5991 "09/or-with"/imm32/subx-name -5992 3/imm32/rm32-is-first-output -5993 1/imm32/r32-is-first-inout -5994 0/imm32/no-imm32 -5995 0/imm32/no-disp32 -5996 0/imm32/output-is-write-only -5997 _Primitive-or-reg-with-mem/imm32/next -5998 _Primitive-or-reg-with-mem: -5999 # or-with var1 var2/reg => 09/or-with var1 var2/r32 -6000 "or-with"/imm32/name -6001 Two-args-int-stack-int-reg/imm32/inouts -6002 0/imm32/outputs -6003 "09/or-with"/imm32/subx-name -6004 1/imm32/rm32-is-first-inout -6005 2/imm32/r32-is-second-inout -6006 0/imm32/no-imm32 -6007 0/imm32/no-disp32 -6008 0/imm32/output-is-write-only -6009 _Primitive-or-mem-with-reg/imm32/next -6010 _Primitive-or-mem-with-reg: -6011 # var1/reg <- or var2 => 0b/or var2/rm32 var1/r32 -6012 "or"/imm32/name -6013 Single-int-var-in-mem/imm32/inouts -6014 Single-int-var-in-some-register/imm32/outputs -6015 "0b/or"/imm32/subx-name -6016 1/imm32/rm32-is-first-inout -6017 3/imm32/r32-is-first-output -6018 0/imm32/no-imm32 -6019 0/imm32/no-disp32 -6020 0/imm32/output-is-write-only -6021 _Primitive-or-lit-with-reg/imm32/next -6022 _Primitive-or-lit-with-reg: -6023 # var1/reg <- or lit => 81 1/subop/or var1/rm32 lit/imm32 -6024 "or"/imm32/name -6025 Single-lit-var/imm32/inouts -6026 Single-int-var-in-some-register/imm32/outputs -6027 "81 1/subop/or"/imm32/subx-name -6028 3/imm32/rm32-is-first-output -6029 0/imm32/no-r32 -6030 1/imm32/imm32-is-first-inout -6031 0/imm32/no-disp32 -6032 0/imm32/output-is-write-only -6033 _Primitive-or-lit-with-mem/imm32/next -6034 _Primitive-or-lit-with-mem: -6035 # or-with var1, lit => 81 1/subop/or var1/rm32 lit/imm32 -6036 "or-with"/imm32/name -6037 Int-var-and-literal/imm32/inouts -6038 0/imm32/outputs -6039 "81 1/subop/or"/imm32/subx-name -6040 1/imm32/rm32-is-first-inout -6041 0/imm32/no-r32 -6042 2/imm32/imm32-is-second-inout -6043 0/imm32/no-disp32 -6044 0/imm32/output-is-write-only -6045 _Primitive-xor-with-eax/imm32/next -6046 # - xor -6047 _Primitive-xor-with-eax: -6048 # var/eax <- xor lit => 35/xor-with-eax lit/imm32 -6049 "xor"/imm32/name -6050 Single-lit-var/imm32/inouts -6051 Single-int-var-in-eax/imm32/outputs -6052 "35/xor-with-eax"/imm32/subx-name -6053 0/imm32/no-rm32 -6054 0/imm32/no-r32 -6055 1/imm32/imm32-is-first-inout -6056 0/imm32/no-disp32 -6057 0/imm32/output-is-write-only -6058 _Primitive-xor-reg-with-reg/imm32/next -6059 _Primitive-xor-reg-with-reg: -6060 # var1/reg <- xor var2/reg => 31/xor-with var1/rm32 var2/r32 -6061 "xor"/imm32/name -6062 Single-int-var-in-some-register/imm32/inouts -6063 Single-int-var-in-some-register/imm32/outputs -6064 "31/xor-with"/imm32/subx-name -6065 3/imm32/rm32-is-first-output -6066 1/imm32/r32-is-first-inout -6067 0/imm32/no-imm32 -6068 0/imm32/no-disp32 -6069 0/imm32/output-is-write-only -6070 _Primitive-xor-reg-with-mem/imm32/next -6071 _Primitive-xor-reg-with-mem: -6072 # xor-with var1 var2/reg => 31/xor-with var1 var2/r32 -6073 "xor-with"/imm32/name -6074 Two-args-int-stack-int-reg/imm32/inouts -6075 0/imm32/outputs -6076 "31/xor-with"/imm32/subx-name -6077 1/imm32/rm32-is-first-inout -6078 2/imm32/r32-is-second-inout -6079 0/imm32/no-imm32 -6080 0/imm32/no-disp32 -6081 0/imm32/output-is-write-only -6082 _Primitive-xor-mem-with-reg/imm32/next -6083 _Primitive-xor-mem-with-reg: -6084 # var1/reg <- xor var2 => 33/xor var2/rm32 var1/r32 -6085 "xor"/imm32/name -6086 Single-int-var-in-mem/imm32/inouts -6087 Single-int-var-in-some-register/imm32/outputs -6088 "33/xor"/imm32/subx-name -6089 1/imm32/rm32-is-first-inout -6090 3/imm32/r32-is-first-output -6091 0/imm32/no-imm32 -6092 0/imm32/no-disp32 -6093 0/imm32/output-is-write-only -6094 _Primitive-xor-lit-with-reg/imm32/next -6095 _Primitive-xor-lit-with-reg: -6096 # var1/reg <- xor lit => 81 6/subop/xor var1/rm32 lit/imm32 -6097 "xor"/imm32/name -6098 Single-lit-var/imm32/inouts -6099 Single-int-var-in-some-register/imm32/outputs -6100 "81 6/subop/xor"/imm32/subx-name -6101 3/imm32/rm32-is-first-output -6102 0/imm32/no-r32 -6103 1/imm32/imm32-is-first-inout -6104 0/imm32/no-disp32 -6105 0/imm32/output-is-write-only -6106 _Primitive-xor-lit-with-mem/imm32/next -6107 _Primitive-xor-lit-with-mem: -6108 # xor-with var1, lit => 81 6/subop/xor var1/rm32 lit/imm32 -6109 "xor-with"/imm32/name -6110 Int-var-and-literal/imm32/inouts -6111 0/imm32/outputs -6112 "81 6/subop/xor"/imm32/subx-name -6113 1/imm32/rm32-is-first-inout -6114 0/imm32/no-r32 -6115 2/imm32/imm32-is-first-inout -6116 0/imm32/no-disp32 -6117 0/imm32/output-is-write-only -6118 _Primitive-copy-to-eax/imm32/next -6119 # - copy -6120 _Primitive-copy-to-eax: -6121 # var/eax <- copy lit => b8/copy-to-eax lit/imm32 -6122 "copy"/imm32/name -6123 Single-lit-var/imm32/inouts -6124 Single-int-var-in-eax/imm32/outputs -6125 "b8/copy-to-eax"/imm32/subx-name -6126 0/imm32/no-rm32 -6127 0/imm32/no-r32 -6128 1/imm32/imm32-is-first-inout -6129 0/imm32/no-disp32 -6130 1/imm32/output-is-write-only -6131 _Primitive-copy-to-ecx/imm32/next -6132 _Primitive-copy-to-ecx: -6133 # var/ecx <- copy lit => b9/copy-to-ecx lit/imm32 -6134 "copy"/imm32/name -6135 Single-lit-var/imm32/inouts -6136 Single-int-var-in-ecx/imm32/outputs -6137 "b9/copy-to-ecx"/imm32/subx-name -6138 0/imm32/no-rm32 -6139 0/imm32/no-r32 -6140 1/imm32/imm32-is-first-inout -6141 0/imm32/no-disp32 -6142 1/imm32/output-is-write-only -6143 _Primitive-copy-to-edx/imm32/next -6144 _Primitive-copy-to-edx: -6145 # var/edx <- copy lit => ba/copy-to-edx lit/imm32 -6146 "copy"/imm32/name -6147 Single-lit-var/imm32/inouts -6148 Single-int-var-in-edx/imm32/outputs -6149 "ba/copy-to-edx"/imm32/subx-name -6150 0/imm32/no-rm32 -6151 0/imm32/no-r32 -6152 1/imm32/imm32-is-first-inout -6153 0/imm32/no-disp32 -6154 1/imm32/output-is-write-only -6155 _Primitive-copy-to-ebx/imm32/next -6156 _Primitive-copy-to-ebx: -6157 # var/ebx <- copy lit => bb/copy-to-ebx lit/imm32 -6158 "copy"/imm32/name -6159 Single-lit-var/imm32/inouts -6160 Single-int-var-in-ebx/imm32/outputs -6161 "bb/copy-to-ebx"/imm32/subx-name -6162 0/imm32/no-rm32 -6163 0/imm32/no-r32 -6164 1/imm32/imm32-is-first-inout -6165 0/imm32/no-disp32 -6166 1/imm32/output-is-write-only -6167 _Primitive-copy-to-esi/imm32/next -6168 _Primitive-copy-to-esi: -6169 # var/esi <- copy lit => be/copy-to-esi lit/imm32 -6170 "copy"/imm32/name -6171 Single-lit-var/imm32/inouts -6172 Single-int-var-in-esi/imm32/outputs -6173 "be/copy-to-esi"/imm32/subx-name -6174 0/imm32/no-rm32 -6175 0/imm32/no-r32 -6176 1/imm32/imm32-is-first-inout -6177 0/imm32/no-disp32 -6178 1/imm32/output-is-write-only -6179 _Primitive-copy-to-edi/imm32/next -6180 _Primitive-copy-to-edi: -6181 # var/edi <- copy lit => bf/copy-to-edi lit/imm32 -6182 "copy"/imm32/name -6183 Single-lit-var/imm32/inouts -6184 Single-int-var-in-edi/imm32/outputs -6185 "bf/copy-to-edi"/imm32/subx-name -6186 0/imm32/no-rm32 -6187 0/imm32/no-r32 -6188 1/imm32/imm32-is-first-inout -6189 0/imm32/no-disp32 -6190 1/imm32/output-is-write-only -6191 _Primitive-copy-reg-to-reg/imm32/next -6192 _Primitive-copy-reg-to-reg: -6193 # var1/reg <- copy var2/reg => 89/copy-to var1/rm32 var2/r32 -6194 "copy"/imm32/name -6195 Single-int-var-in-some-register/imm32/inouts -6196 Single-int-var-in-some-register/imm32/outputs -6197 "89/copy-to"/imm32/subx-name -6198 3/imm32/rm32-is-first-output -6199 1/imm32/r32-is-first-inout -6200 0/imm32/no-imm32 -6201 0/imm32/no-disp32 -6202 1/imm32/output-is-write-only -6203 _Primitive-copy-reg-to-mem/imm32/next -6204 _Primitive-copy-reg-to-mem: -6205 # copy-to var1 var2/reg => 89/copy-to var1 var2/r32 -6206 "copy-to"/imm32/name -6207 Two-args-int-stack-int-reg/imm32/inouts -6208 0/imm32/outputs -6209 "89/copy-to"/imm32/subx-name -6210 1/imm32/rm32-is-first-inout -6211 2/imm32/r32-is-second-inout -6212 0/imm32/no-imm32 -6213 0/imm32/no-disp32 -6214 1/imm32/output-is-write-only -6215 _Primitive-copy-mem-to-reg/imm32/next -6216 _Primitive-copy-mem-to-reg: -6217 # var1/reg <- copy var2 => 8b/copy-from var2/rm32 var1/r32 -6218 "copy"/imm32/name -6219 Single-int-var-in-mem/imm32/inouts -6220 Single-int-var-in-some-register/imm32/outputs -6221 "8b/copy-from"/imm32/subx-name -6222 1/imm32/rm32-is-first-inout -6223 3/imm32/r32-is-first-output -6224 0/imm32/no-imm32 -6225 0/imm32/no-disp32 -6226 1/imm32/output-is-write-only -6227 _Primitive-copy-lit-to-reg/imm32/next -6228 _Primitive-copy-lit-to-reg: -6229 # var1/reg <- copy lit => c7 0/subop/copy var1/rm32 lit/imm32 -6230 "copy"/imm32/name -6231 Single-lit-var/imm32/inouts -6232 Single-int-var-in-some-register/imm32/outputs -6233 "c7 0/subop/copy"/imm32/subx-name -6234 3/imm32/rm32-is-first-output -6235 0/imm32/no-r32 -6236 1/imm32/imm32-is-first-inout -6237 0/imm32/no-disp32 -6238 1/imm32/output-is-write-only -6239 _Primitive-copy-lit-to-mem/imm32/next -6240 _Primitive-copy-lit-to-mem: -6241 # copy-to var1, lit => c7 0/subop/copy var1/rm32 lit/imm32 -6242 "copy-to"/imm32/name -6243 Int-var-and-literal/imm32/inouts -6244 0/imm32/outputs -6245 "c7 0/subop/copy"/imm32/subx-name -6246 1/imm32/rm32-is-first-inout -6247 0/imm32/no-r32 -6248 2/imm32/imm32-is-first-inout -6249 0/imm32/no-disp32 -6250 1/imm32/output-is-write-only -6251 _Primitive-compare-mem-with-reg/imm32/next -6252 # - compare -6253 _Primitive-compare-mem-with-reg: -6254 # compare var1 var2/reg => 39/compare-> var1/rm32 var2/r32 -6255 "compare"/imm32/name -6256 Two-args-int-stack-int-reg/imm32/inouts -6257 0/imm32/outputs -6258 "39/compare->"/imm32/subx-name -6259 1/imm32/rm32-is-first-inout -6260 2/imm32/r32-is-second-inout -6261 0/imm32/no-imm32 -6262 0/imm32/no-disp32 -6263 0/imm32/output-is-write-only -6264 _Primitive-compare-reg-with-mem/imm32/next -6265 _Primitive-compare-reg-with-mem: -6266 # compare var1/reg var2 => 3b/compare<- var2/rm32 var1/r32 -6267 "compare"/imm32/name -6268 Two-args-int-reg-int-stack/imm32/inouts -6269 0/imm32/outputs -6270 "3b/compare<-"/imm32/subx-name -6271 2/imm32/rm32-is-second-inout -6272 1/imm32/r32-is-first-inout -6273 0/imm32/no-imm32 -6274 0/imm32/no-disp32 -6275 0/imm32/output-is-write-only -6276 _Primitive-compare-eax-with-literal/imm32/next -6277 _Primitive-compare-eax-with-literal: -6278 # compare var1/eax n => 3d/compare-eax-with n/imm32 -6279 "compare"/imm32/name -6280 Two-args-int-eax-int-literal/imm32/inouts -6281 0/imm32/outputs -6282 "3d/compare-eax-with"/imm32/subx-name -6283 0/imm32/no-rm32 -6284 0/imm32/no-r32 -6285 2/imm32/imm32-is-second-inout -6286 0/imm32/no-disp32 -6287 0/imm32/output-is-write-only -6288 _Primitive-compare-reg-with-literal/imm32/next -6289 _Primitive-compare-reg-with-literal: -6290 # compare var1/reg n => 81 7/subop/compare %reg n/imm32 -6291 "compare"/imm32/name -6292 Int-var-in-register-and-literal/imm32/inouts -6293 0/imm32/outputs -6294 "81 7/subop/compare"/imm32/subx-name -6295 1/imm32/rm32-is-first-inout -6296 0/imm32/no-r32 -6297 2/imm32/imm32-is-second-inout -6298 0/imm32/no-disp32 -6299 0/imm32/output-is-write-only -6300 _Primitive-compare-mem-with-literal/imm32/next -6301 _Primitive-compare-mem-with-literal: -6302 # compare var1 n => 81 7/subop/compare *(ebp+___) n/imm32 -6303 "compare"/imm32/name -6304 Int-var-and-literal/imm32/inouts -6305 0/imm32/outputs -6306 "81 7/subop/compare"/imm32/subx-name -6307 1/imm32/rm32-is-first-inout -6308 0/imm32/no-r32 -6309 2/imm32/imm32-is-second-inout -6310 0/imm32/no-disp32 -6311 0/imm32/output-is-write-only -6312 _Primitive-multiply-reg-by-mem/imm32/next -6313 # - multiply -6314 _Primitive-multiply-reg-by-mem: -6315 # var1/reg <- multiply var2 => 0f af/multiply var2/rm32 var1/r32 -6316 "multiply"/imm32/name -6317 Single-int-var-in-mem/imm32/inouts -6318 Single-int-var-in-some-register/imm32/outputs -6319 "0f af/multiply"/imm32/subx-name -6320 1/imm32/rm32-is-first-inout -6321 3/imm32/r32-is-first-output -6322 0/imm32/no-imm32 -6323 0/imm32/no-disp32 -6324 0/imm32/output-is-write-only -6325 _Primitive-break-if-addr</imm32/next -6326 # - branches -6327 _Primitive-break-if-addr<: -6328 "break-if-addr<"/imm32/name -6329 0/imm32/inouts -6330 0/imm32/outputs -6331 "0f 82/jump-if-addr< break/disp32"/imm32/subx-name -6332 0/imm32/no-rm32 -6333 0/imm32/no-r32 -6334 0/imm32/no-imm32 -6335 0/imm32/no-disp32 -6336 0/imm32/no-output -6337 _Primitive-break-if-addr>=/imm32/next -6338 _Primitive-break-if-addr>=: -6339 "break-if-addr>="/imm32/name -6340 0/imm32/inouts -6341 0/imm32/outputs -6342 "0f 83/jump-if-addr>= break/disp32"/imm32/subx-name -6343 0/imm32/no-rm32 -6344 0/imm32/no-r32 -6345 0/imm32/no-imm32 -6346 0/imm32/no-disp32 -6347 0/imm32/no-output -6348 _Primitive-break-if-=/imm32/next -6349 _Primitive-break-if-=: -6350 "break-if-="/imm32/name -6351 0/imm32/inouts -6352 0/imm32/outputs -6353 "0f 84/jump-if-= break/disp32"/imm32/subx-name -6354 0/imm32/no-rm32 -6355 0/imm32/no-r32 -6356 0/imm32/no-imm32 -6357 0/imm32/no-disp32 -6358 0/imm32/no-output -6359 _Primitive-break-if-!=/imm32/next -6360 _Primitive-break-if-!=: -6361 "break-if-!="/imm32/name -6362 0/imm32/inouts -6363 0/imm32/outputs -6364 "0f 85/jump-if-!= break/disp32"/imm32/subx-name -6365 0/imm32/no-rm32 -6366 0/imm32/no-r32 -6367 0/imm32/no-imm32 -6368 0/imm32/no-disp32 -6369 0/imm32/no-output -6370 _Primitive-break-if-addr<=/imm32/next -6371 _Primitive-break-if-addr<=: -6372 "break-if-addr<="/imm32/name -6373 0/imm32/inouts -6374 0/imm32/outputs -6375 "0f 86/jump-if-addr<= break/disp32"/imm32/subx-name -6376 0/imm32/no-rm32 -6377 0/imm32/no-r32 -6378 0/imm32/no-imm32 -6379 0/imm32/no-disp32 -6380 0/imm32/no-output -6381 _Primitive-break-if-addr>/imm32/next -6382 _Primitive-break-if-addr>: -6383 "break-if-addr>"/imm32/name -6384 0/imm32/inouts -6385 0/imm32/outputs -6386 "0f 87/jump-if-addr> break/disp32"/imm32/subx-name -6387 0/imm32/no-rm32 -6388 0/imm32/no-r32 -6389 0/imm32/no-imm32 -6390 0/imm32/no-disp32 -6391 0/imm32/no-output -6392 _Primitive-break-if-</imm32/next -6393 _Primitive-break-if-<: -6394 "break-if-<"/imm32/name -6395 0/imm32/inouts -6396 0/imm32/outputs -6397 "0f 8c/jump-if-< break/disp32"/imm32/subx-name -6398 0/imm32/no-rm32 -6399 0/imm32/no-r32 -6400 0/imm32/no-imm32 -6401 0/imm32/no-disp32 -6402 0/imm32/no-output -6403 _Primitive-break-if->=/imm32/next -6404 _Primitive-break-if->=: -6405 "break-if->="/imm32/name +5397 5b/pop-to-ebx +5398 5a/pop-to-edx +5399 59/pop-to-ecx +5400 58/pop-to-eax +5401 # . epilogue +5402 89/<- %esp 5/r32/ebp +5403 5d/pop-to-ebp +5404 c3/return +5405 +5406 # clean up global state for 'vars' until some block depth +5407 clean-up-blocks: # vars: (addr stack (handle var)), until-block-depth: int +5408 # . prologue +5409 55/push-ebp +5410 89/<- %ebp 4/r32/esp +5411 # . save registers +5412 50/push-eax +5413 51/push-ecx +5414 56/push-esi +5415 # esi = vars +5416 8b/-> *(ebp+8) 6/r32/esi +5417 # ecx = until-block-depth +5418 8b/-> *(ebp+0xc) 1/r32/ecx +5419 { +5420 $clean-up-blocks:reclaim-loop: +5421 # if (vars->top <= 0) break +5422 81 7/subop/compare *esi 0/imm32 # Stack-top +5423 7e/jump-if-<= break/disp8 +5424 # var v/eax: (handle var) = top(vars) +5425 (top %esi) # => eax +5426 # if (v->block-depth < until-block-depth) break +5427 39/compare *(eax+8) 1/r32/ecx # Var-block-depth +5428 7c/jump-if-< break/disp8 +5429 # if v is on the stack, update Next-local-stack-offset +5430 81 7/subop/compare *(eax+0x10) 0/imm32 # Var-register +5431 { +5432 75/jump-if-!= break/disp8 +5433 $clean-up-blocks:reclaim-var-on-stack: +5434 (size-of %eax) # => eax +5435 01/add *Next-local-stack-offset 0/r32/eax +5436 } +5437 (pop %esi) +5438 e9/jump loop/disp32 +5439 } +5440 $clean-up-blocks:end: +5441 # . restore registers +5442 5e/pop-to-esi +5443 59/pop-to-ecx +5444 58/pop-to-eax +5445 # . epilogue +5446 89/<- %esp 5/r32/ebp +5447 5d/pop-to-ebp +5448 c3/return +5449 +5450 emit-subx-var-def: # out: (addr buffered-file), stmt: (handle statement) +5451 # . prologue +5452 55/push-ebp +5453 89/<- %ebp 4/r32/esp +5454 # . save registers +5455 50/push-eax +5456 51/push-ecx +5457 # eax = stmt +5458 8b/-> *(ebp+0xc) 0/r32/eax +5459 # var n/eax: int = size-of(stmt->var) +5460 (size-of *(eax+4)) # Vardef-var => eax +5461 # while n > 0 +5462 { +5463 3d/compare-eax-with 0/imm32 +5464 7e/jump-if-<= break/disp8 +5465 (emit-indent *(ebp+8) *Curr-block-depth) +5466 (write-buffered *(ebp+8) "68/push 0/imm32\n") +5467 # n -= 4 +5468 2d/subtract-from-eax 4/imm32 +5469 # +5470 eb/jump loop/disp8 +5471 } +5472 $emit-subx-var-def:end: +5473 # . restore registers +5474 59/pop-to-ecx +5475 58/pop-to-eax +5476 # . epilogue +5477 89/<- %esp 5/r32/ebp +5478 5d/pop-to-ebp +5479 c3/return +5480 +5481 emit-subx-statement: # out: (addr buffered-file), stmt: (handle statement), primitives: (handle primitive), functions: (handle function) +5482 # . prologue +5483 55/push-ebp +5484 89/<- %ebp 4/r32/esp +5485 # . save registers +5486 50/push-eax +5487 51/push-ecx +5488 # handle some special cases +5489 # ecx = stmt +5490 8b/-> *(ebp+0xc) 1/r32/ecx +5491 +-- 24 lines: # array length ------------------------------------------------------------------------------------------------------------------------------------------------------------ +5515 +-- 32 lines: # array index ------------------------------------------------------------------------------------------------------------------------------------------------------------- +5547 # if stmt matches a primitive, emit it +5548 { +5549 $emit-subx-statement:check-for-primitive: +5550 (find-matching-primitive *(ebp+0x10) *(ebp+0xc)) # primitives, stmt => curr/eax +5551 3d/compare-eax-and 0/imm32 +5552 74/jump-if-= break/disp8 +5553 $emit-subx-statement:primitive: +5554 (emit-subx-primitive *(ebp+8) *(ebp+0xc) %eax) # out, stmt, curr +5555 e9/jump $emit-subx-statement:end/disp32 +5556 } +5557 # else if stmt matches a function, emit a call to it +5558 { +5559 $emit-subx-statement:check-for-call: +5560 (find-matching-function *(ebp+0x14) *(ebp+0xc)) # functions, stmt => curr/eax +5561 3d/compare-eax-and 0/imm32 +5562 74/jump-if-= break/disp8 +5563 $emit-subx-statement:call: +5564 (emit-subx-call *(ebp+8) *(ebp+0xc) %eax) # out, stmt, curr +5565 e9/jump $emit-subx-statement:end/disp32 +5566 } +5567 # else assume it's a SubX function (TODO: how to type-check?!) +5568 (emit-hailmary-call *(ebp+8) *(ebp+0xc)) +5569 $emit-subx-statement:end: +5570 # . restore registers +5571 59/pop-to-ecx +5572 58/pop-to-eax +5573 # . epilogue +5574 89/<- %esp 5/r32/ebp +5575 5d/pop-to-ebp +5576 c3/return +5577 +5578 $emit-subx-statement:abort: +5579 # error("couldn't translate '" stmt "'\n") +5580 (write-buffered Stderr "couldn't translate an instruction with operation '") +5581 8b/-> *(ebp+0xc) 0/r32/eax +5582 (write-buffered Stderr *(eax+4)) # Stmt1-operation +5583 (write-buffered Stderr "'\n") +5584 (flush Stderr) +5585 # . syscall(exit, 1) +5586 bb/copy-to-ebx 1/imm32 +5587 b8/copy-to-eax 1/imm32/exit +5588 cd/syscall 0x80/imm8 +5589 # never gets here +5590 +5591 emit-subx-block: # out: (addr buffered-file), block: (handle block), vars: (addr stack (handle var)) +5592 # . prologue +5593 55/push-ebp +5594 89/<- %ebp 4/r32/esp +5595 # . save registers +5596 50/push-eax +5597 51/push-ecx +5598 56/push-esi +5599 # esi = block +5600 8b/-> *(ebp+0xc) 6/r32/esi +5601 # var stmts/eax: (handle list statement) = block->statements +5602 8b/-> *(esi+4) 0/r32/eax # Block-statements +5603 # +5604 { +5605 $emit-subx-block:check-empty: +5606 81 7/subop/compare %eax 0/imm32 +5607 0f 84/jump-if-= break/disp32 +5608 (emit-indent *(ebp+8) *Curr-block-depth) +5609 (write-buffered *(ebp+8) "{\n") +5610 # var v/ecx: (addr array byte) = block->var->name +5611 8b/-> *(esi+8) 1/r32/ecx # Block-var +5612 (write-buffered *(ebp+8) *ecx) # Var-name +5613 (write-buffered *(ebp+8) ":loop:\n") +5614 ff 0/subop/increment *Curr-block-depth +5615 (push *(ebp+0x10) %ecx) +5616 (emit-subx-stmt-list *(ebp+8) %eax *(ebp+0x10)) +5617 (pop *(ebp+0x10)) # => eax +5618 ff 1/subop/decrement *Curr-block-depth +5619 (emit-indent *(ebp+8) *Curr-block-depth) +5620 (write-buffered *(ebp+8) "}\n") +5621 (write-buffered *(ebp+8) *ecx) # Var-name +5622 (write-buffered *(ebp+8) ":break:\n") +5623 } +5624 $emit-subx-block:end: +5625 # . restore registers +5626 5e/pop-to-esi +5627 59/pop-to-ecx +5628 58/pop-to-eax +5629 # . epilogue +5630 89/<- %esp 5/r32/ebp +5631 5d/pop-to-ebp +5632 c3/return +5633 +5634 # Primitives supported +5635 # For each operation, put variants with hard-coded registers before flexible ones. +5636 == data +5637 Primitives: +5638 # - increment/decrement +5639 _Primitive-inc-eax: +5640 # var/eax <- increment => 40/increment-eax +5641 "increment"/imm32/name +5642 0/imm32/no-inouts +5643 Single-int-var-in-eax/imm32/outputs +5644 "40/increment-eax"/imm32/subx-name +5645 0/imm32/no-rm32 +5646 0/imm32/no-r32 +5647 0/imm32/no-imm32 +5648 0/imm32/no-disp32 +5649 0/imm32/output-is-write-only +5650 _Primitive-inc-ecx/imm32/next +5651 _Primitive-inc-ecx: +5652 # var/ecx <- increment => 41/increment-ecx +5653 "increment"/imm32/name +5654 0/imm32/no-inouts +5655 Single-int-var-in-ecx/imm32/outputs +5656 "41/increment-ecx"/imm32/subx-name +5657 0/imm32/no-rm32 +5658 0/imm32/no-r32 +5659 0/imm32/no-imm32 +5660 0/imm32/no-disp32 +5661 0/imm32/output-is-write-only +5662 _Primitive-inc-edx/imm32/next +5663 _Primitive-inc-edx: +5664 # var/edx <- increment => 42/increment-edx +5665 "increment"/imm32/name +5666 0/imm32/no-inouts +5667 Single-int-var-in-edx/imm32/outputs +5668 "42/increment-edx"/imm32/subx-name +5669 0/imm32/no-rm32 +5670 0/imm32/no-r32 +5671 0/imm32/no-imm32 +5672 0/imm32/no-disp32 +5673 0/imm32/output-is-write-only +5674 _Primitive-inc-ebx/imm32/next +5675 _Primitive-inc-ebx: +5676 # var/ebx <- increment => 43/increment-ebx +5677 "increment"/imm32/name +5678 0/imm32/no-inouts +5679 Single-int-var-in-ebx/imm32/outputs +5680 "43/increment-ebx"/imm32/subx-name +5681 0/imm32/no-rm32 +5682 0/imm32/no-r32 +5683 0/imm32/no-imm32 +5684 0/imm32/no-disp32 +5685 0/imm32/output-is-write-only +5686 _Primitive-inc-esi/imm32/next +5687 _Primitive-inc-esi: +5688 # var/esi <- increment => 46/increment-esi +5689 "increment"/imm32/name +5690 0/imm32/no-inouts +5691 Single-int-var-in-esi/imm32/outputs +5692 "46/increment-esi"/imm32/subx-name +5693 0/imm32/no-rm32 +5694 0/imm32/no-r32 +5695 0/imm32/no-imm32 +5696 0/imm32/no-disp32 +5697 0/imm32/output-is-write-only +5698 _Primitive-inc-edi/imm32/next +5699 _Primitive-inc-edi: +5700 # var/edi <- increment => 47/increment-edi +5701 "increment"/imm32/name +5702 0/imm32/no-inouts +5703 Single-int-var-in-edi/imm32/outputs +5704 "47/increment-edi"/imm32/subx-name +5705 0/imm32/no-rm32 +5706 0/imm32/no-r32 +5707 0/imm32/no-imm32 +5708 0/imm32/no-disp32 +5709 0/imm32/output-is-write-only +5710 _Primitive-dec-eax/imm32/next +5711 _Primitive-dec-eax: +5712 # var/eax <- decrement => 48/decrement-eax +5713 "decrement"/imm32/name +5714 0/imm32/no-inouts +5715 Single-int-var-in-eax/imm32/outputs +5716 "48/decrement-eax"/imm32/subx-name +5717 0/imm32/no-rm32 +5718 0/imm32/no-r32 +5719 0/imm32/no-imm32 +5720 0/imm32/no-disp32 +5721 0/imm32/output-is-write-only +5722 _Primitive-dec-ecx/imm32/next +5723 _Primitive-dec-ecx: +5724 # var/ecx <- decrement => 49/decrement-ecx +5725 "decrement"/imm32/name +5726 0/imm32/no-inouts +5727 Single-int-var-in-ecx/imm32/outputs +5728 "49/decrement-ecx"/imm32/subx-name +5729 0/imm32/no-rm32 +5730 0/imm32/no-r32 +5731 0/imm32/no-imm32 +5732 0/imm32/no-disp32 +5733 0/imm32/output-is-write-only +5734 _Primitive-dec-edx/imm32/next +5735 _Primitive-dec-edx: +5736 # var/edx <- decrement => 4a/decrement-edx +5737 "decrement"/imm32/name +5738 0/imm32/no-inouts +5739 Single-int-var-in-edx/imm32/outputs +5740 "4a/decrement-edx"/imm32/subx-name +5741 0/imm32/no-rm32 +5742 0/imm32/no-r32 +5743 0/imm32/no-imm32 +5744 0/imm32/no-disp32 +5745 0/imm32/output-is-write-only +5746 _Primitive-dec-ebx/imm32/next +5747 _Primitive-dec-ebx: +5748 # var/ebx <- decrement => 4b/decrement-ebx +5749 "decrement"/imm32/name +5750 0/imm32/no-inouts +5751 Single-int-var-in-ebx/imm32/outputs +5752 "4b/decrement-ebx"/imm32/subx-name +5753 0/imm32/no-rm32 +5754 0/imm32/no-r32 +5755 0/imm32/no-imm32 +5756 0/imm32/no-disp32 +5757 0/imm32/output-is-write-only +5758 _Primitive-dec-esi/imm32/next +5759 _Primitive-dec-esi: +5760 # var/esi <- decrement => 4e/decrement-esi +5761 "decrement"/imm32/name +5762 0/imm32/no-inouts +5763 Single-int-var-in-esi/imm32/outputs +5764 "4e/decrement-esi"/imm32/subx-name +5765 0/imm32/no-rm32 +5766 0/imm32/no-r32 +5767 0/imm32/no-imm32 +5768 0/imm32/no-disp32 +5769 0/imm32/output-is-write-only +5770 _Primitive-dec-edi/imm32/next +5771 _Primitive-dec-edi: +5772 # var/edi <- decrement => 4f/decrement-edi +5773 "decrement"/imm32/name +5774 0/imm32/no-inouts +5775 Single-int-var-in-edi/imm32/outputs +5776 "4f/decrement-edi"/imm32/subx-name +5777 0/imm32/no-rm32 +5778 0/imm32/no-r32 +5779 0/imm32/no-imm32 +5780 0/imm32/no-disp32 +5781 0/imm32/output-is-write-only +5782 _Primitive-inc-mem/imm32/next +5783 _Primitive-inc-mem: +5784 # increment var => ff 0/subop/increment *(ebp+__) +5785 "increment"/imm32/name +5786 Single-int-var-in-mem/imm32/inouts +5787 0/imm32/no-outputs +5788 "ff 0/subop/increment"/imm32/subx-name +5789 1/imm32/rm32-is-first-inout +5790 0/imm32/no-r32 +5791 0/imm32/no-imm32 +5792 0/imm32/no-disp32 +5793 0/imm32/output-is-write-only +5794 _Primitive-inc-reg/imm32/next +5795 _Primitive-inc-reg: +5796 # var/reg <- increment => ff 0/subop/increment %__ +5797 "increment"/imm32/name +5798 0/imm32/no-inouts +5799 Single-int-var-in-some-register/imm32/outputs +5800 "ff 0/subop/increment"/imm32/subx-name +5801 3/imm32/rm32-is-first-output +5802 0/imm32/no-r32 +5803 0/imm32/no-imm32 +5804 0/imm32/no-disp32 +5805 0/imm32/output-is-write-only +5806 _Primitive-dec-mem/imm32/next +5807 _Primitive-dec-mem: +5808 # decrement var => ff 1/subop/decrement *(ebp+__) +5809 "decrement"/imm32/name +5810 Single-int-var-in-mem/imm32/inouts +5811 0/imm32/no-outputs +5812 "ff 1/subop/decrement"/imm32/subx-name +5813 1/imm32/rm32-is-first-inout +5814 0/imm32/no-r32 +5815 0/imm32/no-imm32 +5816 0/imm32/no-disp32 +5817 0/imm32/output-is-write-only +5818 _Primitive-dec-reg/imm32/next +5819 _Primitive-dec-reg: +5820 # var/reg <- decrement => ff 1/subop/decrement %__ +5821 "decrement"/imm32/name +5822 0/imm32/no-inouts +5823 Single-int-var-in-some-register/imm32/outputs +5824 "ff 1/subop/decrement"/imm32/subx-name +5825 3/imm32/rm32-is-first-output +5826 0/imm32/no-r32 +5827 0/imm32/no-imm32 +5828 0/imm32/no-disp32 +5829 0/imm32/output-is-write-only +5830 _Primitive-add-to-eax/imm32/next +5831 # - add +5832 _Primitive-add-to-eax: +5833 # var/eax <- add lit => 05/add-to-eax lit/imm32 +5834 "add"/imm32/name +5835 Single-lit-var/imm32/inouts +5836 Single-int-var-in-eax/imm32/outputs +5837 "05/add-to-eax"/imm32/subx-name +5838 0/imm32/no-rm32 +5839 0/imm32/no-r32 +5840 1/imm32/imm32-is-first-inout +5841 0/imm32/no-disp32 +5842 0/imm32/output-is-write-only +5843 _Primitive-add-reg-to-reg/imm32/next +5844 _Primitive-add-reg-to-reg: +5845 # var1/reg <- add var2/reg => 01/add-to var1/rm32 var2/r32 +5846 "add"/imm32/name +5847 Single-int-var-in-some-register/imm32/inouts +5848 Single-int-var-in-some-register/imm32/outputs +5849 "01/add-to"/imm32/subx-name +5850 3/imm32/rm32-is-first-output +5851 1/imm32/r32-is-first-inout +5852 0/imm32/no-imm32 +5853 0/imm32/no-disp32 +5854 0/imm32/output-is-write-only +5855 _Primitive-add-reg-to-mem/imm32/next +5856 _Primitive-add-reg-to-mem: +5857 # add-to var1 var2/reg => 01/add-to var1 var2/r32 +5858 "add-to"/imm32/name +5859 Two-args-int-stack-int-reg/imm32/inouts +5860 0/imm32/outputs +5861 "01/add-to"/imm32/subx-name +5862 1/imm32/rm32-is-first-inout +5863 2/imm32/r32-is-second-inout +5864 0/imm32/no-imm32 +5865 0/imm32/no-disp32 +5866 0/imm32/output-is-write-only +5867 _Primitive-add-mem-to-reg/imm32/next +5868 _Primitive-add-mem-to-reg: +5869 # var1/reg <- add var2 => 03/add var2/rm32 var1/r32 +5870 "add"/imm32/name +5871 Single-int-var-in-mem/imm32/inouts +5872 Single-int-var-in-some-register/imm32/outputs +5873 "03/add"/imm32/subx-name +5874 1/imm32/rm32-is-first-inout +5875 3/imm32/r32-is-first-output +5876 0/imm32/no-imm32 +5877 0/imm32/no-disp32 +5878 0/imm32/output-is-write-only +5879 _Primitive-add-lit-to-reg/imm32/next +5880 _Primitive-add-lit-to-reg: +5881 # var1/reg <- add lit => 81 0/subop/add var1/rm32 lit/imm32 +5882 "add"/imm32/name +5883 Single-lit-var/imm32/inouts +5884 Single-int-var-in-some-register/imm32/outputs +5885 "81 0/subop/add"/imm32/subx-name +5886 3/imm32/rm32-is-first-output +5887 0/imm32/no-r32 +5888 1/imm32/imm32-is-first-inout +5889 0/imm32/no-disp32 +5890 0/imm32/output-is-write-only +5891 _Primitive-add-lit-to-mem/imm32/next +5892 _Primitive-add-lit-to-mem: +5893 # add-to var1, lit => 81 0/subop/add var1/rm32 lit/imm32 +5894 "add-to"/imm32/name +5895 Int-var-and-literal/imm32/inouts +5896 0/imm32/outputs +5897 "81 0/subop/add"/imm32/subx-name +5898 1/imm32/rm32-is-first-inout +5899 0/imm32/no-r32 +5900 2/imm32/imm32-is-second-inout +5901 0/imm32/no-disp32 +5902 0/imm32/output-is-write-only +5903 _Primitive-subtract-from-eax/imm32/next +5904 # - subtract +5905 _Primitive-subtract-from-eax: +5906 # var/eax <- subtract lit => 2d/subtract-from-eax lit/imm32 +5907 "subtract"/imm32/name +5908 Single-lit-var/imm32/inouts +5909 Single-int-var-in-eax/imm32/outputs +5910 "2d/subtract-from-eax"/imm32/subx-name +5911 0/imm32/no-rm32 +5912 0/imm32/no-r32 +5913 1/imm32/imm32-is-first-inout +5914 0/imm32/no-disp32 +5915 0/imm32/output-is-write-only +5916 _Primitive-subtract-reg-from-reg/imm32/next +5917 _Primitive-subtract-reg-from-reg: +5918 # var1/reg <- subtract var2/reg => 29/subtract-from var1/rm32 var2/r32 +5919 "subtract"/imm32/name +5920 Single-int-var-in-some-register/imm32/inouts +5921 Single-int-var-in-some-register/imm32/outputs +5922 "29/subtract-from"/imm32/subx-name +5923 3/imm32/rm32-is-first-output +5924 1/imm32/r32-is-first-inout +5925 0/imm32/no-imm32 +5926 0/imm32/no-disp32 +5927 0/imm32/output-is-write-only +5928 _Primitive-subtract-reg-from-mem/imm32/next +5929 _Primitive-subtract-reg-from-mem: +5930 # subtract-from var1 var2/reg => 29/subtract-from var1 var2/r32 +5931 "subtract-from"/imm32/name +5932 Two-args-int-stack-int-reg/imm32/inouts +5933 0/imm32/outputs +5934 "29/subtract-from"/imm32/subx-name +5935 1/imm32/rm32-is-first-inout +5936 2/imm32/r32-is-second-inout +5937 0/imm32/no-imm32 +5938 0/imm32/no-disp32 +5939 0/imm32/output-is-write-only +5940 _Primitive-subtract-mem-from-reg/imm32/next +5941 _Primitive-subtract-mem-from-reg: +5942 # var1/reg <- subtract var2 => 2b/subtract var2/rm32 var1/r32 +5943 "subtract"/imm32/name +5944 Single-int-var-in-mem/imm32/inouts +5945 Single-int-var-in-some-register/imm32/outputs +5946 "2b/subtract"/imm32/subx-name +5947 1/imm32/rm32-is-first-inout +5948 3/imm32/r32-is-first-output +5949 0/imm32/no-imm32 +5950 0/imm32/no-disp32 +5951 0/imm32/output-is-write-only +5952 _Primitive-subtract-lit-from-reg/imm32/next +5953 _Primitive-subtract-lit-from-reg: +5954 # var1/reg <- subtract lit => 81 5/subop/subtract var1/rm32 lit/imm32 +5955 "subtract"/imm32/name +5956 Single-lit-var/imm32/inouts +5957 Single-int-var-in-some-register/imm32/outputs +5958 "81 5/subop/subtract"/imm32/subx-name +5959 3/imm32/rm32-is-first-output +5960 0/imm32/no-r32 +5961 1/imm32/imm32-is-first-inout +5962 0/imm32/no-disp32 +5963 0/imm32/output-is-write-only +5964 _Primitive-subtract-lit-from-mem/imm32/next +5965 _Primitive-subtract-lit-from-mem: +5966 # subtract-from var1, lit => 81 5/subop/subtract var1/rm32 lit/imm32 +5967 "subtract-from"/imm32/name +5968 Int-var-and-literal/imm32/inouts +5969 0/imm32/outputs +5970 "81 5/subop/subtract"/imm32/subx-name +5971 1/imm32/rm32-is-first-inout +5972 0/imm32/no-r32 +5973 2/imm32/imm32-is-first-inout +5974 0/imm32/no-disp32 +5975 0/imm32/output-is-write-only +5976 _Primitive-and-with-eax/imm32/next +5977 # - and +5978 _Primitive-and-with-eax: +5979 # var/eax <- and lit => 25/and-with-eax lit/imm32 +5980 "and"/imm32/name +5981 Single-lit-var/imm32/inouts +5982 Single-int-var-in-eax/imm32/outputs +5983 "25/and-with-eax"/imm32/subx-name +5984 0/imm32/no-rm32 +5985 0/imm32/no-r32 +5986 1/imm32/imm32-is-first-inout +5987 0/imm32/no-disp32 +5988 0/imm32/output-is-write-only +5989 _Primitive-and-reg-with-reg/imm32/next +5990 _Primitive-and-reg-with-reg: +5991 # var1/reg <- and var2/reg => 21/and-with var1/rm32 var2/r32 +5992 "and"/imm32/name +5993 Single-int-var-in-some-register/imm32/inouts +5994 Single-int-var-in-some-register/imm32/outputs +5995 "21/and-with"/imm32/subx-name +5996 3/imm32/rm32-is-first-output +5997 1/imm32/r32-is-first-inout +5998 0/imm32/no-imm32 +5999 0/imm32/no-disp32 +6000 0/imm32/output-is-write-only +6001 _Primitive-and-reg-with-mem/imm32/next +6002 _Primitive-and-reg-with-mem: +6003 # and-with var1 var2/reg => 21/and-with var1 var2/r32 +6004 "and-with"/imm32/name +6005 Two-args-int-stack-int-reg/imm32/inouts +6006 0/imm32/outputs +6007 "21/and-with"/imm32/subx-name +6008 1/imm32/rm32-is-first-inout +6009 2/imm32/r32-is-second-inout +6010 0/imm32/no-imm32 +6011 0/imm32/no-disp32 +6012 0/imm32/output-is-write-only +6013 _Primitive-and-mem-with-reg/imm32/next +6014 _Primitive-and-mem-with-reg: +6015 # var1/reg <- and var2 => 23/and var2/rm32 var1/r32 +6016 "and"/imm32/name +6017 Single-int-var-in-mem/imm32/inouts +6018 Single-int-var-in-some-register/imm32/outputs +6019 "23/and"/imm32/subx-name +6020 1/imm32/rm32-is-first-inout +6021 3/imm32/r32-is-first-output +6022 0/imm32/no-imm32 +6023 0/imm32/no-disp32 +6024 0/imm32/output-is-write-only +6025 _Primitive-and-lit-with-reg/imm32/next +6026 _Primitive-and-lit-with-reg: +6027 # var1/reg <- and lit => 81 4/subop/and var1/rm32 lit/imm32 +6028 "and"/imm32/name +6029 Single-lit-var/imm32/inouts +6030 Single-int-var-in-some-register/imm32/outputs +6031 "81 4/subop/and"/imm32/subx-name +6032 3/imm32/rm32-is-first-output +6033 0/imm32/no-r32 +6034 1/imm32/imm32-is-first-inout +6035 0/imm32/no-disp32 +6036 0/imm32/output-is-write-only +6037 _Primitive-and-lit-with-mem/imm32/next +6038 _Primitive-and-lit-with-mem: +6039 # and-with var1, lit => 81 4/subop/and var1/rm32 lit/imm32 +6040 "and-with"/imm32/name +6041 Int-var-and-literal/imm32/inouts +6042 0/imm32/outputs +6043 "81 4/subop/and"/imm32/subx-name +6044 1/imm32/rm32-is-first-inout +6045 0/imm32/no-r32 +6046 2/imm32/imm32-is-first-inout +6047 0/imm32/no-disp32 +6048 0/imm32/output-is-write-only +6049 _Primitive-or-with-eax/imm32/next +6050 # - or +6051 _Primitive-or-with-eax: +6052 # var/eax <- or lit => 0d/or-with-eax lit/imm32 +6053 "or"/imm32/name +6054 Single-lit-var/imm32/inouts +6055 Single-int-var-in-eax/imm32/outputs +6056 "0d/or-with-eax"/imm32/subx-name +6057 0/imm32/no-rm32 +6058 0/imm32/no-r32 +6059 1/imm32/imm32-is-first-inout +6060 0/imm32/no-disp32 +6061 0/imm32/output-is-write-only +6062 _Primitive-or-reg-with-reg/imm32/next +6063 _Primitive-or-reg-with-reg: +6064 # var1/reg <- or var2/reg => 09/or-with var1/rm32 var2/r32 +6065 "or"/imm32/name +6066 Single-int-var-in-some-register/imm32/inouts +6067 Single-int-var-in-some-register/imm32/outputs +6068 "09/or-with"/imm32/subx-name +6069 3/imm32/rm32-is-first-output +6070 1/imm32/r32-is-first-inout +6071 0/imm32/no-imm32 +6072 0/imm32/no-disp32 +6073 0/imm32/output-is-write-only +6074 _Primitive-or-reg-with-mem/imm32/next +6075 _Primitive-or-reg-with-mem: +6076 # or-with var1 var2/reg => 09/or-with var1 var2/r32 +6077 "or-with"/imm32/name +6078 Two-args-int-stack-int-reg/imm32/inouts +6079 0/imm32/outputs +6080 "09/or-with"/imm32/subx-name +6081 1/imm32/rm32-is-first-inout +6082 2/imm32/r32-is-second-inout +6083 0/imm32/no-imm32 +6084 0/imm32/no-disp32 +6085 0/imm32/output-is-write-only +6086 _Primitive-or-mem-with-reg/imm32/next +6087 _Primitive-or-mem-with-reg: +6088 # var1/reg <- or var2 => 0b/or var2/rm32 var1/r32 +6089 "or"/imm32/name +6090 Single-int-var-in-mem/imm32/inouts +6091 Single-int-var-in-some-register/imm32/outputs +6092 "0b/or"/imm32/subx-name +6093 1/imm32/rm32-is-first-inout +6094 3/imm32/r32-is-first-output +6095 0/imm32/no-imm32 +6096 0/imm32/no-disp32 +6097 0/imm32/output-is-write-only +6098 _Primitive-or-lit-with-reg/imm32/next +6099 _Primitive-or-lit-with-reg: +6100 # var1/reg <- or lit => 81 1/subop/or var1/rm32 lit/imm32 +6101 "or"/imm32/name +6102 Single-lit-var/imm32/inouts +6103 Single-int-var-in-some-register/imm32/outputs +6104 "81 1/subop/or"/imm32/subx-name +6105 3/imm32/rm32-is-first-output +6106 0/imm32/no-r32 +6107 1/imm32/imm32-is-first-inout +6108 0/imm32/no-disp32 +6109 0/imm32/output-is-write-only +6110 _Primitive-or-lit-with-mem/imm32/next +6111 _Primitive-or-lit-with-mem: +6112 # or-with var1, lit => 81 1/subop/or var1/rm32 lit/imm32 +6113 "or-with"/imm32/name +6114 Int-var-and-literal/imm32/inouts +6115 0/imm32/outputs +6116 "81 1/subop/or"/imm32/subx-name +6117 1/imm32/rm32-is-first-inout +6118 0/imm32/no-r32 +6119 2/imm32/imm32-is-second-inout +6120 0/imm32/no-disp32 +6121 0/imm32/output-is-write-only +6122 _Primitive-xor-with-eax/imm32/next +6123 # - xor +6124 _Primitive-xor-with-eax: +6125 # var/eax <- xor lit => 35/xor-with-eax lit/imm32 +6126 "xor"/imm32/name +6127 Single-lit-var/imm32/inouts +6128 Single-int-var-in-eax/imm32/outputs +6129 "35/xor-with-eax"/imm32/subx-name +6130 0/imm32/no-rm32 +6131 0/imm32/no-r32 +6132 1/imm32/imm32-is-first-inout +6133 0/imm32/no-disp32 +6134 0/imm32/output-is-write-only +6135 _Primitive-xor-reg-with-reg/imm32/next +6136 _Primitive-xor-reg-with-reg: +6137 # var1/reg <- xor var2/reg => 31/xor-with var1/rm32 var2/r32 +6138 "xor"/imm32/name +6139 Single-int-var-in-some-register/imm32/inouts +6140 Single-int-var-in-some-register/imm32/outputs +6141 "31/xor-with"/imm32/subx-name +6142 3/imm32/rm32-is-first-output +6143 1/imm32/r32-is-first-inout +6144 0/imm32/no-imm32 +6145 0/imm32/no-disp32 +6146 0/imm32/output-is-write-only +6147 _Primitive-xor-reg-with-mem/imm32/next +6148 _Primitive-xor-reg-with-mem: +6149 # xor-with var1 var2/reg => 31/xor-with var1 var2/r32 +6150 "xor-with"/imm32/name +6151 Two-args-int-stack-int-reg/imm32/inouts +6152 0/imm32/outputs +6153 "31/xor-with"/imm32/subx-name +6154 1/imm32/rm32-is-first-inout +6155 2/imm32/r32-is-second-inout +6156 0/imm32/no-imm32 +6157 0/imm32/no-disp32 +6158 0/imm32/output-is-write-only +6159 _Primitive-xor-mem-with-reg/imm32/next +6160 _Primitive-xor-mem-with-reg: +6161 # var1/reg <- xor var2 => 33/xor var2/rm32 var1/r32 +6162 "xor"/imm32/name +6163 Single-int-var-in-mem/imm32/inouts +6164 Single-int-var-in-some-register/imm32/outputs +6165 "33/xor"/imm32/subx-name +6166 1/imm32/rm32-is-first-inout +6167 3/imm32/r32-is-first-output +6168 0/imm32/no-imm32 +6169 0/imm32/no-disp32 +6170 0/imm32/output-is-write-only +6171 _Primitive-xor-lit-with-reg/imm32/next +6172 _Primitive-xor-lit-with-reg: +6173 # var1/reg <- xor lit => 81 6/subop/xor var1/rm32 lit/imm32 +6174 "xor"/imm32/name +6175 Single-lit-var/imm32/inouts +6176 Single-int-var-in-some-register/imm32/outputs +6177 "81 6/subop/xor"/imm32/subx-name +6178 3/imm32/rm32-is-first-output +6179 0/imm32/no-r32 +6180 1/imm32/imm32-is-first-inout +6181 0/imm32/no-disp32 +6182 0/imm32/output-is-write-only +6183 _Primitive-xor-lit-with-mem/imm32/next +6184 _Primitive-xor-lit-with-mem: +6185 # xor-with var1, lit => 81 6/subop/xor var1/rm32 lit/imm32 +6186 "xor-with"/imm32/name +6187 Int-var-and-literal/imm32/inouts +6188 0/imm32/outputs +6189 "81 6/subop/xor"/imm32/subx-name +6190 1/imm32/rm32-is-first-inout +6191 0/imm32/no-r32 +6192 2/imm32/imm32-is-first-inout +6193 0/imm32/no-disp32 +6194 0/imm32/output-is-write-only +6195 _Primitive-copy-to-eax/imm32/next +6196 # - copy +6197 _Primitive-copy-to-eax: +6198 # var/eax <- copy lit => b8/copy-to-eax lit/imm32 +6199 "copy"/imm32/name +6200 Single-lit-var/imm32/inouts +6201 Single-int-var-in-eax/imm32/outputs +6202 "b8/copy-to-eax"/imm32/subx-name +6203 0/imm32/no-rm32 +6204 0/imm32/no-r32 +6205 1/imm32/imm32-is-first-inout +6206 0/imm32/no-disp32 +6207 1/imm32/output-is-write-only +6208 _Primitive-copy-to-ecx/imm32/next +6209 _Primitive-copy-to-ecx: +6210 # var/ecx <- copy lit => b9/copy-to-ecx lit/imm32 +6211 "copy"/imm32/name +6212 Single-lit-var/imm32/inouts +6213 Single-int-var-in-ecx/imm32/outputs +6214 "b9/copy-to-ecx"/imm32/subx-name +6215 0/imm32/no-rm32 +6216 0/imm32/no-r32 +6217 1/imm32/imm32-is-first-inout +6218 0/imm32/no-disp32 +6219 1/imm32/output-is-write-only +6220 _Primitive-copy-to-edx/imm32/next +6221 _Primitive-copy-to-edx: +6222 # var/edx <- copy lit => ba/copy-to-edx lit/imm32 +6223 "copy"/imm32/name +6224 Single-lit-var/imm32/inouts +6225 Single-int-var-in-edx/imm32/outputs +6226 "ba/copy-to-edx"/imm32/subx-name +6227 0/imm32/no-rm32 +6228 0/imm32/no-r32 +6229 1/imm32/imm32-is-first-inout +6230 0/imm32/no-disp32 +6231 1/imm32/output-is-write-only +6232 _Primitive-copy-to-ebx/imm32/next +6233 _Primitive-copy-to-ebx: +6234 # var/ebx <- copy lit => bb/copy-to-ebx lit/imm32 +6235 "copy"/imm32/name +6236 Single-lit-var/imm32/inouts +6237 Single-int-var-in-ebx/imm32/outputs +6238 "bb/copy-to-ebx"/imm32/subx-name +6239 0/imm32/no-rm32 +6240 0/imm32/no-r32 +6241 1/imm32/imm32-is-first-inout +6242 0/imm32/no-disp32 +6243 1/imm32/output-is-write-only +6244 _Primitive-copy-to-esi/imm32/next +6245 _Primitive-copy-to-esi: +6246 # var/esi <- copy lit => be/copy-to-esi lit/imm32 +6247 "copy"/imm32/name +6248 Single-lit-var/imm32/inouts +6249 Single-int-var-in-esi/imm32/outputs +6250 "be/copy-to-esi"/imm32/subx-name +6251 0/imm32/no-rm32 +6252 0/imm32/no-r32 +6253 1/imm32/imm32-is-first-inout +6254 0/imm32/no-disp32 +6255 1/imm32/output-is-write-only +6256 _Primitive-copy-to-edi/imm32/next +6257 _Primitive-copy-to-edi: +6258 # var/edi <- copy lit => bf/copy-to-edi lit/imm32 +6259 "copy"/imm32/name +6260 Single-lit-var/imm32/inouts +6261 Single-int-var-in-edi/imm32/outputs +6262 "bf/copy-to-edi"/imm32/subx-name +6263 0/imm32/no-rm32 +6264 0/imm32/no-r32 +6265 1/imm32/imm32-is-first-inout +6266 0/imm32/no-disp32 +6267 1/imm32/output-is-write-only +6268 _Primitive-copy-reg-to-reg/imm32/next +6269 _Primitive-copy-reg-to-reg: +6270 # var1/reg <- copy var2/reg => 89/copy-to var1/rm32 var2/r32 +6271 "copy"/imm32/name +6272 Single-int-var-in-some-register/imm32/inouts +6273 Single-int-var-in-some-register/imm32/outputs +6274 "89/copy-to"/imm32/subx-name +6275 3/imm32/rm32-is-first-output +6276 1/imm32/r32-is-first-inout +6277 0/imm32/no-imm32 +6278 0/imm32/no-disp32 +6279 1/imm32/output-is-write-only +6280 _Primitive-copy-reg-to-mem/imm32/next +6281 _Primitive-copy-reg-to-mem: +6282 # copy-to var1 var2/reg => 89/copy-to var1 var2/r32 +6283 "copy-to"/imm32/name +6284 Two-args-int-stack-int-reg/imm32/inouts +6285 0/imm32/outputs +6286 "89/copy-to"/imm32/subx-name +6287 1/imm32/rm32-is-first-inout +6288 2/imm32/r32-is-second-inout +6289 0/imm32/no-imm32 +6290 0/imm32/no-disp32 +6291 1/imm32/output-is-write-only +6292 _Primitive-copy-mem-to-reg/imm32/next +6293 _Primitive-copy-mem-to-reg: +6294 # var1/reg <- copy var2 => 8b/copy-from var2/rm32 var1/r32 +6295 "copy"/imm32/name +6296 Single-int-var-in-mem/imm32/inouts +6297 Single-int-var-in-some-register/imm32/outputs +6298 "8b/copy-from"/imm32/subx-name +6299 1/imm32/rm32-is-first-inout +6300 3/imm32/r32-is-first-output +6301 0/imm32/no-imm32 +6302 0/imm32/no-disp32 +6303 1/imm32/output-is-write-only +6304 _Primitive-copy-lit-to-reg/imm32/next +6305 _Primitive-copy-lit-to-reg: +6306 # var1/reg <- copy lit => c7 0/subop/copy var1/rm32 lit/imm32 +6307 "copy"/imm32/name +6308 Single-lit-var/imm32/inouts +6309 Single-int-var-in-some-register/imm32/outputs +6310 "c7 0/subop/copy"/imm32/subx-name +6311 3/imm32/rm32-is-first-output +6312 0/imm32/no-r32 +6313 1/imm32/imm32-is-first-inout +6314 0/imm32/no-disp32 +6315 1/imm32/output-is-write-only +6316 _Primitive-copy-lit-to-mem/imm32/next +6317 _Primitive-copy-lit-to-mem: +6318 # copy-to var1, lit => c7 0/subop/copy var1/rm32 lit/imm32 +6319 "copy-to"/imm32/name +6320 Int-var-and-literal/imm32/inouts +6321 0/imm32/outputs +6322 "c7 0/subop/copy"/imm32/subx-name +6323 1/imm32/rm32-is-first-inout +6324 0/imm32/no-r32 +6325 2/imm32/imm32-is-first-inout +6326 0/imm32/no-disp32 +6327 1/imm32/output-is-write-only +6328 _Primitive-compare-mem-with-reg/imm32/next +6329 # - compare +6330 _Primitive-compare-mem-with-reg: +6331 # compare var1 var2/reg => 39/compare-> var1/rm32 var2/r32 +6332 "compare"/imm32/name +6333 Two-args-int-stack-int-reg/imm32/inouts +6334 0/imm32/outputs +6335 "39/compare->"/imm32/subx-name +6336 1/imm32/rm32-is-first-inout +6337 2/imm32/r32-is-second-inout +6338 0/imm32/no-imm32 +6339 0/imm32/no-disp32 +6340 0/imm32/output-is-write-only +6341 _Primitive-compare-reg-with-mem/imm32/next +6342 _Primitive-compare-reg-with-mem: +6343 # compare var1/reg var2 => 3b/compare<- var2/rm32 var1/r32 +6344 "compare"/imm32/name +6345 Two-args-int-reg-int-stack/imm32/inouts +6346 0/imm32/outputs +6347 "3b/compare<-"/imm32/subx-name +6348 2/imm32/rm32-is-second-inout +6349 1/imm32/r32-is-first-inout +6350 0/imm32/no-imm32 +6351 0/imm32/no-disp32 +6352 0/imm32/output-is-write-only +6353 _Primitive-compare-eax-with-literal/imm32/next +6354 _Primitive-compare-eax-with-literal: +6355 # compare var1/eax n => 3d/compare-eax-with n/imm32 +6356 "compare"/imm32/name +6357 Two-args-int-eax-int-literal/imm32/inouts +6358 0/imm32/outputs +6359 "3d/compare-eax-with"/imm32/subx-name +6360 0/imm32/no-rm32 +6361 0/imm32/no-r32 +6362 2/imm32/imm32-is-second-inout +6363 0/imm32/no-disp32 +6364 0/imm32/output-is-write-only +6365 _Primitive-compare-reg-with-literal/imm32/next +6366 _Primitive-compare-reg-with-literal: +6367 # compare var1/reg n => 81 7/subop/compare %reg n/imm32 +6368 "compare"/imm32/name +6369 Int-var-in-register-and-literal/imm32/inouts +6370 0/imm32/outputs +6371 "81 7/subop/compare"/imm32/subx-name +6372 1/imm32/rm32-is-first-inout +6373 0/imm32/no-r32 +6374 2/imm32/imm32-is-second-inout +6375 0/imm32/no-disp32 +6376 0/imm32/output-is-write-only +6377 _Primitive-compare-mem-with-literal/imm32/next +6378 _Primitive-compare-mem-with-literal: +6379 # compare var1 n => 81 7/subop/compare *(ebp+___) n/imm32 +6380 "compare"/imm32/name +6381 Int-var-and-literal/imm32/inouts +6382 0/imm32/outputs +6383 "81 7/subop/compare"/imm32/subx-name +6384 1/imm32/rm32-is-first-inout +6385 0/imm32/no-r32 +6386 2/imm32/imm32-is-second-inout +6387 0/imm32/no-disp32 +6388 0/imm32/output-is-write-only +6389 _Primitive-multiply-reg-by-mem/imm32/next +6390 # - multiply +6391 _Primitive-multiply-reg-by-mem: +6392 # var1/reg <- multiply var2 => 0f af/multiply var2/rm32 var1/r32 +6393 "multiply"/imm32/name +6394 Single-int-var-in-mem/imm32/inouts +6395 Single-int-var-in-some-register/imm32/outputs +6396 "0f af/multiply"/imm32/subx-name +6397 1/imm32/rm32-is-first-inout +6398 3/imm32/r32-is-first-output +6399 0/imm32/no-imm32 +6400 0/imm32/no-disp32 +6401 0/imm32/output-is-write-only +6402 _Primitive-break-if-addr</imm32/next +6403 # - branches +6404 _Primitive-break-if-addr<: +6405 "break-if-addr<"/imm32/name 6406 0/imm32/inouts 6407 0/imm32/outputs -6408 "0f 8d/jump-if->= break/disp32"/imm32/subx-name +6408 "0f 82/jump-if-addr< break/disp32"/imm32/subx-name 6409 0/imm32/no-rm32 6410 0/imm32/no-r32 6411 0/imm32/no-imm32 6412 0/imm32/no-disp32 6413 0/imm32/no-output -6414 _Primitive-break-if-<=/imm32/next -6415 _Primitive-break-if-<=: -6416 "break-if-<="/imm32/name +6414 _Primitive-break-if-addr>=/imm32/next +6415 _Primitive-break-if-addr>=: +6416 "break-if-addr>="/imm32/name 6417 0/imm32/inouts 6418 0/imm32/outputs -6419 "0f 8e/jump-if-<= break/disp32"/imm32/subx-name +6419 "0f 83/jump-if-addr>= break/disp32"/imm32/subx-name 6420 0/imm32/no-rm32 6421 0/imm32/no-r32 6422 0/imm32/no-imm32 6423 0/imm32/no-disp32 6424 0/imm32/no-output -6425 _Primitive-break-if->/imm32/next -6426 _Primitive-break-if->: -6427 "break-if->"/imm32/name +6425 _Primitive-break-if-=/imm32/next +6426 _Primitive-break-if-=: +6427 "break-if-="/imm32/name 6428 0/imm32/inouts 6429 0/imm32/outputs -6430 "0f 8f/jump-if-> break/disp32"/imm32/subx-name +6430 "0f 84/jump-if-= break/disp32"/imm32/subx-name 6431 0/imm32/no-rm32 6432 0/imm32/no-r32 6433 0/imm32/no-imm32 6434 0/imm32/no-disp32 6435 0/imm32/no-output -6436 _Primitive-break/imm32/next -6437 _Primitive-break: -6438 "break"/imm32/name +6436 _Primitive-break-if-!=/imm32/next +6437 _Primitive-break-if-!=: +6438 "break-if-!="/imm32/name 6439 0/imm32/inouts 6440 0/imm32/outputs -6441 "e9/jump break/disp32"/imm32/subx-name +6441 "0f 85/jump-if-!= break/disp32"/imm32/subx-name 6442 0/imm32/no-rm32 6443 0/imm32/no-r32 6444 0/imm32/no-imm32 6445 0/imm32/no-disp32 6446 0/imm32/no-output -6447 _Primitive-loop-if-addr</imm32/next -6448 _Primitive-loop-if-addr<: -6449 "loop-if-addr<"/imm32/name +6447 _Primitive-break-if-addr<=/imm32/next +6448 _Primitive-break-if-addr<=: +6449 "break-if-addr<="/imm32/name 6450 0/imm32/inouts 6451 0/imm32/outputs -6452 "0f 82/jump-if-addr< loop/disp32"/imm32/subx-name +6452 "0f 86/jump-if-addr<= break/disp32"/imm32/subx-name 6453 0/imm32/no-rm32 6454 0/imm32/no-r32 6455 0/imm32/no-imm32 6456 0/imm32/no-disp32 6457 0/imm32/no-output -6458 _Primitive-loop-if-addr>=/imm32/next -6459 _Primitive-loop-if-addr>=: -6460 "loop-if-addr>="/imm32/name +6458 _Primitive-break-if-addr>/imm32/next +6459 _Primitive-break-if-addr>: +6460 "break-if-addr>"/imm32/name 6461 0/imm32/inouts 6462 0/imm32/outputs -6463 "0f 83/jump-if-addr>= loop/disp32"/imm32/subx-name +6463 "0f 87/jump-if-addr> break/disp32"/imm32/subx-name 6464 0/imm32/no-rm32 6465 0/imm32/no-r32 6466 0/imm32/no-imm32 6467 0/imm32/no-disp32 6468 0/imm32/no-output -6469 _Primitive-loop-if-=/imm32/next -6470 _Primitive-loop-if-=: -6471 "loop-if-="/imm32/name +6469 _Primitive-break-if-</imm32/next +6470 _Primitive-break-if-<: +6471 "break-if-<"/imm32/name 6472 0/imm32/inouts 6473 0/imm32/outputs -6474 "0f 84/jump-if-= loop/disp32"/imm32/subx-name +6474 "0f 8c/jump-if-< break/disp32"/imm32/subx-name 6475 0/imm32/no-rm32 6476 0/imm32/no-r32 6477 0/imm32/no-imm32 6478 0/imm32/no-disp32 6479 0/imm32/no-output -6480 _Primitive-loop-if-!=/imm32/next -6481 _Primitive-loop-if-!=: -6482 "loop-if-!="/imm32/name +6480 _Primitive-break-if->=/imm32/next +6481 _Primitive-break-if->=: +6482 "break-if->="/imm32/name 6483 0/imm32/inouts 6484 0/imm32/outputs -6485 "0f 85/jump-if-!= loop/disp32"/imm32/subx-name +6485 "0f 8d/jump-if->= break/disp32"/imm32/subx-name 6486 0/imm32/no-rm32 6487 0/imm32/no-r32 6488 0/imm32/no-imm32 6489 0/imm32/no-disp32 6490 0/imm32/no-output -6491 _Primitive-loop-if-addr<=/imm32/next -6492 _Primitive-loop-if-addr<=: -6493 "loop-if-addr<="/imm32/name +6491 _Primitive-break-if-<=/imm32/next +6492 _Primitive-break-if-<=: +6493 "break-if-<="/imm32/name 6494 0/imm32/inouts 6495 0/imm32/outputs -6496 "0f 86/jump-if-addr<= loop/disp32"/imm32/subx-name +6496 "0f 8e/jump-if-<= break/disp32"/imm32/subx-name 6497 0/imm32/no-rm32 6498 0/imm32/no-r32 6499 0/imm32/no-imm32 6500 0/imm32/no-disp32 6501 0/imm32/no-output -6502 _Primitive-loop-if-addr>/imm32/next -6503 _Primitive-loop-if-addr>: -6504 "loop-if-addr>"/imm32/name +6502 _Primitive-break-if->/imm32/next +6503 _Primitive-break-if->: +6504 "break-if->"/imm32/name 6505 0/imm32/inouts 6506 0/imm32/outputs -6507 "0f 87/jump-if-addr> loop/disp32"/imm32/subx-name +6507 "0f 8f/jump-if-> break/disp32"/imm32/subx-name 6508 0/imm32/no-rm32 6509 0/imm32/no-r32 6510 0/imm32/no-imm32 6511 0/imm32/no-disp32 6512 0/imm32/no-output -6513 _Primitive-loop-if-</imm32/next -6514 _Primitive-loop-if-<: -6515 "loop-if-<"/imm32/name +6513 _Primitive-break/imm32/next +6514 _Primitive-break: +6515 "break"/imm32/name 6516 0/imm32/inouts 6517 0/imm32/outputs -6518 "0f 8c/jump-if-< loop/disp32"/imm32/subx-name +6518 "e9/jump break/disp32"/imm32/subx-name 6519 0/imm32/no-rm32 6520 0/imm32/no-r32 6521 0/imm32/no-imm32 6522 0/imm32/no-disp32 6523 0/imm32/no-output -6524 _Primitive-loop-if->=/imm32/next -6525 _Primitive-loop-if->=: -6526 "loop-if->="/imm32/name +6524 _Primitive-loop-if-addr</imm32/next +6525 _Primitive-loop-if-addr<: +6526 "loop-if-addr<"/imm32/name 6527 0/imm32/inouts 6528 0/imm32/outputs -6529 "0f 8d/jump-if->= loop/disp32"/imm32/subx-name +6529 "0f 82/jump-if-addr< loop/disp32"/imm32/subx-name 6530 0/imm32/no-rm32 6531 0/imm32/no-r32 6532 0/imm32/no-imm32 6533 0/imm32/no-disp32 6534 0/imm32/no-output -6535 _Primitive-loop-if-<=/imm32/next -6536 _Primitive-loop-if-<=: -6537 "loop-if-<="/imm32/name +6535 _Primitive-loop-if-addr>=/imm32/next +6536 _Primitive-loop-if-addr>=: +6537 "loop-if-addr>="/imm32/name 6538 0/imm32/inouts 6539 0/imm32/outputs -6540 "0f 8e/jump-if-<= loop/disp32"/imm32/subx-name +6540 "0f 83/jump-if-addr>= loop/disp32"/imm32/subx-name 6541 0/imm32/no-rm32 6542 0/imm32/no-r32 6543 0/imm32/no-imm32 6544 0/imm32/no-disp32 6545 0/imm32/no-output -6546 _Primitive-loop-if->/imm32/next -6547 _Primitive-loop-if->: -6548 "loop-if->"/imm32/name +6546 _Primitive-loop-if-=/imm32/next +6547 _Primitive-loop-if-=: +6548 "loop-if-="/imm32/name 6549 0/imm32/inouts 6550 0/imm32/outputs -6551 "0f 8f/jump-if-> loop/disp32"/imm32/subx-name +6551 "0f 84/jump-if-= loop/disp32"/imm32/subx-name 6552 0/imm32/no-rm32 6553 0/imm32/no-r32 6554 0/imm32/no-imm32 6555 0/imm32/no-disp32 6556 0/imm32/no-output -6557 _Primitive-loop/imm32/next # we probably don't need an unconditional break -6558 _Primitive-loop: -6559 "loop"/imm32/name +6557 _Primitive-loop-if-!=/imm32/next +6558 _Primitive-loop-if-!=: +6559 "loop-if-!="/imm32/name 6560 0/imm32/inouts 6561 0/imm32/outputs -6562 "e9/jump loop/disp32"/imm32/subx-name +6562 "0f 85/jump-if-!= loop/disp32"/imm32/subx-name 6563 0/imm32/no-rm32 6564 0/imm32/no-r32 6565 0/imm32/no-imm32 6566 0/imm32/no-disp32 6567 0/imm32/no-output -6568 _Primitive-break-if-addr<-named/imm32/next -6569 # - branches to named blocks -6570 _Primitive-break-if-addr<-named: -6571 "break-if-addr<"/imm32/name -6572 Single-lit-var/imm32/inouts -6573 0/imm32/outputs -6574 "0f 82/jump-if-addr<"/imm32/subx-name -6575 0/imm32/no-rm32 -6576 0/imm32/no-r32 -6577 0/imm32/no-imm32 -6578 1/imm32/disp32-is-first-inout -6579 0/imm32/no-output -6580 _Primitive-break-if-addr>=-named/imm32/next -6581 _Primitive-break-if-addr>=-named: -6582 "break-if-addr>="/imm32/name -6583 Single-lit-var/imm32/inouts -6584 0/imm32/outputs -6585 "0f 83/jump-if-addr>="/imm32/subx-name -6586 0/imm32/no-rm32 -6587 0/imm32/no-r32 -6588 0/imm32/no-imm32 -6589 1/imm32/disp32-is-first-inout -6590 0/imm32/no-output -6591 _Primitive-break-if-=-named/imm32/next -6592 _Primitive-break-if-=-named: -6593 "break-if-="/imm32/name -6594 Single-lit-var/imm32/inouts -6595 0/imm32/outputs -6596 "0f 84/jump-if-="/imm32/subx-name -6597 0/imm32/no-rm32 -6598 0/imm32/no-r32 -6599 0/imm32/no-imm32 -6600 1/imm32/disp32-is-first-inout -6601 0/imm32/no-output -6602 _Primitive-break-if-!=-named/imm32/next -6603 _Primitive-break-if-!=-named: -6604 "break-if-!="/imm32/name -6605 Single-lit-var/imm32/inouts -6606 0/imm32/outputs -6607 "0f 85/jump-if-!="/imm32/subx-name -6608 0/imm32/no-rm32 -6609 0/imm32/no-r32 -6610 0/imm32/no-imm32 -6611 1/imm32/disp32-is-first-inout -6612 0/imm32/no-output -6613 _Primitive-break-if-addr<=-named/imm32/next -6614 _Primitive-break-if-addr<=-named: -6615 "break-if-addr<="/imm32/name -6616 Single-lit-var/imm32/inouts -6617 0/imm32/outputs -6618 "0f 86/jump-if-addr<="/imm32/subx-name -6619 0/imm32/no-rm32 -6620 0/imm32/no-r32 -6621 0/imm32/no-imm32 -6622 1/imm32/disp32-is-first-inout -6623 0/imm32/no-output -6624 _Primitive-break-if-addr>-named/imm32/next -6625 _Primitive-break-if-addr>-named: -6626 "break-if-addr>"/imm32/name -6627 Single-lit-var/imm32/inouts -6628 0/imm32/outputs -6629 "0f 87/jump-if-addr>"/imm32/subx-name -6630 0/imm32/no-rm32 -6631 0/imm32/no-r32 -6632 0/imm32/no-imm32 -6633 1/imm32/disp32-is-first-inout -6634 0/imm32/no-output -6635 _Primitive-break-if-<-named/imm32/next -6636 _Primitive-break-if-<-named: -6637 "break-if-<"/imm32/name -6638 Single-lit-var/imm32/inouts -6639 0/imm32/outputs -6640 "0f 8c/jump-if-<"/imm32/subx-name -6641 0/imm32/no-rm32 -6642 0/imm32/no-r32 -6643 0/imm32/no-imm32 -6644 1/imm32/disp32-is-first-inout -6645 0/imm32/no-output -6646 _Primitive-break-if->=-named/imm32/next -6647 _Primitive-break-if->=-named: -6648 "break-if->="/imm32/name -6649 Single-lit-var/imm32/inouts +6568 _Primitive-loop-if-addr<=/imm32/next +6569 _Primitive-loop-if-addr<=: +6570 "loop-if-addr<="/imm32/name +6571 0/imm32/inouts +6572 0/imm32/outputs +6573 "0f 86/jump-if-addr<= loop/disp32"/imm32/subx-name +6574 0/imm32/no-rm32 +6575 0/imm32/no-r32 +6576 0/imm32/no-imm32 +6577 0/imm32/no-disp32 +6578 0/imm32/no-output +6579 _Primitive-loop-if-addr>/imm32/next +6580 _Primitive-loop-if-addr>: +6581 "loop-if-addr>"/imm32/name +6582 0/imm32/inouts +6583 0/imm32/outputs +6584 "0f 87/jump-if-addr> loop/disp32"/imm32/subx-name +6585 0/imm32/no-rm32 +6586 0/imm32/no-r32 +6587 0/imm32/no-imm32 +6588 0/imm32/no-disp32 +6589 0/imm32/no-output +6590 _Primitive-loop-if-</imm32/next +6591 _Primitive-loop-if-<: +6592 "loop-if-<"/imm32/name +6593 0/imm32/inouts +6594 0/imm32/outputs +6595 "0f 8c/jump-if-< loop/disp32"/imm32/subx-name +6596 0/imm32/no-rm32 +6597 0/imm32/no-r32 +6598 0/imm32/no-imm32 +6599 0/imm32/no-disp32 +6600 0/imm32/no-output +6601 _Primitive-loop-if->=/imm32/next +6602 _Primitive-loop-if->=: +6603 "loop-if->="/imm32/name +6604 0/imm32/inouts +6605 0/imm32/outputs +6606 "0f 8d/jump-if->= loop/disp32"/imm32/subx-name +6607 0/imm32/no-rm32 +6608 0/imm32/no-r32 +6609 0/imm32/no-imm32 +6610 0/imm32/no-disp32 +6611 0/imm32/no-output +6612 _Primitive-loop-if-<=/imm32/next +6613 _Primitive-loop-if-<=: +6614 "loop-if-<="/imm32/name +6615 0/imm32/inouts +6616 0/imm32/outputs +6617 "0f 8e/jump-if-<= loop/disp32"/imm32/subx-name +6618 0/imm32/no-rm32 +6619 0/imm32/no-r32 +6620 0/imm32/no-imm32 +6621 0/imm32/no-disp32 +6622 0/imm32/no-output +6623 _Primitive-loop-if->/imm32/next +6624 _Primitive-loop-if->: +6625 "loop-if->"/imm32/name +6626 0/imm32/inouts +6627 0/imm32/outputs +6628 "0f 8f/jump-if-> loop/disp32"/imm32/subx-name +6629 0/imm32/no-rm32 +6630 0/imm32/no-r32 +6631 0/imm32/no-imm32 +6632 0/imm32/no-disp32 +6633 0/imm32/no-output +6634 _Primitive-loop/imm32/next # we probably don't need an unconditional break +6635 _Primitive-loop: +6636 "loop"/imm32/name +6637 0/imm32/inouts +6638 0/imm32/outputs +6639 "e9/jump loop/disp32"/imm32/subx-name +6640 0/imm32/no-rm32 +6641 0/imm32/no-r32 +6642 0/imm32/no-imm32 +6643 0/imm32/no-disp32 +6644 0/imm32/no-output +6645 _Primitive-break-if-addr<-named/imm32/next +6646 # - branches to named blocks +6647 _Primitive-break-if-addr<-named: +6648 "break-if-addr<"/imm32/name +6649 Single-lit-var/imm32/inouts 6650 0/imm32/outputs -6651 "0f 8d/jump-if->="/imm32/subx-name +6651 "0f 82/jump-if-addr<"/imm32/subx-name 6652 0/imm32/no-rm32 6653 0/imm32/no-r32 6654 0/imm32/no-imm32 6655 1/imm32/disp32-is-first-inout 6656 0/imm32/no-output -6657 _Primitive-break-if-<=-named/imm32/next -6658 _Primitive-break-if-<=-named: -6659 "break-if-<="/imm32/name -6660 Single-lit-var/imm32/inouts +6657 _Primitive-break-if-addr>=-named/imm32/next +6658 _Primitive-break-if-addr>=-named: +6659 "break-if-addr>="/imm32/name +6660 Single-lit-var/imm32/inouts 6661 0/imm32/outputs -6662 "0f 8e/jump-if-<="/imm32/subx-name +6662 "0f 83/jump-if-addr>="/imm32/subx-name 6663 0/imm32/no-rm32 6664 0/imm32/no-r32 6665 0/imm32/no-imm32 6666 1/imm32/disp32-is-first-inout 6667 0/imm32/no-output -6668 _Primitive-break-if->-named/imm32/next -6669 _Primitive-break-if->-named: -6670 "break-if->"/imm32/name -6671 Single-lit-var/imm32/inouts +6668 _Primitive-break-if-=-named/imm32/next +6669 _Primitive-break-if-=-named: +6670 "break-if-="/imm32/name +6671 Single-lit-var/imm32/inouts 6672 0/imm32/outputs -6673 "0f 8f/jump-if->"/imm32/subx-name +6673 "0f 84/jump-if-="/imm32/subx-name 6674 0/imm32/no-rm32 6675 0/imm32/no-r32 6676 0/imm32/no-imm32 6677 1/imm32/disp32-is-first-inout 6678 0/imm32/no-output -6679 _Primitive-break-named/imm32/next -6680 _Primitive-break-named: -6681 "break"/imm32/name -6682 Single-lit-var/imm32/inouts +6679 _Primitive-break-if-!=-named/imm32/next +6680 _Primitive-break-if-!=-named: +6681 "break-if-!="/imm32/name +6682 Single-lit-var/imm32/inouts 6683 0/imm32/outputs -6684 "e9/jump"/imm32/subx-name +6684 "0f 85/jump-if-!="/imm32/subx-name 6685 0/imm32/no-rm32 6686 0/imm32/no-r32 6687 0/imm32/no-imm32 6688 1/imm32/disp32-is-first-inout 6689 0/imm32/no-output -6690 _Primitive-loop-if-addr<-named/imm32/next -6691 _Primitive-loop-if-addr<-named: -6692 "loop-if-addr<"/imm32/name -6693 Single-lit-var/imm32/inouts +6690 _Primitive-break-if-addr<=-named/imm32/next +6691 _Primitive-break-if-addr<=-named: +6692 "break-if-addr<="/imm32/name +6693 Single-lit-var/imm32/inouts 6694 0/imm32/outputs -6695 "0f 82/jump-if-addr<"/imm32/subx-name +6695 "0f 86/jump-if-addr<="/imm32/subx-name 6696 0/imm32/no-rm32 6697 0/imm32/no-r32 6698 0/imm32/no-imm32 6699 1/imm32/disp32-is-first-inout 6700 0/imm32/no-output -6701 _Primitive-loop-if-addr>=-named/imm32/next -6702 _Primitive-loop-if-addr>=-named: -6703 "loop-if-addr>="/imm32/name -6704 Single-lit-var/imm32/inouts +6701 _Primitive-break-if-addr>-named/imm32/next +6702 _Primitive-break-if-addr>-named: +6703 "break-if-addr>"/imm32/name +6704 Single-lit-var/imm32/inouts 6705 0/imm32/outputs -6706 "0f 83/jump-if-addr>="/imm32/subx-name +6706 "0f 87/jump-if-addr>"/imm32/subx-name 6707 0/imm32/no-rm32 6708 0/imm32/no-r32 6709 0/imm32/no-imm32 6710 1/imm32/disp32-is-first-inout 6711 0/imm32/no-output -6712 _Primitive-loop-if-=-named/imm32/next -6713 _Primitive-loop-if-=-named: -6714 "loop-if-="/imm32/name -6715 Single-lit-var/imm32/inouts +6712 _Primitive-break-if-<-named/imm32/next +6713 _Primitive-break-if-<-named: +6714 "break-if-<"/imm32/name +6715 Single-lit-var/imm32/inouts 6716 0/imm32/outputs -6717 "0f 84/jump-if-="/imm32/subx-name +6717 "0f 8c/jump-if-<"/imm32/subx-name 6718 0/imm32/no-rm32 6719 0/imm32/no-r32 6720 0/imm32/no-imm32 6721 1/imm32/disp32-is-first-inout 6722 0/imm32/no-output -6723 _Primitive-loop-if-!=-named/imm32/next -6724 _Primitive-loop-if-!=-named: -6725 "loop-if-!="/imm32/name -6726 Single-lit-var/imm32/inouts +6723 _Primitive-break-if->=-named/imm32/next +6724 _Primitive-break-if->=-named: +6725 "break-if->="/imm32/name +6726 Single-lit-var/imm32/inouts 6727 0/imm32/outputs -6728 "0f 85/jump-if-!="/imm32/subx-name +6728 "0f 8d/jump-if->="/imm32/subx-name 6729 0/imm32/no-rm32 6730 0/imm32/no-r32 6731 0/imm32/no-imm32 6732 1/imm32/disp32-is-first-inout 6733 0/imm32/no-output -6734 _Primitive-loop-if-addr<=-named/imm32/next -6735 _Primitive-loop-if-addr<=-named: -6736 "loop-if-addr<="/imm32/name -6737 Single-lit-var/imm32/inouts +6734 _Primitive-break-if-<=-named/imm32/next +6735 _Primitive-break-if-<=-named: +6736 "break-if-<="/imm32/name +6737 Single-lit-var/imm32/inouts 6738 0/imm32/outputs -6739 "0f 86/jump-if-addr<="/imm32/subx-name +6739 "0f 8e/jump-if-<="/imm32/subx-name 6740 0/imm32/no-rm32 6741 0/imm32/no-r32 6742 0/imm32/no-imm32 6743 1/imm32/disp32-is-first-inout 6744 0/imm32/no-output -6745 _Primitive-loop-if-addr>-named/imm32/next -6746 _Primitive-loop-if-addr>-named: -6747 "loop-if-addr>"/imm32/name -6748 Single-lit-var/imm32/inouts +6745 _Primitive-break-if->-named/imm32/next +6746 _Primitive-break-if->-named: +6747 "break-if->"/imm32/name +6748 Single-lit-var/imm32/inouts 6749 0/imm32/outputs -6750 "0f 87/jump-if-addr>"/imm32/subx-name +6750 "0f 8f/jump-if->"/imm32/subx-name 6751 0/imm32/no-rm32 6752 0/imm32/no-r32 6753 0/imm32/no-imm32 6754 1/imm32/disp32-is-first-inout 6755 0/imm32/no-output -6756 _Primitive-loop-if-<-named/imm32/next -6757 _Primitive-loop-if-<-named: -6758 "loop-if-<"/imm32/name -6759 Single-lit-var/imm32/inouts +6756 _Primitive-break-named/imm32/next +6757 _Primitive-break-named: +6758 "break"/imm32/name +6759 Single-lit-var/imm32/inouts 6760 0/imm32/outputs -6761 "0f 8c/jump-if-<"/imm32/subx-name +6761 "e9/jump"/imm32/subx-name 6762 0/imm32/no-rm32 6763 0/imm32/no-r32 6764 0/imm32/no-imm32 6765 1/imm32/disp32-is-first-inout 6766 0/imm32/no-output -6767 _Primitive-loop-if->=-named/imm32/next -6768 _Primitive-loop-if->=-named: -6769 "loop-if->="/imm32/name -6770 Single-lit-var/imm32/inouts +6767 _Primitive-loop-if-addr<-named/imm32/next +6768 _Primitive-loop-if-addr<-named: +6769 "loop-if-addr<"/imm32/name +6770 Single-lit-var/imm32/inouts 6771 0/imm32/outputs -6772 "0f 8d/jump-if->="/imm32/subx-name +6772 "0f 82/jump-if-addr<"/imm32/subx-name 6773 0/imm32/no-rm32 6774 0/imm32/no-r32 6775 0/imm32/no-imm32 6776 1/imm32/disp32-is-first-inout 6777 0/imm32/no-output -6778 _Primitive-loop-if-<=-named/imm32/next -6779 _Primitive-loop-if-<=-named: -6780 "loop-if-<="/imm32/name -6781 Single-lit-var/imm32/inouts +6778 _Primitive-loop-if-addr>=-named/imm32/next +6779 _Primitive-loop-if-addr>=-named: +6780 "loop-if-addr>="/imm32/name +6781 Single-lit-var/imm32/inouts 6782 0/imm32/outputs -6783 "0f 8e/jump-if-<="/imm32/subx-name +6783 "0f 83/jump-if-addr>="/imm32/subx-name 6784 0/imm32/no-rm32 6785 0/imm32/no-r32 6786 0/imm32/no-imm32 6787 1/imm32/disp32-is-first-inout 6788 0/imm32/no-output -6789 _Primitive-loop-if->-named/imm32/next -6790 _Primitive-loop-if->-named: -6791 "loop-if->"/imm32/name -6792 Single-lit-var/imm32/inouts +6789 _Primitive-loop-if-=-named/imm32/next +6790 _Primitive-loop-if-=-named: +6791 "loop-if-="/imm32/name +6792 Single-lit-var/imm32/inouts 6793 0/imm32/outputs -6794 "0f 8f/jump-if->"/imm32/subx-name +6794 "0f 84/jump-if-="/imm32/subx-name 6795 0/imm32/no-rm32 6796 0/imm32/no-r32 6797 0/imm32/no-imm32 6798 1/imm32/disp32-is-first-inout 6799 0/imm32/no-output -6800 _Primitive-loop-named/imm32/next # we probably don't need an unconditional break -6801 _Primitive-loop-named: -6802 "loop"/imm32/name -6803 Single-lit-var/imm32/inouts +6800 _Primitive-loop-if-!=-named/imm32/next +6801 _Primitive-loop-if-!=-named: +6802 "loop-if-!="/imm32/name +6803 Single-lit-var/imm32/inouts 6804 0/imm32/outputs -6805 "e9/jump"/imm32/subx-name +6805 "0f 85/jump-if-!="/imm32/subx-name 6806 0/imm32/no-rm32 6807 0/imm32/no-r32 6808 0/imm32/no-imm32 6809 1/imm32/disp32-is-first-inout 6810 0/imm32/no-output -6811 0/imm32/next -6812 -6813 Single-int-var-in-mem: -6814 Int-var-in-mem/imm32 -6815 0/imm32/next -6816 -6817 Int-var-in-mem: -6818 "arg1"/imm32/name -6819 Type-int/imm32 -6820 1/imm32/some-block-depth -6821 1/imm32/some-stack-offset -6822 0/imm32/no-register -6823 -6824 Two-args-int-stack-int-reg: -6825 Int-var-in-mem/imm32 -6826 Single-int-var-in-some-register/imm32/next -6827 -6828 Two-args-int-reg-int-stack: -6829 Int-var-in-some-register/imm32 -6830 Single-int-var-in-mem/imm32/next -6831 -6832 Two-args-int-eax-int-literal: -6833 Int-var-in-eax/imm32 -6834 Single-lit-var/imm32/next -6835 -6836 Int-var-and-literal: -6837 Int-var-in-mem/imm32 -6838 Single-lit-var/imm32/next -6839 -6840 Int-var-in-register-and-literal: -6841 Int-var-in-some-register/imm32 -6842 Single-lit-var/imm32/next -6843 -6844 Single-int-var-in-some-register: -6845 Int-var-in-some-register/imm32 -6846 0/imm32/next -6847 -6848 Int-var-in-some-register: -6849 "arg1"/imm32/name -6850 Type-int/imm32 -6851 1/imm32/some-block-depth -6852 0/imm32/no-stack-offset -6853 Any-register/imm32 -6854 -6855 Single-int-var-in-eax: -6856 Int-var-in-eax/imm32 -6857 0/imm32/next -6858 -6859 Int-var-in-eax: -6860 "arg1"/imm32/name -6861 Type-int/imm32 -6862 1/imm32/some-block-depth -6863 0/imm32/no-stack-offset -6864 "eax"/imm32/register -6865 -6866 Single-int-var-in-ecx: -6867 Int-var-in-ecx/imm32 -6868 0/imm32/next -6869 -6870 Int-var-in-ecx: -6871 "arg1"/imm32/name -6872 Type-int/imm32 -6873 1/imm32/some-block-depth -6874 0/imm32/no-stack-offset -6875 "ecx"/imm32/register -6876 -6877 Single-int-var-in-edx: -6878 Int-var-in-edx/imm32 -6879 0/imm32/next -6880 -6881 Int-var-in-edx: -6882 "arg1"/imm32/name -6883 Type-int/imm32 -6884 1/imm32/some-block-depth -6885 0/imm32/no-stack-offset -6886 "edx"/imm32/register -6887 -6888 Single-int-var-in-ebx: -6889 Int-var-in-ebx/imm32 -6890 0/imm32/next -6891 -6892 Int-var-in-ebx: -6893 "arg1"/imm32/name -6894 Type-int/imm32 -6895 1/imm32/some-block-depth -6896 0/imm32/no-stack-offset -6897 "ebx"/imm32/register -6898 -6899 Single-int-var-in-esi: -6900 Int-var-in-esi/imm32 -6901 0/imm32/next -6902 -6903 Int-var-in-esi: -6904 "arg1"/imm32/name -6905 Type-int/imm32 -6906 1/imm32/some-block-depth -6907 0/imm32/no-stack-offset -6908 "esi"/imm32/register -6909 -6910 Single-int-var-in-edi: -6911 Int-var-in-edi/imm32 -6912 0/imm32/next -6913 -6914 Int-var-in-edi: -6915 "arg1"/imm32/name -6916 Type-int/imm32 -6917 1/imm32/some-block-depth -6918 0/imm32/no-stack-offset -6919 "edi"/imm32/register +6811 _Primitive-loop-if-addr<=-named/imm32/next +6812 _Primitive-loop-if-addr<=-named: +6813 "loop-if-addr<="/imm32/name +6814 Single-lit-var/imm32/inouts +6815 0/imm32/outputs +6816 "0f 86/jump-if-addr<="/imm32/subx-name +6817 0/imm32/no-rm32 +6818 0/imm32/no-r32 +6819 0/imm32/no-imm32 +6820 1/imm32/disp32-is-first-inout +6821 0/imm32/no-output +6822 _Primitive-loop-if-addr>-named/imm32/next +6823 _Primitive-loop-if-addr>-named: +6824 "loop-if-addr>"/imm32/name +6825 Single-lit-var/imm32/inouts +6826 0/imm32/outputs +6827 "0f 87/jump-if-addr>"/imm32/subx-name +6828 0/imm32/no-rm32 +6829 0/imm32/no-r32 +6830 0/imm32/no-imm32 +6831 1/imm32/disp32-is-first-inout +6832 0/imm32/no-output +6833 _Primitive-loop-if-<-named/imm32/next +6834 _Primitive-loop-if-<-named: +6835 "loop-if-<"/imm32/name +6836 Single-lit-var/imm32/inouts +6837 0/imm32/outputs +6838 "0f 8c/jump-if-<"/imm32/subx-name +6839 0/imm32/no-rm32 +6840 0/imm32/no-r32 +6841 0/imm32/no-imm32 +6842 1/imm32/disp32-is-first-inout +6843 0/imm32/no-output +6844 _Primitive-loop-if->=-named/imm32/next +6845 _Primitive-loop-if->=-named: +6846 "loop-if->="/imm32/name +6847 Single-lit-var/imm32/inouts +6848 0/imm32/outputs +6849 "0f 8d/jump-if->="/imm32/subx-name +6850 0/imm32/no-rm32 +6851 0/imm32/no-r32 +6852 0/imm32/no-imm32 +6853 1/imm32/disp32-is-first-inout +6854 0/imm32/no-output +6855 _Primitive-loop-if-<=-named/imm32/next +6856 _Primitive-loop-if-<=-named: +6857 "loop-if-<="/imm32/name +6858 Single-lit-var/imm32/inouts +6859 0/imm32/outputs +6860 "0f 8e/jump-if-<="/imm32/subx-name +6861 0/imm32/no-rm32 +6862 0/imm32/no-r32 +6863 0/imm32/no-imm32 +6864 1/imm32/disp32-is-first-inout +6865 0/imm32/no-output +6866 _Primitive-loop-if->-named/imm32/next +6867 _Primitive-loop-if->-named: +6868 "loop-if->"/imm32/name +6869 Single-lit-var/imm32/inouts +6870 0/imm32/outputs +6871 "0f 8f/jump-if->"/imm32/subx-name +6872 0/imm32/no-rm32 +6873 0/imm32/no-r32 +6874 0/imm32/no-imm32 +6875 1/imm32/disp32-is-first-inout +6876 0/imm32/no-output +6877 _Primitive-loop-named/imm32/next # we probably don't need an unconditional break +6878 _Primitive-loop-named: +6879 "loop"/imm32/name +6880 Single-lit-var/imm32/inouts +6881 0/imm32/outputs +6882 "e9/jump"/imm32/subx-name +6883 0/imm32/no-rm32 +6884 0/imm32/no-r32 +6885 0/imm32/no-imm32 +6886 1/imm32/disp32-is-first-inout +6887 0/imm32/no-output +6888 0/imm32/next +6889 +6890 Single-int-var-in-mem: +6891 Int-var-in-mem/imm32 +6892 0/imm32/next +6893 +6894 Int-var-in-mem: +6895 "arg1"/imm32/name +6896 Type-int/imm32 +6897 1/imm32/some-block-depth +6898 1/imm32/some-stack-offset +6899 0/imm32/no-register +6900 +6901 Two-args-int-stack-int-reg: +6902 Int-var-in-mem/imm32 +6903 Single-int-var-in-some-register/imm32/next +6904 +6905 Two-args-int-reg-int-stack: +6906 Int-var-in-some-register/imm32 +6907 Single-int-var-in-mem/imm32/next +6908 +6909 Two-args-int-eax-int-literal: +6910 Int-var-in-eax/imm32 +6911 Single-lit-var/imm32/next +6912 +6913 Int-var-and-literal: +6914 Int-var-in-mem/imm32 +6915 Single-lit-var/imm32/next +6916 +6917 Int-var-in-register-and-literal: +6918 Int-var-in-some-register/imm32 +6919 Single-lit-var/imm32/next 6920 -6921 Single-lit-var: -6922 Lit-var/imm32 +6921 Single-int-var-in-some-register: +6922 Int-var-in-some-register/imm32 6923 0/imm32/next 6924 -6925 Lit-var: -6926 "literal"/imm32/name -6927 Type-literal/imm32 +6925 Int-var-in-some-register: +6926 "arg1"/imm32/name +6927 Type-int/imm32 6928 1/imm32/some-block-depth 6929 0/imm32/no-stack-offset -6930 0/imm32/no-register +6930 Any-register/imm32 6931 -6932 Type-int: -6933 1/imm32/left/int -6934 0/imm32/right/null +6932 Single-int-var-in-eax: +6933 Int-var-in-eax/imm32 +6934 0/imm32/next 6935 -6936 Type-literal: -6937 0/imm32/left/literal -6938 0/imm32/right/null -6939 -6940 == code -6941 emit-subx-primitive: # out: (addr buffered-file), stmt: (handle statement), primitive: (handle function) -6942 # . prologue -6943 55/push-ebp -6944 89/<- %ebp 4/r32/esp -6945 # . save registers -6946 50/push-eax -6947 51/push-ecx -6948 # ecx = primitive -6949 8b/-> *(ebp+0x10) 1/r32/ecx -6950 # emit primitive name -6951 (emit-indent *(ebp+8) *Curr-block-depth) -6952 (write-buffered *(ebp+8) *(ecx+0xc)) # Primitive-subx-name -6953 # emit rm32 if necessary -6954 (emit-subx-rm32 *(ebp+8) *(ecx+0x10) *(ebp+0xc)) # out, Primitive-subx-rm32, stmt -6955 # emit r32 if necessary -6956 (emit-subx-r32 *(ebp+8) *(ecx+0x14) *(ebp+0xc)) # out, Primitive-subx-r32, stmt -6957 # emit imm32 if necessary -6958 (emit-subx-imm32 *(ebp+8) *(ecx+0x18) *(ebp+0xc)) # out, Primitive-subx-imm32, stmt -6959 # emit disp32 if necessary -6960 (emit-subx-disp32 *(ebp+8) *(ecx+0x1c) *(ebp+0xc)) # out, Primitive-subx-disp32, stmt -6961 (write-buffered *(ebp+8) Newline) -6962 $emit-subx-primitive:end: -6963 # . restore registers -6964 59/pop-to-ecx -6965 58/pop-to-eax -6966 # . epilogue -6967 89/<- %esp 5/r32/ebp -6968 5d/pop-to-ebp -6969 c3/return -6970 -6971 emit-subx-rm32: # out: (addr buffered-file), l: arg-location, stmt: (handle statement) -6972 # . prologue -6973 55/push-ebp -6974 89/<- %ebp 4/r32/esp -6975 # . save registers -6976 50/push-eax -6977 # if (l == 0) return -6978 81 7/subop/compare *(ebp+0xc) 0/imm32 -6979 74/jump-if-= $emit-subx-rm32:end/disp8 -6980 # var v/eax: (handle var) -6981 (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc)) # => eax -6982 (emit-subx-var-as-rm32 *(ebp+8) %eax) -6983 $emit-subx-rm32:end: -6984 # . restore registers -6985 58/pop-to-eax -6986 # . epilogue -6987 89/<- %esp 5/r32/ebp -6988 5d/pop-to-ebp -6989 c3/return +6936 Int-var-in-eax: +6937 "arg1"/imm32/name +6938 Type-int/imm32 +6939 1/imm32/some-block-depth +6940 0/imm32/no-stack-offset +6941 "eax"/imm32/register +6942 +6943 Single-int-var-in-ecx: +6944 Int-var-in-ecx/imm32 +6945 0/imm32/next +6946 +6947 Int-var-in-ecx: +6948 "arg1"/imm32/name +6949 Type-int/imm32 +6950 1/imm32/some-block-depth +6951 0/imm32/no-stack-offset +6952 "ecx"/imm32/register +6953 +6954 Single-int-var-in-edx: +6955 Int-var-in-edx/imm32 +6956 0/imm32/next +6957 +6958 Int-var-in-edx: +6959 "arg1"/imm32/name +6960 Type-int/imm32 +6961 1/imm32/some-block-depth +6962 0/imm32/no-stack-offset +6963 "edx"/imm32/register +6964 +6965 Single-int-var-in-ebx: +6966 Int-var-in-ebx/imm32 +6967 0/imm32/next +6968 +6969 Int-var-in-ebx: +6970 "arg1"/imm32/name +6971 Type-int/imm32 +6972 1/imm32/some-block-depth +6973 0/imm32/no-stack-offset +6974 "ebx"/imm32/register +6975 +6976 Single-int-var-in-esi: +6977 Int-var-in-esi/imm32 +6978 0/imm32/next +6979 +6980 Int-var-in-esi: +6981 "arg1"/imm32/name +6982 Type-int/imm32 +6983 1/imm32/some-block-depth +6984 0/imm32/no-stack-offset +6985 "esi"/imm32/register +6986 +6987 Single-int-var-in-edi: +6988 Int-var-in-edi/imm32 +6989 0/imm32/next 6990 -6991 get-stmt-operand-from-arg-location: # stmt: (handle statement), l: arg-location -> var/eax: (handle stmt-var) -6992 # . prologue -6993 55/push-ebp -6994 89/<- %ebp 4/r32/esp -6995 # . save registers -6996 51/push-ecx -6997 # eax = l -6998 8b/-> *(ebp+0xc) 0/r32/eax -6999 # ecx = stmt -7000 8b/-> *(ebp+8) 1/r32/ecx -7001 # if (l == 1) return stmt->inouts -7002 { -7003 3d/compare-eax-and 1/imm32 -7004 75/jump-if-!= break/disp8 -7005 $get-stmt-operand-from-arg-location:1: -7006 8b/-> *(ecx+8) 0/r32/eax # Stmt1-inouts or Regvardef-inouts -7007 eb/jump $get-stmt-operand-from-arg-location:end/disp8 -7008 } -7009 # if (l == 2) return stmt->inouts->next -7010 { -7011 3d/compare-eax-and 2/imm32 -7012 75/jump-if-!= break/disp8 -7013 $get-stmt-operand-from-arg-location:2: -7014 8b/-> *(ecx+8) 0/r32/eax # Stmt1-inouts or Regvardef-inouts -7015 8b/-> *(eax+4) 0/r32/eax # Stmt-var-next -7016 eb/jump $get-stmt-operand-from-arg-location:end/disp8 -7017 } -7018 # if (l == 3) return stmt->outputs -7019 { -7020 3d/compare-eax-and 3/imm32 -7021 75/jump-if-!= break/disp8 -7022 $get-stmt-operand-from-arg-location:3: -7023 8b/-> *(ecx+0xc) 0/r32/eax # Stmt1-outputs -7024 eb/jump $get-stmt-operand-from-arg-location:end/disp8 -7025 } -7026 # abort -7027 e9/jump $get-stmt-operand-from-arg-location:abort/disp32 -7028 $get-stmt-operand-from-arg-location:end: -7029 # . restore registers -7030 59/pop-to-ecx -7031 # . epilogue -7032 89/<- %esp 5/r32/ebp -7033 5d/pop-to-ebp -7034 c3/return -7035 -7036 $get-stmt-operand-from-arg-location:abort: -7037 # error("invalid arg-location " eax) -7038 (write-buffered Stderr "invalid arg-location ") -7039 (print-int32-buffered Stderr %eax) -7040 (write-buffered Stderr Newline) -7041 (flush Stderr) -7042 # . syscall(exit, 1) -7043 bb/copy-to-ebx 1/imm32 -7044 b8/copy-to-eax 1/imm32/exit -7045 cd/syscall 0x80/imm8 -7046 # never gets here +6991 Int-var-in-edi: +6992 "arg1"/imm32/name +6993 Type-int/imm32 +6994 1/imm32/some-block-depth +6995 0/imm32/no-stack-offset +6996 "edi"/imm32/register +6997 +6998 Single-lit-var: +6999 Lit-var/imm32 +7000 0/imm32/next +7001 +7002 Lit-var: +7003 "literal"/imm32/name +7004 Type-literal/imm32 +7005 1/imm32/some-block-depth +7006 0/imm32/no-stack-offset +7007 0/imm32/no-register +7008 +7009 Type-int: +7010 1/imm32/left/int +7011 0/imm32/right/null +7012 +7013 Type-literal: +7014 0/imm32/left/literal +7015 0/imm32/right/null +7016 +7017 == code +7018 emit-subx-primitive: # out: (addr buffered-file), stmt: (handle statement), primitive: (handle function) +7019 # . prologue +7020 55/push-ebp +7021 89/<- %ebp 4/r32/esp +7022 # . save registers +7023 50/push-eax +7024 51/push-ecx +7025 # ecx = primitive +7026 8b/-> *(ebp+0x10) 1/r32/ecx +7027 # emit primitive name +7028 (emit-indent *(ebp+8) *Curr-block-depth) +7029 (write-buffered *(ebp+8) *(ecx+0xc)) # Primitive-subx-name +7030 # emit rm32 if necessary +7031 (emit-subx-rm32 *(ebp+8) *(ecx+0x10) *(ebp+0xc)) # out, Primitive-subx-rm32, stmt +7032 # emit r32 if necessary +7033 (emit-subx-r32 *(ebp+8) *(ecx+0x14) *(ebp+0xc)) # out, Primitive-subx-r32, stmt +7034 # emit imm32 if necessary +7035 (emit-subx-imm32 *(ebp+8) *(ecx+0x18) *(ebp+0xc)) # out, Primitive-subx-imm32, stmt +7036 # emit disp32 if necessary +7037 (emit-subx-disp32 *(ebp+8) *(ecx+0x1c) *(ebp+0xc)) # out, Primitive-subx-disp32, stmt +7038 (write-buffered *(ebp+8) Newline) +7039 $emit-subx-primitive:end: +7040 # . restore registers +7041 59/pop-to-ecx +7042 58/pop-to-eax +7043 # . epilogue +7044 89/<- %esp 5/r32/ebp +7045 5d/pop-to-ebp +7046 c3/return 7047 -7048 emit-subx-r32: # out: (addr buffered-file), l: arg-location, stmt: (handle statement) +7048 emit-subx-rm32: # out: (addr buffered-file), l: arg-location, stmt: (handle statement) 7049 # . prologue 7050 55/push-ebp 7051 89/<- %ebp 4/r32/esp 7052 # . save registers 7053 50/push-eax -7054 51/push-ecx -7055 # if (location == 0) return -7056 81 7/subop/compare *(ebp+0xc) 0/imm32 -7057 0f 84/jump-if-= $emit-subx-r32:end/disp32 -7058 # var v/eax: (handle var) -7059 (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc)) # => eax -7060 8b/-> *eax 0/r32/eax # Stmt-var-value -7061 (maybe-get Registers *(eax+0x10) 8) # Var-register => eax: (addr register-index) -7062 (write-buffered *(ebp+8) Space) -7063 (print-int32-buffered *(ebp+8) *eax) -7064 (write-buffered *(ebp+8) "/r32") -7065 $emit-subx-r32:end: -7066 # . restore registers -7067 59/pop-to-ecx -7068 58/pop-to-eax -7069 # . epilogue -7070 89/<- %esp 5/r32/ebp -7071 5d/pop-to-ebp -7072 c3/return -7073 -7074 emit-subx-imm32: # out: (addr buffered-file), l: arg-location, stmt: (handle statement) -7075 # . prologue -7076 55/push-ebp -7077 89/<- %ebp 4/r32/esp -7078 # . save registers -7079 50/push-eax -7080 51/push-ecx -7081 # if (location == 0) return -7082 81 7/subop/compare *(ebp+0xc) 0/imm32 -7083 74/jump-if-= $emit-subx-imm32:end/disp8 -7084 # var v/eax: (handle var) -7085 (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc)) # => eax -7086 8b/-> *eax 0/r32/eax # Stmt-var-value -7087 (write-buffered *(ebp+8) Space) -7088 (write-buffered *(ebp+8) *eax) # Var-name -7089 (write-buffered *(ebp+8) "/imm32") -7090 $emit-subx-imm32:end: -7091 # . restore registers -7092 59/pop-to-ecx -7093 58/pop-to-eax -7094 # . epilogue -7095 89/<- %esp 5/r32/ebp -7096 5d/pop-to-ebp -7097 c3/return -7098 -7099 emit-subx-disp32: # out: (addr buffered-file), l: arg-location, stmt: (handle statement) -7100 # . prologue -7101 55/push-ebp -7102 89/<- %ebp 4/r32/esp -7103 # . save registers -7104 50/push-eax -7105 51/push-ecx -7106 # if (location == 0) return -7107 81 7/subop/compare *(ebp+0xc) 0/imm32 -7108 0f 84/jump-if-= $emit-subx-disp32:end/disp32 -7109 # var v/eax: (handle var) -7110 (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc)) # => eax -7111 8b/-> *eax 0/r32/eax # Stmt-var-value -7112 (write-buffered *(ebp+8) Space) -7113 (write-buffered *(ebp+8) *eax) # Var-name -7114 # hack: if instruction operation starts with "break", emit ":break" -7115 # var name/ecx: (addr array byte) = stmt->operation -7116 8b/-> *(ebp+0x10) 0/r32/eax -7117 8b/-> *(eax+4) 1/r32/ecx -7118 { -7119 (string-starts-with? %ecx "break") # => eax -7120 3d/compare-eax-and 0/imm32/false -7121 74/jump-if-= break/disp8 -7122 (write-buffered *(ebp+8) ":break") -7123 } -7124 # hack: if instruction operation starts with "loop", emit ":loop" -7125 { -7126 (string-starts-with? %ecx "loop") # => eax -7127 3d/compare-eax-and 0/imm32/false -7128 74/jump-if-= break/disp8 -7129 (write-buffered *(ebp+8) ":loop") -7130 } -7131 (write-buffered *(ebp+8) "/disp32") -7132 $emit-subx-disp32:end: -7133 # . restore registers -7134 59/pop-to-ecx -7135 58/pop-to-eax -7136 # . epilogue -7137 89/<- %esp 5/r32/ebp -7138 5d/pop-to-ebp -7139 c3/return -7140 -7141 emit-subx-call: # out: (addr buffered-file), stmt: (handle statement), callee: (handle function) -7142 # . prologue -7143 55/push-ebp -7144 89/<- %ebp 4/r32/esp -7145 # . save registers -7146 51/push-ecx -7147 # -7148 (emit-indent *(ebp+8) *Curr-block-depth) -7149 (write-buffered *(ebp+8) "(") -7150 # - emit function name -7151 8b/-> *(ebp+0x10) 1/r32/ecx -7152 (write-buffered *(ebp+8) *(ecx+4)) # Function-subx-name -7153 # - emit arguments -7154 # var curr/ecx: (handle stmt-var) = stmt->inouts -7155 8b/-> *(ebp+0xc) 1/r32/ecx -7156 8b/-> *(ecx+8) 1/r32/ecx # Stmt1-inouts -7157 { -7158 # if (curr == null) break -7159 81 7/subop/compare %ecx 0/imm32 -7160 74/jump-if-= break/disp8 -7161 # -7162 (emit-subx-call-operand *(ebp+8) %ecx) -7163 # curr = curr->next -7164 8b/-> *(ecx+4) 1/r32/ecx # Stmt-var-next -7165 eb/jump loop/disp8 -7166 } -7167 # -7168 (write-buffered *(ebp+8) ")\n") -7169 $emit-subx-call:end: -7170 # . restore registers -7171 59/pop-to-ecx -7172 # . epilogue -7173 89/<- %esp 5/r32/ebp -7174 5d/pop-to-ebp -7175 c3/return -7176 -7177 # like a function call, except we have no idea what function it is -7178 # we hope it's defined in SubX and that the types are ok -7179 emit-hailmary-call: # out: (addr buffered-file), stmt: (handle statement) -7180 # . prologue -7181 55/push-ebp -7182 89/<- %ebp 4/r32/esp -7183 # . save registers -7184 51/push-ecx -7185 # -7186 (emit-indent *(ebp+8) *Curr-block-depth) -7187 (write-buffered *(ebp+8) "(") -7188 # ecx = stmt -7189 8b/-> *(ebp+0xc) 1/r32/ecx -7190 # - emit function name -7191 (write-buffered *(ebp+8) *(ecx+4)) # Stmt1-operation -7192 # - emit arguments -7193 # var curr/ecx: (handle stmt-var) = stmt->inouts -7194 8b/-> *(ecx+8) 1/r32/ecx # Stmt1-inouts +7054 # if (l == 0) return +7055 81 7/subop/compare *(ebp+0xc) 0/imm32 +7056 74/jump-if-= $emit-subx-rm32:end/disp8 +7057 # var v/eax: (handle var) +7058 (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc)) # => eax +7059 (emit-subx-var-as-rm32 *(ebp+8) %eax) +7060 $emit-subx-rm32:end: +7061 # . restore registers +7062 58/pop-to-eax +7063 # . epilogue +7064 89/<- %esp 5/r32/ebp +7065 5d/pop-to-ebp +7066 c3/return +7067 +7068 get-stmt-operand-from-arg-location: # stmt: (handle statement), l: arg-location -> var/eax: (handle stmt-var) +7069 # . prologue +7070 55/push-ebp +7071 89/<- %ebp 4/r32/esp +7072 # . save registers +7073 51/push-ecx +7074 # eax = l +7075 8b/-> *(ebp+0xc) 0/r32/eax +7076 # ecx = stmt +7077 8b/-> *(ebp+8) 1/r32/ecx +7078 # if (l == 1) return stmt->inouts +7079 { +7080 3d/compare-eax-and 1/imm32 +7081 75/jump-if-!= break/disp8 +7082 $get-stmt-operand-from-arg-location:1: +7083 8b/-> *(ecx+8) 0/r32/eax # Stmt1-inouts or Regvardef-inouts +7084 eb/jump $get-stmt-operand-from-arg-location:end/disp8 +7085 } +7086 # if (l == 2) return stmt->inouts->next +7087 { +7088 3d/compare-eax-and 2/imm32 +7089 75/jump-if-!= break/disp8 +7090 $get-stmt-operand-from-arg-location:2: +7091 8b/-> *(ecx+8) 0/r32/eax # Stmt1-inouts or Regvardef-inouts +7092 8b/-> *(eax+4) 0/r32/eax # Stmt-var-next +7093 eb/jump $get-stmt-operand-from-arg-location:end/disp8 +7094 } +7095 # if (l == 3) return stmt->outputs +7096 { +7097 3d/compare-eax-and 3/imm32 +7098 75/jump-if-!= break/disp8 +7099 $get-stmt-operand-from-arg-location:3: +7100 8b/-> *(ecx+0xc) 0/r32/eax # Stmt1-outputs +7101 eb/jump $get-stmt-operand-from-arg-location:end/disp8 +7102 } +7103 # abort +7104 e9/jump $get-stmt-operand-from-arg-location:abort/disp32 +7105 $get-stmt-operand-from-arg-location:end: +7106 # . restore registers +7107 59/pop-to-ecx +7108 # . epilogue +7109 89/<- %esp 5/r32/ebp +7110 5d/pop-to-ebp +7111 c3/return +7112 +7113 $get-stmt-operand-from-arg-location:abort: +7114 # error("invalid arg-location " eax) +7115 (write-buffered Stderr "invalid arg-location ") +7116 (print-int32-buffered Stderr %eax) +7117 (write-buffered Stderr Newline) +7118 (flush Stderr) +7119 # . syscall(exit, 1) +7120 bb/copy-to-ebx 1/imm32 +7121 b8/copy-to-eax 1/imm32/exit +7122 cd/syscall 0x80/imm8 +7123 # never gets here +7124 +7125 emit-subx-r32: # out: (addr buffered-file), l: arg-location, stmt: (handle statement) +7126 # . prologue +7127 55/push-ebp +7128 89/<- %ebp 4/r32/esp +7129 # . save registers +7130 50/push-eax +7131 51/push-ecx +7132 # if (location == 0) return +7133 81 7/subop/compare *(ebp+0xc) 0/imm32 +7134 0f 84/jump-if-= $emit-subx-r32:end/disp32 +7135 # var v/eax: (handle var) +7136 (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc)) # => eax +7137 8b/-> *eax 0/r32/eax # Stmt-var-value +7138 (maybe-get Registers *(eax+0x10) 8) # Var-register => eax: (addr register-index) +7139 (write-buffered *(ebp+8) Space) +7140 (print-int32-buffered *(ebp+8) *eax) +7141 (write-buffered *(ebp+8) "/r32") +7142 $emit-subx-r32:end: +7143 # . restore registers +7144 59/pop-to-ecx +7145 58/pop-to-eax +7146 # . epilogue +7147 89/<- %esp 5/r32/ebp +7148 5d/pop-to-ebp +7149 c3/return +7150 +7151 emit-subx-imm32: # out: (addr buffered-file), l: arg-location, stmt: (handle statement) +7152 # . prologue +7153 55/push-ebp +7154 89/<- %ebp 4/r32/esp +7155 # . save registers +7156 50/push-eax +7157 51/push-ecx +7158 # if (location == 0) return +7159 81 7/subop/compare *(ebp+0xc) 0/imm32 +7160 74/jump-if-= $emit-subx-imm32:end/disp8 +7161 # var v/eax: (handle var) +7162 (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc)) # => eax +7163 8b/-> *eax 0/r32/eax # Stmt-var-value +7164 (write-buffered *(ebp+8) Space) +7165 (write-buffered *(ebp+8) *eax) # Var-name +7166 (write-buffered *(ebp+8) "/imm32") +7167 $emit-subx-imm32:end: +7168 # . restore registers +7169 59/pop-to-ecx +7170 58/pop-to-eax +7171 # . epilogue +7172 89/<- %esp 5/r32/ebp +7173 5d/pop-to-ebp +7174 c3/return +7175 +7176 emit-subx-disp32: # out: (addr buffered-file), l: arg-location, stmt: (handle statement) +7177 # . prologue +7178 55/push-ebp +7179 89/<- %ebp 4/r32/esp +7180 # . save registers +7181 50/push-eax +7182 51/push-ecx +7183 # if (location == 0) return +7184 81 7/subop/compare *(ebp+0xc) 0/imm32 +7185 0f 84/jump-if-= $emit-subx-disp32:end/disp32 +7186 # var v/eax: (handle var) +7187 (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc)) # => eax +7188 8b/-> *eax 0/r32/eax # Stmt-var-value +7189 (write-buffered *(ebp+8) Space) +7190 (write-buffered *(ebp+8) *eax) # Var-name +7191 # hack: if instruction operation starts with "break", emit ":break" +7192 # var name/ecx: (addr array byte) = stmt->operation +7193 8b/-> *(ebp+0x10) 0/r32/eax +7194 8b/-> *(eax+4) 1/r32/ecx 7195 { -7196 # if (curr == null) break -7197 81 7/subop/compare %ecx 0/imm32 +7196 (string-starts-with? %ecx "break") # => eax +7197 3d/compare-eax-and 0/imm32/false 7198 74/jump-if-= break/disp8 -7199 # -7200 (emit-subx-call-operand *(ebp+8) %ecx) -7201 # curr = curr->next -7202 8b/-> *(ecx+4) 1/r32/ecx # Stmt-var-next -7203 eb/jump loop/disp8 -7204 } -7205 # -7206 (write-buffered *(ebp+8) ")\n") -7207 $emit-hailmary-call:end: -7208 # . restore registers -7209 59/pop-to-ecx -7210 # . epilogue -7211 89/<- %esp 5/r32/ebp -7212 5d/pop-to-ebp -7213 c3/return -7214 -7215 emit-subx-call-operand: # out: (addr buffered-file), s: (handle stmt-var) -7216 # shares code with emit-subx-var-as-rm32 -7217 # . prologue -7218 55/push-ebp -7219 89/<- %ebp 4/r32/esp -7220 # . save registers -7221 50/push-eax -7222 51/push-ecx -7223 56/push-esi -7224 # ecx = s -7225 8b/-> *(ebp+0xc) 1/r32/ecx -7226 # var operand/esi: (handle var) = s->value -7227 8b/-> *ecx 6/r32/esi # Stmt-var-value -7228 # if (operand->register) emit "%__" -7229 { -7230 81 7/subop/compare *(esi+0x10) 0/imm32 # Var-register -7231 74/jump-if-= break/disp8 -7232 $emit-subx-call-operand:register: -7233 (write-buffered *(ebp+8) " %") -7234 (write-buffered *(ebp+8) *(esi+0x10)) # Var-register -7235 e9/jump $emit-subx-call-operand:end/disp32 -7236 } -7237 # else if (operand->stack-offset) emit "*(ebp+__)" -7238 { -7239 81 7/subop/compare *(esi+0xc) 0/imm32 # Var-stack-offset -7240 74/jump-if-= break/disp8 -7241 $emit-subx-call-operand:stack: -7242 (write-buffered *(ebp+8) Space) -7243 (write-buffered *(ebp+8) "*(ebp+") -7244 (print-int32-buffered *(ebp+8) *(esi+0xc)) # Var-stack-offset -7245 (write-buffered *(ebp+8) ")") -7246 e9/jump $emit-subx-call-operand:end/disp32 -7247 } -7248 # else if (operand->type == literal) emit "__" -7249 { -7250 8b/-> *(esi+4) 0/r32/eax # Var-type -7251 81 7/subop/compare *eax 0/imm32 # Tree-left -7252 75/jump-if-!= break/disp8 -7253 $emit-subx-call-operand:literal: -7254 (write-buffered *(ebp+8) Space) -7255 (write-buffered *(ebp+8) *esi) -7256 } -7257 $emit-subx-call-operand:end: -7258 # . restore registers -7259 5e/pop-to-esi -7260 59/pop-to-ecx -7261 58/pop-to-eax -7262 # . epilogue -7263 89/<- %esp 5/r32/ebp -7264 5d/pop-to-ebp -7265 c3/return -7266 -7267 emit-subx-var-as-rm32: # out: (addr buffered-file), s: (handle stmt-var) -7268 # . prologue -7269 55/push-ebp -7270 89/<- %ebp 4/r32/esp -7271 # . save registers -7272 50/push-eax -7273 51/push-ecx -7274 56/push-esi -7275 # ecx = s -7276 8b/-> *(ebp+0xc) 1/r32/ecx -7277 # var operand/esi: (handle var) = s->value -7278 8b/-> *ecx 6/r32/esi # Stmt-var-value -7279 # if (operand->register && s->is-deref?) emit "*__" -7280 { -7281 81 7/subop/compare *(esi+0x10) 0/imm32 # Var-register -7282 74/jump-if-= break/disp8 -7283 81 7/subop/compare *(ecx+8) 0/imm32/false # Stmt-var-is-deref -7284 74/jump-if-= break/disp8 -7285 $emit-subx-var-as-rm32:register-indirect: -7286 (write-buffered *(ebp+8) " *") -7287 (write-buffered *(ebp+8) *(esi+0x10)) # Var-register -7288 } -7289 # if (operand->register && !s->is-deref?) emit "%__" -7290 { -7291 81 7/subop/compare *(esi+0x10) 0/imm32 # Var-register -7292 74/jump-if-= break/disp8 -7293 81 7/subop/compare *(ecx+8) 0/imm32/false # Stmt-var-is-deref -7294 75/jump-if-!= break/disp8 -7295 $emit-subx-var-as-rm32:register-direct: -7296 (write-buffered *(ebp+8) " %") -7297 (write-buffered *(ebp+8) *(esi+0x10)) # Var-register -7298 } -7299 # else if (operand->stack-offset) emit "*(ebp+__)" -7300 { -7301 81 7/subop/compare *(esi+0xc) 0/imm32 # Var-stack-offset -7302 74/jump-if-= break/disp8 -7303 $emit-subx-var-as-rm32:stack: -7304 (write-buffered *(ebp+8) Space) -7305 (write-buffered *(ebp+8) "*(ebp+") -7306 (print-int32-buffered *(ebp+8) *(esi+0xc)) # Var-stack-offset -7307 (write-buffered *(ebp+8) ")") -7308 } -7309 $emit-subx-var-as-rm32:end: -7310 # . restore registers -7311 5e/pop-to-esi -7312 59/pop-to-ecx -7313 58/pop-to-eax -7314 # . epilogue -7315 89/<- %esp 5/r32/ebp -7316 5d/pop-to-ebp -7317 c3/return -7318 -7319 find-matching-function: # functions: (addr function), stmt: (handle statement) -> result/eax: (handle function) -7320 # . prologue -7321 55/push-ebp -7322 89/<- %ebp 4/r32/esp -7323 # . save registers -7324 51/push-ecx -7325 # var curr/ecx: (handle function) = functions -7326 8b/-> *(ebp+8) 1/r32/ecx -7327 { -7328 # if (curr == null) break -7329 81 7/subop/compare %ecx 0/imm32 -7330 74/jump-if-= break/disp8 -7331 # if match(stmt, curr) return curr -7332 { -7333 (mu-stmt-matches-function? *(ebp+0xc) %ecx) # => eax -7334 3d/compare-eax-and 0/imm32/false -7335 74/jump-if-= break/disp8 -7336 89/<- %eax 1/r32/ecx -7337 eb/jump $find-matching-function:end/disp8 -7338 } -7339 # curr = curr->next -7340 8b/-> *(ecx+0x14) 1/r32/ecx # Function-next -7341 eb/jump loop/disp8 -7342 } -7343 # return null -7344 b8/copy-to-eax 0/imm32 -7345 $find-matching-function:end: -7346 # . restore registers -7347 59/pop-to-ecx -7348 # . epilogue -7349 89/<- %esp 5/r32/ebp -7350 5d/pop-to-ebp -7351 c3/return -7352 -7353 find-matching-primitive: # primitives: (handle primitive), stmt: (handle statement) -> result/eax: (handle primitive) -7354 # . prologue -7355 55/push-ebp -7356 89/<- %ebp 4/r32/esp -7357 # . save registers -7358 51/push-ecx -7359 # var curr/ecx: (handle primitive) = primitives -7360 8b/-> *(ebp+8) 1/r32/ecx -7361 { -7362 $find-matching-primitive:loop: -7363 # if (curr == null) break -7364 81 7/subop/compare %ecx 0/imm32 -7365 0f 84/jump-if-= break/disp32 -7366 #? (write-buffered Stderr "prim: ") -7367 #? (write-buffered Stderr *ecx) # Primitive-name -7368 #? (write-buffered Stderr " => ") -7369 #? (write-buffered Stderr *(ecx+0xc)) # Primitive-subx-name -7370 #? (write-buffered Stderr Newline) -7371 #? (flush Stderr) -7372 # if match(curr, stmt) return curr -7373 { -7374 (mu-stmt-matches-primitive? *(ebp+0xc) %ecx) # => eax -7375 3d/compare-eax-and 0/imm32/false -7376 74/jump-if-= break/disp8 -7377 89/<- %eax 1/r32/ecx -7378 eb/jump $find-matching-primitive:end/disp8 -7379 } -7380 $find-matching-primitive:next-primitive: -7381 # curr = curr->next -7382 8b/-> *(ecx+0x24) 1/r32/ecx # Primitive-next -7383 e9/jump loop/disp32 -7384 } -7385 # return null -7386 b8/copy-to-eax 0/imm32 -7387 $find-matching-primitive:end: -7388 # . restore registers -7389 59/pop-to-ecx -7390 # . epilogue -7391 89/<- %esp 5/r32/ebp -7392 5d/pop-to-ebp -7393 c3/return -7394 -7395 mu-stmt-matches-function?: # stmt: (handle statement), function: (handle function) -> result/eax: boolean -7396 # . prologue -7397 55/push-ebp -7398 89/<- %ebp 4/r32/esp -7399 # . save registers -7400 51/push-ecx -7401 # return function->name == stmt->operation -7402 8b/-> *(ebp+8) 1/r32/ecx -7403 8b/-> *(ebp+0xc) 0/r32/eax -7404 (string-equal? *(ecx+4) *eax) # Stmt1-operation, Function-name => eax -7405 $mu-stmt-matches-function?:end: -7406 # . restore registers -7407 59/pop-to-ecx +7199 (write-buffered *(ebp+8) ":break") +7200 } +7201 # hack: if instruction operation starts with "loop", emit ":loop" +7202 { +7203 (string-starts-with? %ecx "loop") # => eax +7204 3d/compare-eax-and 0/imm32/false +7205 74/jump-if-= break/disp8 +7206 (write-buffered *(ebp+8) ":loop") +7207 } +7208 (write-buffered *(ebp+8) "/disp32") +7209 $emit-subx-disp32:end: +7210 # . restore registers +7211 59/pop-to-ecx +7212 58/pop-to-eax +7213 # . epilogue +7214 89/<- %esp 5/r32/ebp +7215 5d/pop-to-ebp +7216 c3/return +7217 +7218 emit-subx-call: # out: (addr buffered-file), stmt: (handle statement), callee: (handle function) +7219 # . prologue +7220 55/push-ebp +7221 89/<- %ebp 4/r32/esp +7222 # . save registers +7223 51/push-ecx +7224 # +7225 (emit-indent *(ebp+8) *Curr-block-depth) +7226 (write-buffered *(ebp+8) "(") +7227 # - emit function name +7228 8b/-> *(ebp+0x10) 1/r32/ecx +7229 (write-buffered *(ebp+8) *(ecx+4)) # Function-subx-name +7230 # - emit arguments +7231 # var curr/ecx: (handle stmt-var) = stmt->inouts +7232 8b/-> *(ebp+0xc) 1/r32/ecx +7233 8b/-> *(ecx+8) 1/r32/ecx # Stmt1-inouts +7234 { +7235 # if (curr == null) break +7236 81 7/subop/compare %ecx 0/imm32 +7237 74/jump-if-= break/disp8 +7238 # +7239 (emit-subx-call-operand *(ebp+8) %ecx) +7240 # curr = curr->next +7241 8b/-> *(ecx+4) 1/r32/ecx # Stmt-var-next +7242 eb/jump loop/disp8 +7243 } +7244 # +7245 (write-buffered *(ebp+8) ")\n") +7246 $emit-subx-call:end: +7247 # . restore registers +7248 59/pop-to-ecx +7249 # . epilogue +7250 89/<- %esp 5/r32/ebp +7251 5d/pop-to-ebp +7252 c3/return +7253 +7254 # like a function call, except we have no idea what function it is +7255 # we hope it's defined in SubX and that the types are ok +7256 emit-hailmary-call: # out: (addr buffered-file), stmt: (handle statement) +7257 # . prologue +7258 55/push-ebp +7259 89/<- %ebp 4/r32/esp +7260 # . save registers +7261 51/push-ecx +7262 # +7263 (emit-indent *(ebp+8) *Curr-block-depth) +7264 (write-buffered *(ebp+8) "(") +7265 # ecx = stmt +7266 8b/-> *(ebp+0xc) 1/r32/ecx +7267 # - emit function name +7268 (write-buffered *(ebp+8) *(ecx+4)) # Stmt1-operation +7269 # - emit arguments +7270 # var curr/ecx: (handle stmt-var) = stmt->inouts +7271 8b/-> *(ecx+8) 1/r32/ecx # Stmt1-inouts +7272 { +7273 # if (curr == null) break +7274 81 7/subop/compare %ecx 0/imm32 +7275 74/jump-if-= break/disp8 +7276 # +7277 (emit-subx-call-operand *(ebp+8) %ecx) +7278 # curr = curr->next +7279 8b/-> *(ecx+4) 1/r32/ecx # Stmt-var-next +7280 eb/jump loop/disp8 +7281 } +7282 # +7283 (write-buffered *(ebp+8) ")\n") +7284 $emit-hailmary-call:end: +7285 # . restore registers +7286 59/pop-to-ecx +7287 # . epilogue +7288 89/<- %esp 5/r32/ebp +7289 5d/pop-to-ebp +7290 c3/return +7291 +7292 emit-subx-call-operand: # out: (addr buffered-file), s: (handle stmt-var) +7293 # shares code with emit-subx-var-as-rm32 +7294 # . prologue +7295 55/push-ebp +7296 89/<- %ebp 4/r32/esp +7297 # . save registers +7298 50/push-eax +7299 51/push-ecx +7300 56/push-esi +7301 # ecx = s +7302 8b/-> *(ebp+0xc) 1/r32/ecx +7303 # var operand/esi: (handle var) = s->value +7304 8b/-> *ecx 6/r32/esi # Stmt-var-value +7305 # if (operand->register && s->is-deref?) emit "*__" +7306 { +7307 $emit-subx-call-operand:check-for-register-indirect: +7308 81 7/subop/compare *(esi+0x10) 0/imm32 # Var-register +7309 74/jump-if-= break/disp8 +7310 81 7/subop/compare *(ecx+8) 0/imm32/false # Stmt-var-is-deref +7311 74/jump-if-= break/disp8 +7312 $emit-subx-call-operand:register-indirect: +7313 (write-buffered *(ebp+8) " *") +7314 (write-buffered *(ebp+8) *(esi+0x10)) # Var-register +7315 e9/jump $emit-subx-call-operand:end/disp32 +7316 } +7317 # if (operand->register && !s->is-deref?) emit "%__" +7318 { +7319 $emit-subx-call-operand:check-for-register-direct: +7320 81 7/subop/compare *(esi+0x10) 0/imm32 # Var-register +7321 74/jump-if-= break/disp8 +7322 81 7/subop/compare *(ecx+8) 0/imm32/false # Stmt-var-is-deref +7323 75/jump-if-!= break/disp8 +7324 $emit-subx-call-operand:register-direct: +7325 (write-buffered *(ebp+8) " %") +7326 (write-buffered *(ebp+8) *(esi+0x10)) # Var-register +7327 e9/jump $emit-subx-call-operand:end/disp32 +7328 } +7329 # else if (operand->stack-offset) emit "*(ebp+__)" +7330 { +7331 81 7/subop/compare *(esi+0xc) 0/imm32 # Var-stack-offset +7332 74/jump-if-= break/disp8 +7333 $emit-subx-call-operand:stack: +7334 (write-buffered *(ebp+8) Space) +7335 (write-buffered *(ebp+8) "*(ebp+") +7336 (print-int32-buffered *(ebp+8) *(esi+0xc)) # Var-stack-offset +7337 (write-buffered *(ebp+8) ")") +7338 e9/jump $emit-subx-call-operand:end/disp32 +7339 } +7340 # else if (operand->type == literal) emit "__" +7341 { +7342 8b/-> *(esi+4) 0/r32/eax # Var-type +7343 81 7/subop/compare *eax 0/imm32 # Tree-left +7344 75/jump-if-!= break/disp8 +7345 $emit-subx-call-operand:literal: +7346 (write-buffered *(ebp+8) Space) +7347 (write-buffered *(ebp+8) *esi) +7348 } +7349 $emit-subx-call-operand:end: +7350 # . restore registers +7351 5e/pop-to-esi +7352 59/pop-to-ecx +7353 58/pop-to-eax +7354 # . epilogue +7355 89/<- %esp 5/r32/ebp +7356 5d/pop-to-ebp +7357 c3/return +7358 +7359 emit-subx-var-as-rm32: # out: (addr buffered-file), s: (handle stmt-var) +7360 # . prologue +7361 55/push-ebp +7362 89/<- %ebp 4/r32/esp +7363 # . save registers +7364 50/push-eax +7365 51/push-ecx +7366 56/push-esi +7367 # ecx = s +7368 8b/-> *(ebp+0xc) 1/r32/ecx +7369 # var operand/esi: (handle var) = s->value +7370 8b/-> *ecx 6/r32/esi # Stmt-var-value +7371 # if (operand->register && s->is-deref?) emit "*__" +7372 { +7373 $emit-subx-var-as-rm32:check-for-register-indirect: +7374 81 7/subop/compare *(esi+0x10) 0/imm32 # Var-register +7375 74/jump-if-= break/disp8 +7376 81 7/subop/compare *(ecx+8) 0/imm32/false # Stmt-var-is-deref +7377 74/jump-if-= break/disp8 +7378 $emit-subx-var-as-rm32:register-indirect: +7379 (write-buffered *(ebp+8) " *") +7380 (write-buffered *(ebp+8) *(esi+0x10)) # Var-register +7381 } +7382 # if (operand->register && !s->is-deref?) emit "%__" +7383 { +7384 $emit-subx-var-as-rm32:check-for-register-direct: +7385 81 7/subop/compare *(esi+0x10) 0/imm32 # Var-register +7386 74/jump-if-= break/disp8 +7387 81 7/subop/compare *(ecx+8) 0/imm32/false # Stmt-var-is-deref +7388 75/jump-if-!= break/disp8 +7389 $emit-subx-var-as-rm32:register-direct: +7390 (write-buffered *(ebp+8) " %") +7391 (write-buffered *(ebp+8) *(esi+0x10)) # Var-register +7392 } +7393 # else if (operand->stack-offset) emit "*(ebp+__)" +7394 { +7395 81 7/subop/compare *(esi+0xc) 0/imm32 # Var-stack-offset +7396 74/jump-if-= break/disp8 +7397 $emit-subx-var-as-rm32:stack: +7398 (write-buffered *(ebp+8) Space) +7399 (write-buffered *(ebp+8) "*(ebp+") +7400 (print-int32-buffered *(ebp+8) *(esi+0xc)) # Var-stack-offset +7401 (write-buffered *(ebp+8) ")") +7402 } +7403 $emit-subx-var-as-rm32:end: +7404 # . restore registers +7405 5e/pop-to-esi +7406 59/pop-to-ecx +7407 58/pop-to-eax 7408 # . epilogue 7409 89/<- %esp 5/r32/ebp 7410 5d/pop-to-ebp 7411 c3/return 7412 -7413 mu-stmt-matches-primitive?: # stmt: (handle statement), primitive: (handle primitive) -> result/eax: boolean -7414 # A mu stmt matches a primitive if the name matches, all the inout vars -7415 # match, and all the output vars match. -7416 # Vars match if types match and registers match. -7417 # In addition, a stmt output matches a primitive's output if types match -7418 # and the primitive has a wildcard register. -7419 # . prologue -7420 55/push-ebp -7421 89/<- %ebp 4/r32/esp -7422 # . save registers -7423 51/push-ecx -7424 52/push-edx -7425 53/push-ebx -7426 56/push-esi -7427 57/push-edi -7428 # ecx = stmt -7429 8b/-> *(ebp+8) 1/r32/ecx -7430 # edx = primitive -7431 8b/-> *(ebp+0xc) 2/r32/edx -7432 { -7433 $mu-stmt-matches-primitive?:check-name: -7434 # if (primitive->name != stmt->operation) return false -7435 (string-equal? *(ecx+4) *edx) # Stmt1-operation, Primitive-name => eax -7436 3d/compare-eax-and 0/imm32/false -7437 75/jump-if-!= break/disp8 -7438 b8/copy-to-eax 0/imm32 -7439 e9/jump $mu-stmt-matches-primitive?:end/disp32 -7440 } -7441 $mu-stmt-matches-primitive?:check-inouts: -7442 # for (curr/esi in stmt->inouts, curr2/edi in primitive->inouts) -7443 8b/-> *(ecx+8) 6/r32/esi # Stmt1-inouts or Regvardef-inouts -7444 8b/-> *(edx+4) 7/r32/edi # Primitive-inouts -7445 { -7446 # if (curr == 0 && curr2 == 0) move on to check outputs -7447 { -7448 81 7/subop/compare %esi 0/imm32 -7449 75/jump-if-!= break/disp8 -7450 $mu-stmt-matches-primitive?:stmt-inout-is-null: -7451 { -7452 81 7/subop/compare %edi 0/imm32 -7453 75/jump-if-!= break/disp8 -7454 # -7455 e9/jump $mu-stmt-matches-primitive?:check-outputs/disp32 -7456 } -7457 # return false -7458 b8/copy-to-eax 0/imm32/false -7459 e9/jump $mu-stmt-matches-primitive?:end/disp32 -7460 } -7461 # if (curr2 == 0) return false -7462 { -7463 81 7/subop/compare %edi 0/imm32 -7464 75/jump-if-!= break/disp8 -7465 $mu-stmt-matches-primitive?:prim-inout-is-null: -7466 b8/copy-to-eax 0/imm32/false -7467 e9/jump $mu-stmt-matches-primitive?:end/disp32 -7468 } -7469 # if (curr != curr2) return false -7470 { -7471 (operand-matches-primitive? %esi *edi) # List-value => eax -7472 3d/compare-eax-and 0/imm32/false -7473 75/jump-if-!= break/disp8 -7474 b8/copy-to-eax 0/imm32/false -7475 e9/jump $mu-stmt-matches-primitive?:end/disp32 -7476 } -7477 # curr=curr->next -7478 8b/-> *(esi+4) 6/r32/esi # Stmt-var-next -7479 # curr2=curr2->next -7480 8b/-> *(edi+4) 7/r32/edi # Stmt-var-next -7481 eb/jump loop/disp8 -7482 } -7483 $mu-stmt-matches-primitive?:check-outputs: -7484 # for (curr/esi in stmt->outputs, curr2/edi in primitive->outputs) -7485 8b/-> *(ecx+0xc) 6/r32/esi # Stmt1-outputs -7486 8b/-> *(edx+8) 7/r32/edi # Primitive-outputs -7487 { -7488 # if (curr == 0) return (curr2 == 0) -7489 { -7490 $mu-stmt-matches-primitive?:check-output: -7491 81 7/subop/compare %esi 0/imm32 -7492 75/jump-if-!= break/disp8 -7493 { -7494 81 7/subop/compare %edi 0/imm32 -7495 75/jump-if-!= break/disp8 -7496 # return true -7497 b8/copy-to-eax 1/imm32 -7498 e9/jump $mu-stmt-matches-primitive?:end/disp32 -7499 } -7500 # return false -7501 b8/copy-to-eax 0/imm32 -7502 e9/jump $mu-stmt-matches-primitive?:end/disp32 -7503 } -7504 # if (curr2 == 0) return false -7505 { -7506 81 7/subop/compare %edi 0/imm32 -7507 75/jump-if-!= break/disp8 -7508 b8/copy-to-eax 0/imm32 -7509 e9/jump $mu-stmt-matches-primitive?:end/disp32 -7510 } -7511 # if (curr != curr2) return false -7512 { -7513 (operand-matches-primitive? %esi *edi) # List-value => eax -7514 3d/compare-eax-and 0/imm32/false -7515 75/jump-if-!= break/disp8 -7516 b8/copy-to-eax 0/imm32 -7517 e9/jump $mu-stmt-matches-primitive?:end/disp32 -7518 } -7519 # curr=curr->next -7520 8b/-> *(esi+4) 6/r32/esi # Stmt-var-next -7521 # curr2=curr2->next -7522 8b/-> *(edi+4) 7/r32/edi # Stmt-var-next -7523 eb/jump loop/disp8 -7524 } -7525 $mu-stmt-matches-primitive?:return-true: -7526 b8/copy-to-eax 1/imm32 -7527 $mu-stmt-matches-primitive?:end: -7528 # . restore registers -7529 5f/pop-to-edi -7530 5e/pop-to-esi -7531 5b/pop-to-ebx -7532 5a/pop-to-edx -7533 59/pop-to-ecx -7534 # . epilogue -7535 89/<- %esp 5/r32/ebp -7536 5d/pop-to-ebp -7537 c3/return -7538 -7539 operand-matches-primitive?: # s: (handle stmt-var), prim-var: (handle var) -> result/eax: boolean -7540 # . prologue -7541 55/push-ebp -7542 89/<- %ebp 4/r32/esp -7543 # . save registers -7544 51/push-ecx -7545 56/push-esi -7546 57/push-edi -7547 # ecx = s -7548 8b/-> *(ebp+8) 1/r32/ecx -7549 # var var/esi : (handle var) = s->value -7550 8b/-> *ecx 6/r32/esi # Stmt-var-value -7551 # edi = prim-var -7552 8b/-> *(ebp+0xc) 7/r32/edi -7553 $operand-matches-primitive?:check-type: -7554 # if (var->type != prim-var->type) return false -7555 (subx-type-equal? *(esi+4) *(edi+4)) # Var-type, Var-type => eax -7556 3d/compare-eax-and 0/imm32/false -7557 b8/copy-to-eax 0/imm32/false -7558 0f 84/jump-if-= $operand-matches-primitive?:end/disp32 -7559 { -7560 $operand-matches-primitive?:check-register: -7561 # if prim-var is in memory and var is in register but dereference, match -7562 { -7563 81 7/subop/compare *(edi+0x10) 0/imm32 # Var-register -7564 0f 85/jump-if-!= break/disp32 -7565 81 7/subop/compare *(esi+0x10) 0/imm32 # Var-register -7566 74/jump-if-= break/disp8 -7567 81 7/subop/compare *(ecx+8) 0/imm32/false # Stmt-var-is-deref -7568 74/jump-if-= break/disp8 -7569 e9/jump $operand-matches-primitive?:return-true/disp32 +7413 find-matching-function: # functions: (addr function), stmt: (handle statement) -> result/eax: (handle function) +7414 # . prologue +7415 55/push-ebp +7416 89/<- %ebp 4/r32/esp +7417 # . save registers +7418 51/push-ecx +7419 # var curr/ecx: (handle function) = functions +7420 8b/-> *(ebp+8) 1/r32/ecx +7421 { +7422 # if (curr == null) break +7423 81 7/subop/compare %ecx 0/imm32 +7424 74/jump-if-= break/disp8 +7425 # if match(stmt, curr) return curr +7426 { +7427 (mu-stmt-matches-function? *(ebp+0xc) %ecx) # => eax +7428 3d/compare-eax-and 0/imm32/false +7429 74/jump-if-= break/disp8 +7430 89/<- %eax 1/r32/ecx +7431 eb/jump $find-matching-function:end/disp8 +7432 } +7433 # curr = curr->next +7434 8b/-> *(ecx+0x14) 1/r32/ecx # Function-next +7435 eb/jump loop/disp8 +7436 } +7437 # return null +7438 b8/copy-to-eax 0/imm32 +7439 $find-matching-function:end: +7440 # . restore registers +7441 59/pop-to-ecx +7442 # . epilogue +7443 89/<- %esp 5/r32/ebp +7444 5d/pop-to-ebp +7445 c3/return +7446 +7447 find-matching-primitive: # primitives: (handle primitive), stmt: (handle statement) -> result/eax: (handle primitive) +7448 # . prologue +7449 55/push-ebp +7450 89/<- %ebp 4/r32/esp +7451 # . save registers +7452 51/push-ecx +7453 # var curr/ecx: (handle primitive) = primitives +7454 8b/-> *(ebp+8) 1/r32/ecx +7455 { +7456 $find-matching-primitive:loop: +7457 # if (curr == null) break +7458 81 7/subop/compare %ecx 0/imm32 +7459 0f 84/jump-if-= break/disp32 +7460 #? (write-buffered Stderr "prim: ") +7461 #? (write-buffered Stderr *ecx) # Primitive-name +7462 #? (write-buffered Stderr " => ") +7463 #? (write-buffered Stderr *(ecx+0xc)) # Primitive-subx-name +7464 #? (write-buffered Stderr Newline) +7465 #? (flush Stderr) +7466 # if match(curr, stmt) return curr +7467 { +7468 (mu-stmt-matches-primitive? *(ebp+0xc) %ecx) # => eax +7469 3d/compare-eax-and 0/imm32/false +7470 74/jump-if-= break/disp8 +7471 89/<- %eax 1/r32/ecx +7472 eb/jump $find-matching-primitive:end/disp8 +7473 } +7474 $find-matching-primitive:next-primitive: +7475 # curr = curr->next +7476 8b/-> *(ecx+0x24) 1/r32/ecx # Primitive-next +7477 e9/jump loop/disp32 +7478 } +7479 # return null +7480 b8/copy-to-eax 0/imm32 +7481 $find-matching-primitive:end: +7482 # . restore registers +7483 59/pop-to-ecx +7484 # . epilogue +7485 89/<- %esp 5/r32/ebp +7486 5d/pop-to-ebp +7487 c3/return +7488 +7489 mu-stmt-matches-function?: # stmt: (handle statement), function: (handle function) -> result/eax: boolean +7490 # . prologue +7491 55/push-ebp +7492 89/<- %ebp 4/r32/esp +7493 # . save registers +7494 51/push-ecx +7495 # return function->name == stmt->operation +7496 8b/-> *(ebp+8) 1/r32/ecx +7497 8b/-> *(ebp+0xc) 0/r32/eax +7498 (string-equal? *(ecx+4) *eax) # Stmt1-operation, Function-name => eax +7499 $mu-stmt-matches-function?:end: +7500 # . restore registers +7501 59/pop-to-ecx +7502 # . epilogue +7503 89/<- %esp 5/r32/ebp +7504 5d/pop-to-ebp +7505 c3/return +7506 +7507 mu-stmt-matches-primitive?: # stmt: (handle statement), primitive: (handle primitive) -> result/eax: boolean +7508 # A mu stmt matches a primitive if the name matches, all the inout vars +7509 # match, and all the output vars match. +7510 # Vars match if types match and registers match. +7511 # In addition, a stmt output matches a primitive's output if types match +7512 # and the primitive has a wildcard register. +7513 # . prologue +7514 55/push-ebp +7515 89/<- %ebp 4/r32/esp +7516 # . save registers +7517 51/push-ecx +7518 52/push-edx +7519 53/push-ebx +7520 56/push-esi +7521 57/push-edi +7522 # ecx = stmt +7523 8b/-> *(ebp+8) 1/r32/ecx +7524 # edx = primitive +7525 8b/-> *(ebp+0xc) 2/r32/edx +7526 { +7527 $mu-stmt-matches-primitive?:check-name: +7528 # if (primitive->name != stmt->operation) return false +7529 (string-equal? *(ecx+4) *edx) # Stmt1-operation, Primitive-name => eax +7530 3d/compare-eax-and 0/imm32/false +7531 75/jump-if-!= break/disp8 +7532 b8/copy-to-eax 0/imm32 +7533 e9/jump $mu-stmt-matches-primitive?:end/disp32 +7534 } +7535 $mu-stmt-matches-primitive?:check-inouts: +7536 # for (curr/esi in stmt->inouts, curr2/edi in primitive->inouts) +7537 8b/-> *(ecx+8) 6/r32/esi # Stmt1-inouts or Regvardef-inouts +7538 8b/-> *(edx+4) 7/r32/edi # Primitive-inouts +7539 { +7540 # if (curr == 0 && curr2 == 0) move on to check outputs +7541 { +7542 81 7/subop/compare %esi 0/imm32 +7543 75/jump-if-!= break/disp8 +7544 $mu-stmt-matches-primitive?:stmt-inout-is-null: +7545 { +7546 81 7/subop/compare %edi 0/imm32 +7547 75/jump-if-!= break/disp8 +7548 # +7549 e9/jump $mu-stmt-matches-primitive?:check-outputs/disp32 +7550 } +7551 # return false +7552 b8/copy-to-eax 0/imm32/false +7553 e9/jump $mu-stmt-matches-primitive?:end/disp32 +7554 } +7555 # if (curr2 == 0) return false +7556 { +7557 81 7/subop/compare %edi 0/imm32 +7558 75/jump-if-!= break/disp8 +7559 $mu-stmt-matches-primitive?:prim-inout-is-null: +7560 b8/copy-to-eax 0/imm32/false +7561 e9/jump $mu-stmt-matches-primitive?:end/disp32 +7562 } +7563 # if (curr != curr2) return false +7564 { +7565 (operand-matches-primitive? %esi *edi) # List-value => eax +7566 3d/compare-eax-and 0/imm32/false +7567 75/jump-if-!= break/disp8 +7568 b8/copy-to-eax 0/imm32/false +7569 e9/jump $mu-stmt-matches-primitive?:end/disp32 7570 } -7571 # if prim-var is in register and var is in register but dereference, no match -7572 { -7573 81 7/subop/compare *(edi+0x10) 0/imm32 # Var-register -7574 0f 84/jump-if-= break/disp32 -7575 81 7/subop/compare *(esi+0x10) 0/imm32 # Var-register -7576 0f 84/jump-if-= break/disp32 -7577 81 7/subop/compare *(ecx+8) 0/imm32/false # Stmt-var-is-deref -7578 74/jump-if-= break/disp8 -7579 e9/jump $operand-matches-primitive?:return-false/disp32 -7580 } -7581 # return false if var->register doesn't match prim-var->register -7582 { -7583 # if register addresses are equal, it's a match -7584 8b/-> *(esi+0x10) 0/r32/eax # Var-register -7585 39/compare *(edi+0x10) 0/r32/eax # Var-register -7586 74/jump-if-= break/disp8 -7587 # if either address is 0, return false -7588 3d/compare-eax-and 0/imm32 -7589 74/jump-if-= $operand-matches-primitive?:end/disp8 # eax goes from meaning var->register to result -7590 81 7/subop/compare *(edi+0x10) 0/imm32 # Var-register -7591 74/jump-if-= $operand-matches-primitive?:return-false/disp8 -7592 # if prim-var->register is wildcard, it's a match -7593 (string-equal? *(edi+0x10) Any-register) # Var-register => eax -7594 3d/compare-eax-and 0/imm32/false -7595 75/jump-if-!= break/disp8 -7596 # if string contents aren't equal, return false -7597 (string-equal? *(esi+0x10) *(edi+0x10)) # Var-register Var-register => eax -7598 3d/compare-eax-and 0/imm32/false -7599 74/jump-if-= $operand-matches-primitive?:return-false/disp8 -7600 } -7601 } -7602 $operand-matches-primitive?:return-true: -7603 b8/copy-to-eax 1/imm32/true -7604 eb/jump $operand-matches-primitive?:end/disp8 -7605 $operand-matches-primitive?:return-false: -7606 b8/copy-to-eax 0/imm32/false -7607 $operand-matches-primitive?:end: -7608 # . restore registers -7609 5f/pop-to-edi -7610 5e/pop-to-esi -7611 59/pop-to-ecx -7612 # . epilogue -7613 89/<- %esp 5/r32/ebp -7614 5d/pop-to-ebp -7615 c3/return -7616 -7617 subx-type-equal?: # a: (handle tree type-id), b: (handle tree type-id) -> result/eax: boolean -7618 # . prologue -7619 55/push-ebp -7620 89/<- %ebp 4/r32/esp -7621 # . save registers -7622 51/push-ecx -7623 # var alit/ecx: boolean = is-literal-type?(a) -7624 (is-literal-type? *(ebp+8)) # => eax -7625 89/<- %ecx 0/r32/eax -7626 # var blit/eax: boolean = is-literal-type?(b) -7627 (is-literal-type? *(ebp+0xc)) # => eax -7628 # return alit == blit -7629 39/compare %eax 1/r32/ecx -7630 74/jump-if-= $subx-type-equal?:true/disp8 -7631 $subx-type-equal?:false: -7632 b8/copy-to-eax 0/imm32/false -7633 eb/jump $subx-type-equal?:end/disp8 -7634 $subx-type-equal?:true: -7635 b8/copy-to-eax 1/imm32/true -7636 $subx-type-equal?:end: -7637 # . restore registers -7638 59/pop-to-ecx -7639 # . epilogue -7640 89/<- %esp 5/r32/ebp -7641 5d/pop-to-ebp -7642 c3/return -7643 -7644 is-literal-type?: # a: (handle tree type-id) -> result/eax: boolean -7645 # . prologue -7646 55/push-ebp -7647 89/<- %ebp 4/r32/esp -7648 # -7649 8b/-> *(ebp+8) 0/r32/eax -7650 8b/-> *eax 0/r32/eax # Atom-value -7651 3d/compare-eax-and 0/imm32/false -7652 74/jump-if-equal $is-literal-type?:end/disp8 -7653 b8/copy-to-eax 1/imm32/true -7654 $is-literal-type?:end: -7655 # . epilogue -7656 89/<- %esp 5/r32/ebp -7657 5d/pop-to-ebp -7658 c3/return -7659 -7660 test-emit-subx-statement-primitive: -7661 # Primitive operation on a variable on the stack. -7662 # increment foo -7663 # => -7664 # ff 0/subop/increment *(ebp-8) -7665 # -7666 # There's a variable on the var stack as follows: -7667 # name: 'foo' -7668 # type: int -7669 # stack-offset: -8 -7670 # -7671 # There's a primitive with this info: -7672 # name: 'increment' -7673 # inouts: int/mem -7674 # value: 'ff 0/subop/increment' -7675 # -7676 # There's nothing in functions. -7677 # -7678 # . prologue -7679 55/push-ebp -7680 89/<- %ebp 4/r32/esp -7681 # setup -7682 (clear-stream _test-output-stream) -7683 (clear-stream $_test-output-buffered-file->buffer) -7684 # var type/ecx: (handle tree type-id) = int -7685 68/push 0/imm32/right/null -7686 68/push 1/imm32/left/int -7687 89/<- %ecx 4/r32/esp -7688 # var var-foo/ecx: var -7689 68/push 0/imm32/no-register -7690 68/push -8/imm32/stack-offset -7691 68/push 1/imm32/block-depth -7692 51/push-ecx -7693 68/push "foo"/imm32 -7694 89/<- %ecx 4/r32/esp -7695 # var operand/ebx: (handle stmt-var) -7696 68/push 0/imm32/is-deref:false -7697 68/push 0/imm32/next -7698 51/push-ecx/var-foo -7699 89/<- %ebx 4/r32/esp -7700 # var stmt/esi: statement -7701 68/push 0/imm32/next -7702 68/push 0/imm32/outputs -7703 53/push-ebx/operands -7704 68/push "increment"/imm32/operation -7705 68/push 1/imm32 -7706 89/<- %esi 4/r32/esp -7707 # var primitives/ebx: primitive -7708 68/push 0/imm32/next -7709 68/push 0/imm32/output-is-write-only -7710 68/push 0/imm32/no-disp32 -7711 68/push 0/imm32/no-imm32 -7712 68/push 0/imm32/no-r32 -7713 68/push 1/imm32/rm32-is-first-inout -7714 68/push "ff 0/subop/increment"/imm32/subx-name -7715 68/push 0/imm32/outputs -7716 53/push-ebx/inouts # hack; in practice we won't have the same var in function definition and call -7717 68/push "increment"/imm32/name -7718 89/<- %ebx 4/r32/esp -7719 # convert -7720 c7 0/subop/copy *Curr-block-depth 0/imm32 -7721 (emit-subx-statement _test-output-buffered-file %esi %ebx 0) -7722 (flush _test-output-buffered-file) -7723 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -7729 # check output -7730 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment *(ebp+0xfffffff8)" "F - test-emit-subx-statement-primitive") -7731 # . epilogue -7732 89/<- %esp 5/r32/ebp -7733 5d/pop-to-ebp -7734 c3/return -7735 -7736 test-emit-subx-statement-primitive-register: -7737 # Primitive operation on a variable in a register. -7738 # foo <- increment -7739 # => -7740 # ff 0/subop/increment %eax # sub-optimal, but should suffice -7741 # -7742 # There's a variable on the var stack as follows: -7743 # name: 'foo' -7744 # type: int -7745 # register: 'eax' -7746 # -7747 # There's a primitive with this info: -7748 # name: 'increment' -7749 # out: int/reg -7750 # value: 'ff 0/subop/increment' -7751 # -7752 # There's nothing in functions. -7753 # -7754 # . prologue -7755 55/push-ebp -7756 89/<- %ebp 4/r32/esp -7757 # setup -7758 (clear-stream _test-output-stream) -7759 (clear-stream $_test-output-buffered-file->buffer) -7760 # var type/ecx: (handle tree type-id) = int -7761 68/push 0/imm32/right/null -7762 68/push 1/imm32/left/int -7763 89/<- %ecx 4/r32/esp -7764 # var var-foo/ecx: var in eax -7765 68/push "eax"/imm32/register -7766 68/push 0/imm32/no-stack-offset -7767 68/push 1/imm32/block-depth -7768 51/push-ecx -7769 68/push "foo"/imm32 -7770 89/<- %ecx 4/r32/esp -7771 # var operand/ebx: (handle stmt-var) -7772 68/push 0/imm32/is-deref:false -7773 68/push 0/imm32/next -7774 51/push-ecx/var-foo -7775 89/<- %ebx 4/r32/esp -7776 # var stmt/esi: statement -7777 68/push 0/imm32/next -7778 53/push-ebx/outputs -7779 68/push 0/imm32/inouts -7780 68/push "increment"/imm32/operation -7781 68/push 1/imm32 -7782 89/<- %esi 4/r32/esp -7783 # var formal-var/ebx: var in any register -7784 68/push Any-register/imm32 -7785 68/push 0/imm32/no-stack-offset -7786 68/push 1/imm32/block-depth -7787 ff 6/subop/push *(ecx+4) # Var-type -7788 68/push "dummy"/imm32 -7789 89/<- %ebx 4/r32/esp -7790 # var operand/ebx: (handle stmt-var) -7791 68/push 0/imm32/is-deref:false -7792 68/push 0/imm32/next -7793 53/push-ebx/formal-var -7794 89/<- %ebx 4/r32/esp -7795 # var primitives/ebx: primitive -7796 68/push 0/imm32/next -7797 68/push 0/imm32/output-is-write-only -7798 68/push 0/imm32/no-disp32 -7799 68/push 0/imm32/no-imm32 -7800 68/push 0/imm32/no-r32 -7801 68/push 3/imm32/rm32-in-first-output -7802 68/push "ff 0/subop/increment"/imm32/subx-name -7803 53/push-ebx/outputs -7804 68/push 0/imm32/inouts -7805 68/push "increment"/imm32/name -7806 89/<- %ebx 4/r32/esp -7807 # convert -7808 c7 0/subop/copy *Curr-block-depth 0/imm32 -7809 (emit-subx-statement _test-output-buffered-file %esi %ebx 0) -7810 (flush _test-output-buffered-file) -7811 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -7817 # check output -7818 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-statement-primitive-register") -7819 # . epilogue -7820 89/<- %esp 5/r32/ebp -7821 5d/pop-to-ebp -7822 c3/return -7823 -7824 test-emit-subx-statement-select-primitive: -7825 # Select the right primitive between overloads. -7826 # foo <- increment -7827 # => -7828 # ff 0/subop/increment %eax # sub-optimal, but should suffice -7829 # -7830 # There's a variable on the var stack as follows: -7831 # name: 'foo' -7832 # type: int -7833 # register: 'eax' -7834 # -7835 # There's two primitives, as follows: -7836 # - name: 'increment' -7837 # out: int/reg -7838 # value: 'ff 0/subop/increment' -7839 # - name: 'increment' -7840 # inout: int/mem -7841 # value: 'ff 0/subop/increment' -7842 # -7843 # There's nothing in functions. -7844 # -7845 # . prologue -7846 55/push-ebp -7847 89/<- %ebp 4/r32/esp -7848 # setup -7849 (clear-stream _test-output-stream) -7850 (clear-stream $_test-output-buffered-file->buffer) -7851 # var type/ecx: (handle tree type-id) = int -7852 68/push 0/imm32/right/null -7853 68/push 1/imm32/left/int -7854 89/<- %ecx 4/r32/esp -7855 # var var-foo/ecx: var in eax -7856 68/push "eax"/imm32/register -7857 68/push 0/imm32/no-stack-offset -7858 68/push 1/imm32/block-depth -7859 51/push-ecx -7860 68/push "foo"/imm32 -7861 89/<- %ecx 4/r32/esp -7862 # var real-outputs/edi: (handle stmt-var) -7863 68/push 0/imm32/is-deref:false -7864 68/push 0/imm32/next -7865 51/push-ecx/var-foo -7866 89/<- %edi 4/r32/esp -7867 # var stmt/esi: statement -7868 68/push 0/imm32/next -7869 57/push-edi/outputs -7870 68/push 0/imm32/inouts -7871 68/push "increment"/imm32/operation -7872 68/push 1/imm32 -7873 89/<- %esi 4/r32/esp -7874 # var formal-var/ebx: var in any register -7875 68/push Any-register/imm32 -7876 68/push 0/imm32/no-stack-offset -7877 68/push 1/imm32/block-depth -7878 ff 6/subop/push *(ecx+4) # Var-type -7879 68/push "dummy"/imm32 -7880 89/<- %ebx 4/r32/esp -7881 # var formal-outputs/ebx: (handle stmt-var) -7882 68/push 0/imm32/is-deref:false -7883 68/push 0/imm32/next -7884 53/push-ebx/formal-var -7885 89/<- %ebx 4/r32/esp -7886 # var primitive1/ebx: primitive -7887 68/push 0/imm32/next -7888 68/push 0/imm32/output-is-write-only -7889 68/push 0/imm32/no-disp32 -7890 68/push 0/imm32/no-imm32 -7891 68/push 0/imm32/no-r32 -7892 68/push 3/imm32/rm32-in-first-output -7893 68/push "ff 0/subop/increment"/imm32/subx-name -7894 53/push-ebx/outputs/formal-outputs -7895 68/push 0/imm32/inouts -7896 68/push "increment"/imm32/name -7897 89/<- %ebx 4/r32/esp -7898 # var primitives/ebx: primitive -7899 53/push-ebx/next -7900 68/push 0/imm32/output-is-write-only -7901 68/push 0/imm32/no-disp32 -7902 68/push 0/imm32/no-imm32 -7903 68/push 0/imm32/no-r32 -7904 68/push 1/imm32/rm32-is-first-inout -7905 68/push "ff 0/subop/increment"/imm32/subx-name -7906 68/push 0/imm32/outputs -7907 57/push-edi/inouts/real-outputs # hack; in practice we won't have the same var in function definition and call -7908 68/push "increment"/imm32/name -7909 89/<- %ebx 4/r32/esp -7910 # convert -7911 c7 0/subop/copy *Curr-block-depth 0/imm32 -7912 (emit-subx-statement _test-output-buffered-file %esi %ebx 0) -7913 (flush _test-output-buffered-file) -7914 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -7920 # check output -7921 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-statement-select-primitive") -7922 # . epilogue -7923 89/<- %esp 5/r32/ebp -7924 5d/pop-to-ebp -7925 c3/return -7926 -7927 test-emit-subx-statement-select-primitive-2: -7928 # Select the right primitive between overloads. -7929 # foo <- increment -7930 # => -7931 # ff 0/subop/increment %eax # sub-optimal, but should suffice -7932 # -7933 # There's a variable on the var stack as follows: -7934 # name: 'foo' -7935 # type: int -7936 # register: 'eax' -7937 # -7938 # There's two primitives, as follows: -7939 # - name: 'increment' -7940 # out: int/reg -7941 # value: 'ff 0/subop/increment' -7942 # - name: 'increment' -7943 # inout: int/mem -7944 # value: 'ff 0/subop/increment' -7945 # -7946 # There's nothing in functions. -7947 # -7948 # . prologue -7949 55/push-ebp -7950 89/<- %ebp 4/r32/esp -7951 # setup -7952 (clear-stream _test-output-stream) -7953 (clear-stream $_test-output-buffered-file->buffer) -7954 # var type/ecx: (handle tree type-id) = int -7955 68/push 0/imm32/right/null -7956 68/push 1/imm32/left/int -7957 89/<- %ecx 4/r32/esp -7958 # var var-foo/ecx: var in eax -7959 68/push "eax"/imm32/register -7960 68/push 0/imm32/no-stack-offset -7961 68/push 1/imm32/block-depth -7962 51/push-ecx -7963 68/push "foo"/imm32 -7964 89/<- %ecx 4/r32/esp -7965 # var inouts/edi: (handle stmt-var) -7966 68/push 0/imm32/is-deref:false -7967 68/push 0/imm32/next -7968 51/push-ecx/var-foo -7969 89/<- %edi 4/r32/esp -7970 # var stmt/esi: statement -7971 68/push 0/imm32/next -7972 68/push 0/imm32/outputs -7973 57/push-edi/inouts -7974 68/push "increment"/imm32/operation -7975 68/push 1/imm32 -7976 89/<- %esi 4/r32/esp -7977 # var formal-var/ebx: var in any register -7978 68/push Any-register/imm32 -7979 68/push 0/imm32/no-stack-offset -7980 68/push 1/imm32/block-depth -7981 ff 6/subop/push *(ecx+4) # Var-type -7982 68/push "dummy"/imm32 -7983 89/<- %ebx 4/r32/esp -7984 # var operand/ebx: (handle stmt-var) -7985 68/push 0/imm32/is-deref:false -7986 68/push 0/imm32/next -7987 53/push-ebx/formal-var -7988 89/<- %ebx 4/r32/esp -7989 # var primitive1/ebx: primitive -7990 68/push 0/imm32/next -7991 68/push 0/imm32/output-is-write-only -7992 68/push 0/imm32/no-disp32 -7993 68/push 0/imm32/no-imm32 -7994 68/push 0/imm32/no-r32 -7995 68/push 3/imm32/rm32-in-first-output -7996 68/push "ff 0/subop/increment"/imm32/subx-name -7997 53/push-ebx/outputs/formal-outputs -7998 68/push 0/imm32/inouts -7999 68/push "increment"/imm32/name -8000 89/<- %ebx 4/r32/esp -8001 # var primitives/ebx: primitive -8002 53/push-ebx/next -8003 68/push 0/imm32/output-is-write-only -8004 68/push 0/imm32/no-disp32 -8005 68/push 0/imm32/no-imm32 -8006 68/push 0/imm32/no-r32 -8007 68/push 1/imm32/rm32-is-first-inout -8008 68/push "ff 0/subop/increment"/imm32/subx-name -8009 68/push 0/imm32/outputs -8010 57/push-edi/inouts/real-outputs # hack; in practice we won't have the same var in function definition and call -8011 68/push "increment"/imm32/name -8012 89/<- %ebx 4/r32/esp -8013 # convert -8014 c7 0/subop/copy *Curr-block-depth 0/imm32 -8015 (emit-subx-statement _test-output-buffered-file %esi %ebx 0) -8016 (flush _test-output-buffered-file) -8017 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -8023 # check output -8024 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-statement-select-primitive-2") -8025 # . epilogue -8026 89/<- %esp 5/r32/ebp -8027 5d/pop-to-ebp -8028 c3/return -8029 -8030 test-increment-register: -8031 # Select the right register between overloads. -8032 # foo <- increment -8033 # => -8034 # 50/increment-eax -8035 # -8036 # There's a variable on the var stack as follows: -8037 # name: 'foo' -8038 # type: int -8039 # register: 'eax' -8040 # -8041 # Primitives are the global definitions. -8042 # -8043 # There are no functions defined. -8044 # -8045 # . prologue -8046 55/push-ebp -8047 89/<- %ebp 4/r32/esp -8048 # setup -8049 (clear-stream _test-output-stream) -8050 (clear-stream $_test-output-buffered-file->buffer) -8051 # var type/ecx: (handle tree type-id) = int -8052 68/push 0/imm32/right/null -8053 68/push 1/imm32/left/int -8054 89/<- %ecx 4/r32/esp -8055 # var var-foo/ecx: var in eax -8056 68/push "eax"/imm32/register -8057 68/push 0/imm32/no-stack-offset -8058 68/push 1/imm32/block-depth -8059 51/push-ecx -8060 68/push "foo"/imm32 -8061 89/<- %ecx 4/r32/esp -8062 # var real-outputs/edi: (handle stmt-var) -8063 68/push 0/imm32/is-deref:false -8064 68/push 0/imm32/next -8065 51/push-ecx/var-foo -8066 89/<- %edi 4/r32/esp -8067 # var stmt/esi: statement -8068 68/push 0/imm32/next -8069 57/push-edi/outputs -8070 68/push 0/imm32/inouts -8071 68/push "increment"/imm32/operation -8072 68/push 1/imm32/regular-statement -8073 89/<- %esi 4/r32/esp -8074 # convert -8075 c7 0/subop/copy *Curr-block-depth 0/imm32 -8076 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) -8077 (flush _test-output-buffered-file) -8078 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -8084 # check output -8085 (check-next-stream-line-equal _test-output-stream "40/increment-eax" "F - test-increment-register") -8086 # . epilogue -8087 89/<- %esp 5/r32/ebp -8088 5d/pop-to-ebp -8089 c3/return -8090 -8091 test-increment-var: -8092 # Select the right primitive between overloads. -8093 # foo <- increment -8094 # => -8095 # ff 0/subop/increment %eax # sub-optimal, but should suffice -8096 # -8097 # There's a variable on the var stack as follows: -8098 # name: 'foo' -8099 # type: int -8100 # register: 'eax' -8101 # -8102 # Primitives are the global definitions. -8103 # -8104 # There are no functions defined. -8105 # -8106 # . prologue -8107 55/push-ebp -8108 89/<- %ebp 4/r32/esp -8109 # setup -8110 (clear-stream _test-output-stream) -8111 (clear-stream $_test-output-buffered-file->buffer) -8112 # var type/ecx: (handle tree type-id) = int -8113 68/push 0/imm32/right/null -8114 68/push 1/imm32/left/int -8115 89/<- %ecx 4/r32/esp -8116 # var var-foo/ecx: var in eax -8117 68/push "eax"/imm32/register -8118 68/push 0/imm32/no-stack-offset -8119 68/push 1/imm32/block-depth -8120 51/push-ecx -8121 68/push "foo"/imm32 -8122 89/<- %ecx 4/r32/esp -8123 # var inouts/edi: (handle stmt-var) -8124 68/push 0/imm32/is-deref:false -8125 68/push 0/imm32/next -8126 51/push-ecx/var-foo -8127 89/<- %edi 4/r32/esp -8128 # var stmt/esi: statement -8129 68/push 0/imm32/next -8130 57/push-edi/outputs -8131 68/push 0/imm32/inouts -8132 68/push "increment"/imm32/operation -8133 68/push 1/imm32 -8134 89/<- %esi 4/r32/esp -8135 # convert -8136 c7 0/subop/copy *Curr-block-depth 0/imm32 -8137 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) -8138 (flush _test-output-buffered-file) -8139 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -8145 # check output -8146 (check-next-stream-line-equal _test-output-stream "40/increment-eax" "F - test-increment-var") -8147 # . epilogue -8148 89/<- %esp 5/r32/ebp -8149 5d/pop-to-ebp -8150 c3/return -8151 -8152 test-add-reg-to-reg: -8153 # var1/reg <- add var2/reg -8154 # => -8155 # 01/add %var1 var2 -8156 # -8157 # . prologue -8158 55/push-ebp -8159 89/<- %ebp 4/r32/esp -8160 # setup -8161 (clear-stream _test-output-stream) -8162 (clear-stream $_test-output-buffered-file->buffer) -8163 # var type/ecx: (handle tree type-id) = int -8164 68/push 0/imm32/right/null -8165 68/push 1/imm32/left/int -8166 89/<- %ecx 4/r32/esp -8167 # var var-var1/ecx: var in eax -8168 68/push "eax"/imm32/register -8169 68/push 0/imm32/no-stack-offset -8170 68/push 1/imm32/block-depth -8171 51/push-ecx -8172 68/push "var1"/imm32 -8173 89/<- %ecx 4/r32/esp -8174 # var var-var2/edx: var in ecx -8175 68/push "ecx"/imm32/register -8176 68/push 0/imm32/no-stack-offset -8177 68/push 1/imm32/block-depth -8178 ff 6/subop/push *(ecx+4) # Var-type -8179 68/push "var2"/imm32 -8180 89/<- %edx 4/r32/esp -8181 # var inouts/esi: (handle stmt-var) = [var2] -8182 68/push 0/imm32/is-deref:false -8183 68/push 0/imm32/next -8184 52/push-edx/var-var2 -8185 89/<- %esi 4/r32/esp -8186 # var outputs/edi: (handle stmt-var) = [var1, var2] -8187 68/push 0/imm32/is-deref:false -8188 68/push 0/imm32/next -8189 51/push-ecx/var-var1 -8190 89/<- %edi 4/r32/esp -8191 # var stmt/esi: statement -8192 68/push 0/imm32/next -8193 57/push-edi/outputs -8194 56/push-esi/inouts -8195 68/push "add"/imm32/operation -8196 68/push 1/imm32 -8197 89/<- %esi 4/r32/esp -8198 # convert -8199 c7 0/subop/copy *Curr-block-depth 0/imm32 -8200 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) -8201 (flush _test-output-buffered-file) -8202 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -8208 # check output -8209 (check-next-stream-line-equal _test-output-stream "01/add-to %eax 0x00000001/r32" "F - test-add-reg-to-reg") -8210 # . epilogue -8211 89/<- %esp 5/r32/ebp -8212 5d/pop-to-ebp -8213 c3/return -8214 -8215 test-add-reg-to-mem: -8216 # add-to var1 var2/reg -8217 # => -8218 # 01/add *(ebp+__) var2 -8219 # -8220 # . prologue -8221 55/push-ebp -8222 89/<- %ebp 4/r32/esp -8223 # setup -8224 (clear-stream _test-output-stream) -8225 (clear-stream $_test-output-buffered-file->buffer) -8226 # var type/ecx: (handle tree type-id) = int -8227 68/push 0/imm32/right/null -8228 68/push 1/imm32/left/int -8229 89/<- %ecx 4/r32/esp -8230 # var var-var1/ecx: var -8231 68/push 0/imm32/no-register -8232 68/push 8/imm32/stack-offset -8233 68/push 1/imm32/block-depth -8234 51/push-ecx -8235 68/push "var1"/imm32 -8236 89/<- %ecx 4/r32/esp -8237 # var var-var2/edx: var in ecx -8238 68/push "ecx"/imm32/register -8239 68/push 0/imm32/no-stack-offset -8240 68/push 1/imm32/block-depth -8241 ff 6/subop/push *(ecx+4) # Var-type -8242 68/push "var2"/imm32 -8243 89/<- %edx 4/r32/esp -8244 # var inouts/esi: (handle stmt-var) = [var2] -8245 68/push 0/imm32/is-deref:false -8246 68/push 0/imm32/next -8247 52/push-edx/var-var2 -8248 89/<- %esi 4/r32/esp -8249 # var inouts = (handle stmt-var) = [var1, var2] -8250 56/push-esi/next -8251 51/push-ecx/var-var1 -8252 89/<- %esi 4/r32/esp -8253 # var stmt/esi: statement -8254 68/push 0/imm32/next -8255 68/push 0/imm32/outputs -8256 56/push-esi/inouts -8257 68/push "add-to"/imm32/operation -8258 68/push 1/imm32 -8259 89/<- %esi 4/r32/esp -8260 # convert -8261 c7 0/subop/copy *Curr-block-depth 0/imm32 -8262 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) -8263 (flush _test-output-buffered-file) -8264 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -8270 # check output -8271 (check-next-stream-line-equal _test-output-stream "01/add-to *(ebp+0x00000008) 0x00000001/r32" "F - test-add-reg-to-mem") -8272 # . epilogue -8273 89/<- %esp 5/r32/ebp -8274 5d/pop-to-ebp -8275 c3/return -8276 -8277 test-add-mem-to-reg: -8278 # var1/reg <- add var2 -8279 # => -8280 # 03/add *(ebp+__) var1 -8281 # -8282 # . prologue -8283 55/push-ebp -8284 89/<- %ebp 4/r32/esp -8285 # setup -8286 (clear-stream _test-output-stream) -8287 (clear-stream $_test-output-buffered-file->buffer) -8288 # var type/ecx: (handle tree type-id) = int -8289 68/push 0/imm32/right/null -8290 68/push 1/imm32/left/int -8291 89/<- %ecx 4/r32/esp -8292 # var var-var1/ecx: var in eax -8293 68/push "eax"/imm32/register -8294 68/push 0/imm32/no-stack-offset -8295 68/push 1/imm32/block-depth -8296 51/push-ecx -8297 68/push "var1"/imm32 -8298 89/<- %ecx 4/r32/esp -8299 # var var-var2/edx: var -8300 68/push 0/imm32/no-register -8301 68/push 8/imm32/stack-offset -8302 68/push 1/imm32/block-depth -8303 ff 6/subop/push *(ecx+4) # Var-type -8304 68/push "var2"/imm32 -8305 89/<- %edx 4/r32/esp -8306 # var inouts/esi: (handle stmt-var) = [var2] -8307 68/push 0/imm32/is-deref:false -8308 68/push 0/imm32/next -8309 52/push-edx/var-var2 -8310 89/<- %esi 4/r32/esp -8311 # var outputs/edi = (handle stmt-var) = [var1] -8312 68/push 0/imm32/is-deref:false -8313 68/push 0/imm32/next -8314 51/push-ecx/var-var1 -8315 89/<- %edi 4/r32/esp -8316 # var stmt/esi: statement -8317 68/push 0/imm32/next -8318 57/push-edi/outputs -8319 56/push-esi/inouts -8320 68/push "add"/imm32/operation -8321 68/push 1/imm32 -8322 89/<- %esi 4/r32/esp -8323 # convert -8324 c7 0/subop/copy *Curr-block-depth 0/imm32 -8325 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) -8326 (flush _test-output-buffered-file) -8327 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -8333 # check output -8334 (check-next-stream-line-equal _test-output-stream "03/add *(ebp+0x00000008) 0x00000000/r32" "F - test-add-mem-to-reg") -8335 # . epilogue -8336 89/<- %esp 5/r32/ebp -8337 5d/pop-to-ebp -8338 c3/return -8339 -8340 test-add-literal-to-eax: -8341 # var1/eax <- add 0x34 -8342 # => -8343 # 05/add-to-eax 0x34/imm32 -8344 # -8345 # . prologue -8346 55/push-ebp -8347 89/<- %ebp 4/r32/esp -8348 # setup -8349 (clear-stream _test-output-stream) -8350 (clear-stream $_test-output-buffered-file->buffer) -8351 # var type/ecx: (handle tree type-id) = int -8352 68/push 0/imm32/right/null -8353 68/push 1/imm32/left/int -8354 89/<- %ecx 4/r32/esp -8355 # var var-var1/ecx: var in eax -8356 68/push "eax"/imm32/register -8357 68/push 0/imm32/no-stack-offset -8358 68/push 1/imm32/block-depth -8359 51/push-ecx -8360 68/push "var1"/imm32 -8361 89/<- %ecx 4/r32/esp -8362 # var type/edx: (handle tree type-id) = literal -8363 68/push 0/imm32/right/null -8364 68/push 0/imm32/left/literal -8365 89/<- %edx 4/r32/esp -8366 # var var-var2/edx: var literal -8367 68/push 0/imm32/no-register -8368 68/push 0/imm32/no-stack-offset -8369 68/push 1/imm32/block-depth -8370 52/push-edx -8371 68/push "0x34"/imm32 -8372 89/<- %edx 4/r32/esp -8373 # var inouts/esi: (handle stmt-var) = [var2] -8374 68/push 0/imm32/is-deref:false -8375 68/push 0/imm32/next -8376 52/push-edx/var-var2 -8377 89/<- %esi 4/r32/esp -8378 # var outputs/edi: (handle stmt-var) = [var1] -8379 68/push 0/imm32/is-deref:false -8380 68/push 0/imm32/next -8381 51/push-ecx/var-var1 -8382 89/<- %edi 4/r32/esp -8383 # var stmt/esi: statement -8384 68/push 0/imm32/next -8385 57/push-edi/outputs -8386 56/push-esi/inouts -8387 68/push "add"/imm32/operation -8388 68/push 1/imm32 -8389 89/<- %esi 4/r32/esp -8390 # convert -8391 c7 0/subop/copy *Curr-block-depth 0/imm32 -8392 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) -8393 (flush _test-output-buffered-file) -8394 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -8400 # check output -8401 (check-next-stream-line-equal _test-output-stream "05/add-to-eax 0x34/imm32" "F - test-add-literal-to-eax") -8402 # . epilogue -8403 89/<- %esp 5/r32/ebp -8404 5d/pop-to-ebp -8405 c3/return -8406 -8407 test-add-literal-to-reg: -8408 # var1/ecx <- add 0x34 -8409 # => -8410 # 81 0/subop/add %ecx 0x34/imm32 -8411 # -8412 # . prologue -8413 55/push-ebp -8414 89/<- %ebp 4/r32/esp -8415 # setup -8416 (clear-stream _test-output-stream) -8417 (clear-stream $_test-output-buffered-file->buffer) -8418 # var type/ecx: (handle tree type-id) = int -8419 68/push 0/imm32/right/null -8420 68/push 1/imm32/left/int -8421 89/<- %ecx 4/r32/esp -8422 # var var-var1/ecx: var in ecx -8423 68/push "ecx"/imm32/register -8424 68/push 0/imm32/no-stack-offset -8425 68/push 1/imm32/block-depth -8426 51/push-ecx -8427 68/push "var1"/imm32 -8428 89/<- %ecx 4/r32/esp -8429 # var type/edx: (handle tree type-id) = literal -8430 68/push 0/imm32/right/null -8431 68/push 0/imm32/left/literal -8432 89/<- %edx 4/r32/esp -8433 # var var-var2/edx: var literal -8434 68/push 0/imm32/no-register -8435 68/push 0/imm32/no-stack-offset -8436 68/push 1/imm32/block-depth -8437 52/push-edx -8438 68/push "0x34"/imm32 -8439 89/<- %edx 4/r32/esp -8440 # var inouts/esi: (handle stmt-var) = [var2] -8441 68/push 0/imm32/is-deref:false -8442 68/push 0/imm32/next -8443 52/push-edx/var-var2 -8444 89/<- %esi 4/r32/esp -8445 # var outputs/edi: (handle stmt-var) = [var1] -8446 68/push 0/imm32/is-deref:false -8447 68/push 0/imm32/next -8448 51/push-ecx/var-var1 -8449 89/<- %edi 4/r32/esp -8450 # var stmt/esi: statement -8451 68/push 0/imm32/next -8452 57/push-edi/outputs -8453 56/push-esi/inouts -8454 68/push "add"/imm32/operation -8455 68/push 1/imm32 -8456 89/<- %esi 4/r32/esp -8457 # convert -8458 c7 0/subop/copy *Curr-block-depth 0/imm32 -8459 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) -8460 (flush _test-output-buffered-file) -8461 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -8467 # check output -8468 (check-next-stream-line-equal _test-output-stream "81 0/subop/add %ecx 0x34/imm32" "F - test-add-literal-to-reg") -8469 # . epilogue -8470 89/<- %esp 5/r32/ebp -8471 5d/pop-to-ebp -8472 c3/return -8473 -8474 test-add-literal-to-mem: -8475 # add-to var1, 0x34 -8476 # => -8477 # 81 0/subop/add %eax 0x34/imm32 -8478 # -8479 # . prologue -8480 55/push-ebp -8481 89/<- %ebp 4/r32/esp -8482 # setup -8483 (clear-stream _test-output-stream) -8484 (clear-stream $_test-output-buffered-file->buffer) -8485 # var type/ecx: (handle tree type-id) = int -8486 68/push 0/imm32/right/null -8487 68/push 1/imm32/left/int -8488 89/<- %ecx 4/r32/esp -8489 # var var-var1/ecx: var -8490 68/push 0/imm32/no-register -8491 68/push 8/imm32/stack-offset -8492 68/push 1/imm32/block-depth -8493 51/push-ecx -8494 68/push "var1"/imm32 -8495 89/<- %ecx 4/r32/esp -8496 # var type/edx: (handle tree type-id) = literal -8497 68/push 0/imm32/right/null -8498 68/push 0/imm32/left/literal -8499 89/<- %edx 4/r32/esp -8500 # var var-var2/edx: var literal -8501 68/push 0/imm32/no-register -8502 68/push 0/imm32/no-stack-offset -8503 68/push 1/imm32/block-depth -8504 52/push-edx -8505 68/push "0x34"/imm32 -8506 89/<- %edx 4/r32/esp -8507 # var inouts/esi: (handle stmt-var) = [var2] -8508 68/push 0/imm32/is-deref:false -8509 68/push 0/imm32/next -8510 52/push-edx/var-var2 -8511 89/<- %esi 4/r32/esp -8512 # var inouts = (handle stmt-var) = [var1, var2] -8513 68/push 0/imm32/is-deref:false -8514 56/push-esi/next -8515 51/push-ecx/var-var1 -8516 89/<- %esi 4/r32/esp -8517 # var stmt/esi: statement -8518 68/push 0/imm32/next -8519 68/push 0/imm32/outputs -8520 56/push-esi/inouts -8521 68/push "add-to"/imm32/operation -8522 68/push 1/imm32 -8523 89/<- %esi 4/r32/esp -8524 # convert -8525 c7 0/subop/copy *Curr-block-depth 0/imm32 -8526 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) -8527 (flush _test-output-buffered-file) -8528 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -8534 # check output -8535 (check-next-stream-line-equal _test-output-stream "81 0/subop/add *(ebp+0x00000008) 0x34/imm32" "F - test-add-literal-to-mem") -8536 # . epilogue -8537 89/<- %esp 5/r32/ebp -8538 5d/pop-to-ebp -8539 c3/return -8540 -8541 test-compare-mem-with-reg: -8542 # compare var1, var2/eax -8543 # => -8544 # 39/compare *(ebp+___) 0/r32/eax -8545 # -8546 # . prologue -8547 55/push-ebp -8548 89/<- %ebp 4/r32/esp -8549 # setup -8550 (clear-stream _test-output-stream) -8551 (clear-stream $_test-output-buffered-file->buffer) -8552 # var type/ecx: (handle tree type-id) = int -8553 68/push 0/imm32/right/null -8554 68/push 1/imm32/left/int -8555 89/<- %ecx 4/r32/esp -8556 # var var-var2/ecx: var in eax -8557 68/push "eax"/imm32/register -8558 68/push 0/imm32/no-stack-offset -8559 68/push 1/imm32/block-depth -8560 51/push-ecx -8561 68/push "var2"/imm32 -8562 89/<- %ecx 4/r32/esp -8563 # var var-var1/edx: var -8564 68/push 0/imm32/no-register -8565 68/push 8/imm32/stack-offset -8566 68/push 1/imm32/block-depth -8567 ff 6/subop/push *(ecx+4) # Var-type -8568 68/push "var1"/imm32 -8569 89/<- %edx 4/r32/esp -8570 # var inouts/esi: (handle stmt-var) = [var2] -8571 68/push 0/imm32/is-deref:false -8572 68/push 0/imm32/next -8573 51/push-ecx/var-var2 -8574 89/<- %esi 4/r32/esp -8575 # inouts = [var1, var2] -8576 68/push 0/imm32/is-deref:false -8577 56/push-esi -8578 52/push-edx/var-var1 -8579 89/<- %esi 4/r32/esp -8580 # var stmt/esi: statement -8581 68/push 0/imm32/next -8582 68/push 0/imm32/outputs -8583 56/push-esi/inouts -8584 68/push "compare"/imm32/operation -8585 68/push 1/imm32 -8586 89/<- %esi 4/r32/esp -8587 # convert -8588 c7 0/subop/copy *Curr-block-depth 0/imm32 -8589 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) -8590 (flush _test-output-buffered-file) -8591 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -8597 # check output -8598 (check-next-stream-line-equal _test-output-stream "39/compare-> *(ebp+0x00000008) 0x00000000/r32" "F - test-compare-mem-with-reg") -8599 # . epilogue -8600 89/<- %esp 5/r32/ebp -8601 5d/pop-to-ebp -8602 c3/return -8603 -8604 test-compare-reg-with-mem: -8605 # compare var1/eax, var2 -8606 # => -8607 # 3b/compare *(ebp+___) 0/r32/eax -8608 # -8609 # . prologue -8610 55/push-ebp -8611 89/<- %ebp 4/r32/esp -8612 # setup -8613 (clear-stream _test-output-stream) -8614 (clear-stream $_test-output-buffered-file->buffer) -8615 # var type/ecx: (handle tree type-id) = int -8616 68/push 0/imm32/right/null -8617 68/push 1/imm32/left/int -8618 89/<- %ecx 4/r32/esp -8619 # var var-var1/ecx: var in eax -8620 68/push "eax"/imm32/register -8621 68/push 0/imm32/no-stack-offset -8622 68/push 1/imm32/block-depth -8623 51/push-ecx -8624 68/push "var1"/imm32 -8625 89/<- %ecx 4/r32/esp -8626 # var var-var2/edx: var -8627 68/push 0/imm32/no-register -8628 68/push 8/imm32/stack-offset -8629 68/push 1/imm32/block-depth -8630 ff 6/subop/push *(ecx+4) # Var-type -8631 68/push "var2"/imm32 -8632 89/<- %edx 4/r32/esp -8633 # var inouts/esi: (handle stmt-var) = [var2] -8634 68/push 0/imm32/is-deref:false -8635 68/push 0/imm32/next -8636 52/push-edx/var-var2 -8637 89/<- %esi 4/r32/esp -8638 # inouts = [var1, var2] -8639 68/push 0/imm32/is-deref:false -8640 56/push-esi -8641 51/push-ecx/var-var1 -8642 89/<- %esi 4/r32/esp -8643 # var stmt/esi: statement -8644 68/push 0/imm32/next -8645 68/push 0/imm32/outputs -8646 56/push-esi/inouts -8647 68/push "compare"/imm32/operation -8648 68/push 1/imm32 -8649 89/<- %esi 4/r32/esp -8650 # convert -8651 c7 0/subop/copy *Curr-block-depth 0/imm32 -8652 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) -8653 (flush _test-output-buffered-file) -8654 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -8660 # check output -8661 (check-next-stream-line-equal _test-output-stream "3b/compare<- *(ebp+0x00000008) 0x00000000/r32" "F - test-compare-reg-with-mem") -8662 # . epilogue -8663 89/<- %esp 5/r32/ebp -8664 5d/pop-to-ebp -8665 c3/return -8666 -8667 test-compare-mem-with-literal: -8668 # compare var1, 0x34 -8669 # => -8670 # 81 7/subop/compare *(ebp+___) 0x34/imm32 -8671 # -8672 # . prologue -8673 55/push-ebp -8674 89/<- %ebp 4/r32/esp -8675 # setup -8676 (clear-stream _test-output-stream) -8677 (clear-stream $_test-output-buffered-file->buffer) -8678 # var type/ecx: (handle tree type-id) = int -8679 68/push 0/imm32/right/null -8680 68/push 1/imm32/left/int -8681 89/<- %ecx 4/r32/esp -8682 # var var-var1/ecx: var -8683 68/push 0/imm32/no-register -8684 68/push 8/imm32/stack-offset -8685 68/push 1/imm32/block-depth -8686 51/push-ecx -8687 68/push "var1"/imm32 -8688 89/<- %ecx 4/r32/esp -8689 # var type/edx: (handle tree type-id) = literal -8690 68/push 0/imm32/right/null -8691 68/push 0/imm32/left/literal -8692 89/<- %edx 4/r32/esp -8693 # var var-var2/edx: var literal -8694 68/push 0/imm32/no-register -8695 68/push 0/imm32/no-stack-offset -8696 68/push 1/imm32/block-depth -8697 52/push-edx -8698 68/push "0x34"/imm32 -8699 89/<- %edx 4/r32/esp -8700 # var inouts/esi: (handle stmt-var) = [var2] -8701 68/push 0/imm32/is-deref:false -8702 68/push 0/imm32/next -8703 52/push-edx/var-var2 -8704 89/<- %esi 4/r32/esp -8705 # inouts = [var1, var2] -8706 68/push 0/imm32/is-deref:false -8707 56/push-esi/next -8708 51/push-ecx/var-var1 -8709 89/<- %esi 4/r32/esp -8710 # var stmt/esi: statement -8711 68/push 0/imm32/next -8712 68/push 0/imm32/outputs -8713 56/push-esi/inouts -8714 68/push "compare"/imm32/operation -8715 68/push 1/imm32 -8716 89/<- %esi 4/r32/esp -8717 # convert -8718 c7 0/subop/copy *Curr-block-depth 0/imm32 -8719 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) -8720 (flush _test-output-buffered-file) -8721 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -8727 # check output -8728 (check-next-stream-line-equal _test-output-stream "81 7/subop/compare *(ebp+0x00000008) 0x34/imm32" "F - test-compare-mem-with-literal") -8729 # . epilogue -8730 89/<- %esp 5/r32/ebp -8731 5d/pop-to-ebp -8732 c3/return -8733 -8734 test-compare-eax-with-literal: -8735 # compare var1/eax 0x34 -8736 # => -8737 # 3d/compare-eax-with 0x34/imm32 -8738 # -8739 # . prologue -8740 55/push-ebp -8741 89/<- %ebp 4/r32/esp -8742 # setup -8743 (clear-stream _test-output-stream) -8744 (clear-stream $_test-output-buffered-file->buffer) -8745 # var type/ecx: (handle tree type-id) = int -8746 68/push 0/imm32/right/null -8747 68/push 1/imm32/left/int -8748 89/<- %ecx 4/r32/esp -8749 # var var-var1/ecx: var in eax -8750 68/push "eax"/imm32/register -8751 68/push 0/imm32/no-stack-offset -8752 68/push 1/imm32/block-depth -8753 51/push-ecx -8754 68/push "var1"/imm32 -8755 89/<- %ecx 4/r32/esp -8756 # var type/edx: (handle tree type-id) = literal -8757 68/push 0/imm32/right/null -8758 68/push 0/imm32/left/literal -8759 89/<- %edx 4/r32/esp -8760 # var var-var2/edx: var literal -8761 68/push 0/imm32/no-register -8762 68/push 0/imm32/no-stack-offset -8763 68/push 1/imm32/block-depth -8764 52/push-edx -8765 68/push "0x34"/imm32 -8766 89/<- %edx 4/r32/esp -8767 # var inouts/esi: (handle stmt-var) = [var2] -8768 68/push 0/imm32/is-deref:false -8769 68/push 0/imm32/next -8770 52/push-edx/var-var2 -8771 89/<- %esi 4/r32/esp -8772 # inouts = [var1, var2] -8773 68/push 0/imm32/is-deref:false -8774 56/push-esi/next -8775 51/push-ecx/var-var1 -8776 89/<- %esi 4/r32/esp -8777 # var stmt/esi: statement -8778 68/push 0/imm32/next -8779 68/push 0/imm32/outputs -8780 56/push-esi/inouts -8781 68/push "compare"/imm32/operation -8782 68/push 1/imm32/regular-stmt -8783 89/<- %esi 4/r32/esp -8784 # convert -8785 c7 0/subop/copy *Curr-block-depth 0/imm32 -8786 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) -8787 (flush _test-output-buffered-file) -8788 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -8794 # check output -8795 (check-next-stream-line-equal _test-output-stream "3d/compare-eax-with 0x34/imm32" "F - test-compare-eax-with-literal") -8796 # . epilogue -8797 89/<- %esp 5/r32/ebp -8798 5d/pop-to-ebp -8799 c3/return -8800 -8801 test-compare-reg-with-literal: -8802 # compare var1/ecx 0x34 -8803 # => -8804 # 81 7/subop/compare %ecx 0x34/imm32 -8805 # -8806 # . prologue -8807 55/push-ebp -8808 89/<- %ebp 4/r32/esp -8809 # setup -8810 (clear-stream _test-output-stream) -8811 (clear-stream $_test-output-buffered-file->buffer) -8812 # var type/ecx: (handle tree type-id) = int -8813 68/push 0/imm32/right/null -8814 68/push 1/imm32/left/int -8815 89/<- %ecx 4/r32/esp -8816 # var var-var1/ecx: var in ecx -8817 68/push "ecx"/imm32/register -8818 68/push 0/imm32/no-stack-offset -8819 68/push 1/imm32/block-depth -8820 51/push-ecx -8821 68/push "var1"/imm32 -8822 89/<- %ecx 4/r32/esp -8823 # var type/edx: (handle tree type-id) = literal -8824 68/push 0/imm32/right/null -8825 68/push 0/imm32/left/literal -8826 89/<- %edx 4/r32/esp -8827 # var var-var2/edx: var literal -8828 68/push 0/imm32/no-register -8829 68/push 0/imm32/no-stack-offset -8830 68/push 1/imm32/block-depth -8831 52/push-edx -8832 68/push "0x34"/imm32 -8833 89/<- %edx 4/r32/esp -8834 # var inouts/esi: (handle stmt-var) = [var2] -8835 68/push 0/imm32/is-deref:false -8836 68/push 0/imm32/next -8837 52/push-edx/var-var2 -8838 89/<- %esi 4/r32/esp -8839 # inouts = [var1, var2] -8840 68/push 0/imm32/is-deref:false -8841 56/push-esi/next -8842 51/push-ecx/var-var1 -8843 89/<- %esi 4/r32/esp -8844 # var stmt/esi: statement -8845 68/push 0/imm32/next -8846 68/push 0/imm32/outputs -8847 56/push-esi/inouts -8848 68/push "compare"/imm32/operation -8849 68/push 1/imm32/regular-stmt -8850 89/<- %esi 4/r32/esp -8851 # convert -8852 c7 0/subop/copy *Curr-block-depth 0/imm32 -8853 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) -8854 (flush _test-output-buffered-file) -8855 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -8861 # check output -8862 (check-next-stream-line-equal _test-output-stream "81 7/subop/compare %ecx 0x34/imm32" "F - test-compare-reg-with-literal") -8863 # . epilogue -8864 89/<- %esp 5/r32/ebp -8865 5d/pop-to-ebp -8866 c3/return -8867 -8868 test-emit-subx-statement-function-call: -8869 # Call a function on a variable on the stack. -8870 # f foo -8871 # => -8872 # (f2 *(ebp-8)) -8873 # (Changing the function name supports overloading in general, but here it -8874 # just serves to help disambiguate things.) -8875 # -8876 # There's a variable on the var stack as follows: -8877 # name: 'foo' -8878 # type: int -8879 # stack-offset: -8 -8880 # -8881 # There's nothing in primitives. -8882 # -8883 # There's a function with this info: -8884 # name: 'f' -8885 # inout: int/mem -8886 # value: 'f2' -8887 # -8888 # . prologue -8889 55/push-ebp -8890 89/<- %ebp 4/r32/esp -8891 # setup -8892 (clear-stream _test-output-stream) -8893 (clear-stream $_test-output-buffered-file->buffer) -8894 # var type/ecx: (handle tree type-id) = int -8895 68/push 0/imm32/right/null -8896 68/push 1/imm32/left/int -8897 89/<- %ecx 4/r32/esp -8898 # var var-foo/ecx: var -8899 68/push 0/imm32/no-register -8900 68/push -8/imm32/stack-offset -8901 68/push 0/imm32/block-depth -8902 51/push-ecx -8903 68/push "foo"/imm32 -8904 89/<- %ecx 4/r32/esp -8905 # var inouts/esi: (handle stmt-var) -8906 68/push 0/imm32/is-deref:false -8907 68/push 0/imm32/next -8908 51/push-ecx/var-foo -8909 89/<- %esi 4/r32/esp -8910 # var stmt/esi: statement -8911 68/push 0/imm32/next -8912 68/push 0/imm32/outputs -8913 56/push-esi/inouts -8914 68/push "f"/imm32/operation -8915 68/push 1/imm32 -8916 89/<- %esi 4/r32/esp -8917 # var functions/ebx: function -8918 68/push 0/imm32/next -8919 68/push 0/imm32/body -8920 68/push 0/imm32/outputs -8921 51/push-ecx/inouts # hack; in practice we won't have the same var in function definition and call -8922 68/push "f2"/imm32/subx-name -8923 68/push "f"/imm32/name -8924 89/<- %ebx 4/r32/esp -8925 # convert -8926 c7 0/subop/copy *Curr-block-depth 0/imm32 -8927 (emit-subx-statement _test-output-buffered-file %esi 0 %ebx) -8928 (flush _test-output-buffered-file) -8929 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -8935 # check output -8936 (check-next-stream-line-equal _test-output-stream "(f2 *(ebp+0xfffffff8))" "F - test-emit-subx-statement-function-call") -8937 # . epilogue -8938 89/<- %esp 5/r32/ebp -8939 5d/pop-to-ebp -8940 c3/return -8941 -8942 test-emit-subx-statement-function-call-with-literal-arg: -8943 # Call a function on a literal. -8944 # f 34 -8945 # => -8946 # (f2 34) -8947 # -8948 # . prologue -8949 55/push-ebp -8950 89/<- %ebp 4/r32/esp -8951 # setup -8952 (clear-stream _test-output-stream) -8953 (clear-stream $_test-output-buffered-file->buffer) -8954 # var type/ecx: (handle tree type-id) = literal -8955 68/push 0/imm32/right/null -8956 68/push 0/imm32/left/literal -8957 89/<- %ecx 4/r32/esp -8958 # var var-foo/ecx: var literal -8959 68/push 0/imm32/no-register -8960 68/push 0/imm32/no-stack-offset -8961 68/push 0/imm32/block-depth -8962 51/push-ecx -8963 68/push "34"/imm32 -8964 89/<- %ecx 4/r32/esp -8965 # var inouts/esi: (handle stmt-var) -8966 68/push 0/imm32/is-deref:false -8967 68/push 0/imm32/next -8968 51/push-ecx/var-foo -8969 89/<- %esi 4/r32/esp -8970 # var stmt/esi: statement -8971 68/push 0/imm32/next -8972 68/push 0/imm32/outputs -8973 56/push-esi/inouts -8974 68/push "f"/imm32/operation -8975 68/push 1/imm32 -8976 89/<- %esi 4/r32/esp -8977 # var functions/ebx: function -8978 68/push 0/imm32/next -8979 68/push 0/imm32/body -8980 68/push 0/imm32/outputs -8981 51/push-ecx/inouts # hack; in practice we won't have the same var in function definition and call -8982 68/push "f2"/imm32/subx-name -8983 68/push "f"/imm32/name -8984 89/<- %ebx 4/r32/esp -8985 # convert -8986 c7 0/subop/copy *Curr-block-depth 0/imm32 -8987 (emit-subx-statement _test-output-buffered-file %esi 0 %ebx) -8988 (flush _test-output-buffered-file) -8989 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- -8995 # check output -8996 (check-next-stream-line-equal _test-output-stream "(f2 34)" "F - test-emit-subx-statement-function-call-with-literal-arg") -8997 # . epilogue -8998 89/<- %esp 5/r32/ebp -8999 5d/pop-to-ebp -9000 c3/return -9001 -9002 emit-indent: # out: (addr buffered-file), n: int -9003 # . prologue -9004 55/push-ebp -9005 89/<- %ebp 4/r32/esp -9006 # . save registers -9007 50/push-eax -9008 # var i/eax: int = n -9009 8b/-> *(ebp+0xc) 0/r32/eax -9010 { -9011 # if (i <= 0) break -9012 3d/compare-eax-with 0/imm32 -9013 7e/jump-if-<= break/disp8 -9014 (write-buffered *(ebp+8) " ") -9015 48/decrement-eax -9016 eb/jump loop/disp8 -9017 } -9018 $emit-indent:end: -9019 # . restore registers -9020 58/pop-to-eax -9021 # . epilogue -9022 89/<- %esp 5/r32/ebp -9023 5d/pop-to-ebp -9024 c3/return -9025 -9026 emit-subx-prologue: # out: (addr buffered-file) -9027 # . prologue -9028 55/push-ebp -9029 89/<- %ebp 4/r32/esp -9030 # -9031 (write-buffered *(ebp+8) " # . prologue\n") -9032 (write-buffered *(ebp+8) " 55/push-ebp\n") -9033 (write-buffered *(ebp+8) " 89/<- %ebp 4/r32/esp\n") -9034 $emit-subx-prologue:end: -9035 # . epilogue -9036 89/<- %esp 5/r32/ebp -9037 5d/pop-to-ebp -9038 c3/return -9039 -9040 emit-subx-epilogue: # out: (addr buffered-file) -9041 # . prologue -9042 55/push-ebp -9043 89/<- %ebp 4/r32/esp -9044 # -9045 (write-buffered *(ebp+8) " # . epilogue\n") -9046 (write-buffered *(ebp+8) " 89/<- %esp 5/r32/ebp\n") -9047 (write-buffered *(ebp+8) " 5d/pop-to-ebp\n") -9048 (write-buffered *(ebp+8) " c3/return\n") -9049 $emit-subx-epilogue:end: -9050 # . epilogue -9051 89/<- %esp 5/r32/ebp -9052 5d/pop-to-ebp -9053 c3/return +7571 # curr=curr->next +7572 8b/-> *(esi+4) 6/r32/esi # Stmt-var-next +7573 # curr2=curr2->next +7574 8b/-> *(edi+4) 7/r32/edi # Stmt-var-next +7575 eb/jump loop/disp8 +7576 } +7577 $mu-stmt-matches-primitive?:check-outputs: +7578 # for (curr/esi in stmt->outputs, curr2/edi in primitive->outputs) +7579 8b/-> *(ecx+0xc) 6/r32/esi # Stmt1-outputs +7580 8b/-> *(edx+8) 7/r32/edi # Primitive-outputs +7581 { +7582 # if (curr == 0) return (curr2 == 0) +7583 { +7584 $mu-stmt-matches-primitive?:check-output: +7585 81 7/subop/compare %esi 0/imm32 +7586 75/jump-if-!= break/disp8 +7587 { +7588 81 7/subop/compare %edi 0/imm32 +7589 75/jump-if-!= break/disp8 +7590 # return true +7591 b8/copy-to-eax 1/imm32 +7592 e9/jump $mu-stmt-matches-primitive?:end/disp32 +7593 } +7594 # return false +7595 b8/copy-to-eax 0/imm32 +7596 e9/jump $mu-stmt-matches-primitive?:end/disp32 +7597 } +7598 # if (curr2 == 0) return false +7599 { +7600 81 7/subop/compare %edi 0/imm32 +7601 75/jump-if-!= break/disp8 +7602 b8/copy-to-eax 0/imm32 +7603 e9/jump $mu-stmt-matches-primitive?:end/disp32 +7604 } +7605 # if (curr != curr2) return false +7606 { +7607 (operand-matches-primitive? %esi *edi) # List-value => eax +7608 3d/compare-eax-and 0/imm32/false +7609 75/jump-if-!= break/disp8 +7610 b8/copy-to-eax 0/imm32 +7611 e9/jump $mu-stmt-matches-primitive?:end/disp32 +7612 } +7613 # curr=curr->next +7614 8b/-> *(esi+4) 6/r32/esi # Stmt-var-next +7615 # curr2=curr2->next +7616 8b/-> *(edi+4) 7/r32/edi # Stmt-var-next +7617 eb/jump loop/disp8 +7618 } +7619 $mu-stmt-matches-primitive?:return-true: +7620 b8/copy-to-eax 1/imm32 +7621 $mu-stmt-matches-primitive?:end: +7622 # . restore registers +7623 5f/pop-to-edi +7624 5e/pop-to-esi +7625 5b/pop-to-ebx +7626 5a/pop-to-edx +7627 59/pop-to-ecx +7628 # . epilogue +7629 89/<- %esp 5/r32/ebp +7630 5d/pop-to-ebp +7631 c3/return +7632 +7633 operand-matches-primitive?: # s: (handle stmt-var), prim-var: (handle var) -> result/eax: boolean +7634 # . prologue +7635 55/push-ebp +7636 89/<- %ebp 4/r32/esp +7637 # . save registers +7638 51/push-ecx +7639 56/push-esi +7640 57/push-edi +7641 # ecx = s +7642 8b/-> *(ebp+8) 1/r32/ecx +7643 # var var/esi : (handle var) = s->value +7644 8b/-> *ecx 6/r32/esi # Stmt-var-value +7645 # edi = prim-var +7646 8b/-> *(ebp+0xc) 7/r32/edi +7647 $operand-matches-primitive?:check-type: +7648 # if (var->type != prim-var->type) return false +7649 (subx-type-equal? *(esi+4) *(edi+4)) # Var-type, Var-type => eax +7650 3d/compare-eax-and 0/imm32/false +7651 b8/copy-to-eax 0/imm32/false +7652 0f 84/jump-if-= $operand-matches-primitive?:end/disp32 +7653 { +7654 $operand-matches-primitive?:check-register: +7655 # if prim-var is in memory and var is in register but dereference, match +7656 { +7657 81 7/subop/compare *(edi+0x10) 0/imm32 # Var-register +7658 0f 85/jump-if-!= break/disp32 +7659 81 7/subop/compare *(esi+0x10) 0/imm32 # Var-register +7660 74/jump-if-= break/disp8 +7661 81 7/subop/compare *(ecx+8) 0/imm32/false # Stmt-var-is-deref +7662 74/jump-if-= break/disp8 +7663 e9/jump $operand-matches-primitive?:return-true/disp32 +7664 } +7665 # if prim-var is in register and var is in register but dereference, no match +7666 { +7667 81 7/subop/compare *(edi+0x10) 0/imm32 # Var-register +7668 0f 84/jump-if-= break/disp32 +7669 81 7/subop/compare *(esi+0x10) 0/imm32 # Var-register +7670 0f 84/jump-if-= break/disp32 +7671 81 7/subop/compare *(ecx+8) 0/imm32/false # Stmt-var-is-deref +7672 74/jump-if-= break/disp8 +7673 e9/jump $operand-matches-primitive?:return-false/disp32 +7674 } +7675 # return false if var->register doesn't match prim-var->register +7676 { +7677 # if register addresses are equal, it's a match +7678 8b/-> *(esi+0x10) 0/r32/eax # Var-register +7679 39/compare *(edi+0x10) 0/r32/eax # Var-register +7680 74/jump-if-= break/disp8 +7681 # if either address is 0, return false +7682 3d/compare-eax-and 0/imm32 +7683 74/jump-if-= $operand-matches-primitive?:end/disp8 # eax goes from meaning var->register to result +7684 81 7/subop/compare *(edi+0x10) 0/imm32 # Var-register +7685 74/jump-if-= $operand-matches-primitive?:return-false/disp8 +7686 # if prim-var->register is wildcard, it's a match +7687 (string-equal? *(edi+0x10) Any-register) # Var-register => eax +7688 3d/compare-eax-and 0/imm32/false +7689 75/jump-if-!= break/disp8 +7690 # if string contents aren't equal, return false +7691 (string-equal? *(esi+0x10) *(edi+0x10)) # Var-register Var-register => eax +7692 3d/compare-eax-and 0/imm32/false +7693 74/jump-if-= $operand-matches-primitive?:return-false/disp8 +7694 } +7695 } +7696 $operand-matches-primitive?:return-true: +7697 b8/copy-to-eax 1/imm32/true +7698 eb/jump $operand-matches-primitive?:end/disp8 +7699 $operand-matches-primitive?:return-false: +7700 b8/copy-to-eax 0/imm32/false +7701 $operand-matches-primitive?:end: +7702 # . restore registers +7703 5f/pop-to-edi +7704 5e/pop-to-esi +7705 59/pop-to-ecx +7706 # . epilogue +7707 89/<- %esp 5/r32/ebp +7708 5d/pop-to-ebp +7709 c3/return +7710 +7711 subx-type-equal?: # a: (handle tree type-id), b: (handle tree type-id) -> result/eax: boolean +7712 # . prologue +7713 55/push-ebp +7714 89/<- %ebp 4/r32/esp +7715 # . save registers +7716 51/push-ecx +7717 # var alit/ecx: boolean = is-literal-type?(a) +7718 (is-literal-type? *(ebp+8)) # => eax +7719 89/<- %ecx 0/r32/eax +7720 # var blit/eax: boolean = is-literal-type?(b) +7721 (is-literal-type? *(ebp+0xc)) # => eax +7722 # return alit == blit +7723 39/compare %eax 1/r32/ecx +7724 74/jump-if-= $subx-type-equal?:true/disp8 +7725 $subx-type-equal?:false: +7726 b8/copy-to-eax 0/imm32/false +7727 eb/jump $subx-type-equal?:end/disp8 +7728 $subx-type-equal?:true: +7729 b8/copy-to-eax 1/imm32/true +7730 $subx-type-equal?:end: +7731 # . restore registers +7732 59/pop-to-ecx +7733 # . epilogue +7734 89/<- %esp 5/r32/ebp +7735 5d/pop-to-ebp +7736 c3/return +7737 +7738 is-literal-type?: # a: (handle tree type-id) -> result/eax: boolean +7739 # . prologue +7740 55/push-ebp +7741 89/<- %ebp 4/r32/esp +7742 # +7743 8b/-> *(ebp+8) 0/r32/eax +7744 8b/-> *eax 0/r32/eax # Atom-value +7745 3d/compare-eax-and 0/imm32/false +7746 74/jump-if-equal $is-literal-type?:end/disp8 +7747 b8/copy-to-eax 1/imm32/true +7748 $is-literal-type?:end: +7749 # . epilogue +7750 89/<- %esp 5/r32/ebp +7751 5d/pop-to-ebp +7752 c3/return +7753 +7754 test-emit-subx-statement-primitive: +7755 # Primitive operation on a variable on the stack. +7756 # increment foo +7757 # => +7758 # ff 0/subop/increment *(ebp-8) +7759 # +7760 # There's a variable on the var stack as follows: +7761 # name: 'foo' +7762 # type: int +7763 # stack-offset: -8 +7764 # +7765 # There's a primitive with this info: +7766 # name: 'increment' +7767 # inouts: int/mem +7768 # value: 'ff 0/subop/increment' +7769 # +7770 # There's nothing in functions. +7771 # +7772 # . prologue +7773 55/push-ebp +7774 89/<- %ebp 4/r32/esp +7775 # setup +7776 (clear-stream _test-output-stream) +7777 (clear-stream $_test-output-buffered-file->buffer) +7778 # var type/ecx: (handle tree type-id) = int +7779 68/push 0/imm32/right/null +7780 68/push 1/imm32/left/int +7781 89/<- %ecx 4/r32/esp +7782 # var var-foo/ecx: var +7783 68/push 0/imm32/no-register +7784 68/push -8/imm32/stack-offset +7785 68/push 1/imm32/block-depth +7786 51/push-ecx +7787 68/push "foo"/imm32 +7788 89/<- %ecx 4/r32/esp +7789 # var operand/ebx: (handle stmt-var) +7790 68/push 0/imm32/is-deref:false +7791 68/push 0/imm32/next +7792 51/push-ecx/var-foo +7793 89/<- %ebx 4/r32/esp +7794 # var stmt/esi: statement +7795 68/push 0/imm32/next +7796 68/push 0/imm32/outputs +7797 53/push-ebx/operands +7798 68/push "increment"/imm32/operation +7799 68/push 1/imm32 +7800 89/<- %esi 4/r32/esp +7801 # var primitives/ebx: primitive +7802 68/push 0/imm32/next +7803 68/push 0/imm32/output-is-write-only +7804 68/push 0/imm32/no-disp32 +7805 68/push 0/imm32/no-imm32 +7806 68/push 0/imm32/no-r32 +7807 68/push 1/imm32/rm32-is-first-inout +7808 68/push "ff 0/subop/increment"/imm32/subx-name +7809 68/push 0/imm32/outputs +7810 53/push-ebx/inouts # hack; in practice we won't have the same var in function definition and call +7811 68/push "increment"/imm32/name +7812 89/<- %ebx 4/r32/esp +7813 # convert +7814 c7 0/subop/copy *Curr-block-depth 0/imm32 +7815 (emit-subx-statement _test-output-buffered-file %esi %ebx 0) +7816 (flush _test-output-buffered-file) +7817 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +7823 # check output +7824 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment *(ebp+0xfffffff8)" "F - test-emit-subx-statement-primitive") +7825 # . epilogue +7826 89/<- %esp 5/r32/ebp +7827 5d/pop-to-ebp +7828 c3/return +7829 +7830 test-emit-subx-statement-primitive-register: +7831 # Primitive operation on a variable in a register. +7832 # foo <- increment +7833 # => +7834 # ff 0/subop/increment %eax # sub-optimal, but should suffice +7835 # +7836 # There's a variable on the var stack as follows: +7837 # name: 'foo' +7838 # type: int +7839 # register: 'eax' +7840 # +7841 # There's a primitive with this info: +7842 # name: 'increment' +7843 # out: int/reg +7844 # value: 'ff 0/subop/increment' +7845 # +7846 # There's nothing in functions. +7847 # +7848 # . prologue +7849 55/push-ebp +7850 89/<- %ebp 4/r32/esp +7851 # setup +7852 (clear-stream _test-output-stream) +7853 (clear-stream $_test-output-buffered-file->buffer) +7854 # var type/ecx: (handle tree type-id) = int +7855 68/push 0/imm32/right/null +7856 68/push 1/imm32/left/int +7857 89/<- %ecx 4/r32/esp +7858 # var var-foo/ecx: var in eax +7859 68/push "eax"/imm32/register +7860 68/push 0/imm32/no-stack-offset +7861 68/push 1/imm32/block-depth +7862 51/push-ecx +7863 68/push "foo"/imm32 +7864 89/<- %ecx 4/r32/esp +7865 # var operand/ebx: (handle stmt-var) +7866 68/push 0/imm32/is-deref:false +7867 68/push 0/imm32/next +7868 51/push-ecx/var-foo +7869 89/<- %ebx 4/r32/esp +7870 # var stmt/esi: statement +7871 68/push 0/imm32/next +7872 53/push-ebx/outputs +7873 68/push 0/imm32/inouts +7874 68/push "increment"/imm32/operation +7875 68/push 1/imm32 +7876 89/<- %esi 4/r32/esp +7877 # var formal-var/ebx: var in any register +7878 68/push Any-register/imm32 +7879 68/push 0/imm32/no-stack-offset +7880 68/push 1/imm32/block-depth +7881 ff 6/subop/push *(ecx+4) # Var-type +7882 68/push "dummy"/imm32 +7883 89/<- %ebx 4/r32/esp +7884 # var operand/ebx: (handle stmt-var) +7885 68/push 0/imm32/is-deref:false +7886 68/push 0/imm32/next +7887 53/push-ebx/formal-var +7888 89/<- %ebx 4/r32/esp +7889 # var primitives/ebx: primitive +7890 68/push 0/imm32/next +7891 68/push 0/imm32/output-is-write-only +7892 68/push 0/imm32/no-disp32 +7893 68/push 0/imm32/no-imm32 +7894 68/push 0/imm32/no-r32 +7895 68/push 3/imm32/rm32-in-first-output +7896 68/push "ff 0/subop/increment"/imm32/subx-name +7897 53/push-ebx/outputs +7898 68/push 0/imm32/inouts +7899 68/push "increment"/imm32/name +7900 89/<- %ebx 4/r32/esp +7901 # convert +7902 c7 0/subop/copy *Curr-block-depth 0/imm32 +7903 (emit-subx-statement _test-output-buffered-file %esi %ebx 0) +7904 (flush _test-output-buffered-file) +7905 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +7911 # check output +7912 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-statement-primitive-register") +7913 # . epilogue +7914 89/<- %esp 5/r32/ebp +7915 5d/pop-to-ebp +7916 c3/return +7917 +7918 test-emit-subx-statement-select-primitive: +7919 # Select the right primitive between overloads. +7920 # foo <- increment +7921 # => +7922 # ff 0/subop/increment %eax # sub-optimal, but should suffice +7923 # +7924 # There's a variable on the var stack as follows: +7925 # name: 'foo' +7926 # type: int +7927 # register: 'eax' +7928 # +7929 # There's two primitives, as follows: +7930 # - name: 'increment' +7931 # out: int/reg +7932 # value: 'ff 0/subop/increment' +7933 # - name: 'increment' +7934 # inout: int/mem +7935 # value: 'ff 0/subop/increment' +7936 # +7937 # There's nothing in functions. +7938 # +7939 # . prologue +7940 55/push-ebp +7941 89/<- %ebp 4/r32/esp +7942 # setup +7943 (clear-stream _test-output-stream) +7944 (clear-stream $_test-output-buffered-file->buffer) +7945 # var type/ecx: (handle tree type-id) = int +7946 68/push 0/imm32/right/null +7947 68/push 1/imm32/left/int +7948 89/<- %ecx 4/r32/esp +7949 # var var-foo/ecx: var in eax +7950 68/push "eax"/imm32/register +7951 68/push 0/imm32/no-stack-offset +7952 68/push 1/imm32/block-depth +7953 51/push-ecx +7954 68/push "foo"/imm32 +7955 89/<- %ecx 4/r32/esp +7956 # var real-outputs/edi: (handle stmt-var) +7957 68/push 0/imm32/is-deref:false +7958 68/push 0/imm32/next +7959 51/push-ecx/var-foo +7960 89/<- %edi 4/r32/esp +7961 # var stmt/esi: statement +7962 68/push 0/imm32/next +7963 57/push-edi/outputs +7964 68/push 0/imm32/inouts +7965 68/push "increment"/imm32/operation +7966 68/push 1/imm32 +7967 89/<- %esi 4/r32/esp +7968 # var formal-var/ebx: var in any register +7969 68/push Any-register/imm32 +7970 68/push 0/imm32/no-stack-offset +7971 68/push 1/imm32/block-depth +7972 ff 6/subop/push *(ecx+4) # Var-type +7973 68/push "dummy"/imm32 +7974 89/<- %ebx 4/r32/esp +7975 # var formal-outputs/ebx: (handle stmt-var) +7976 68/push 0/imm32/is-deref:false +7977 68/push 0/imm32/next +7978 53/push-ebx/formal-var +7979 89/<- %ebx 4/r32/esp +7980 # var primitive1/ebx: primitive +7981 68/push 0/imm32/next +7982 68/push 0/imm32/output-is-write-only +7983 68/push 0/imm32/no-disp32 +7984 68/push 0/imm32/no-imm32 +7985 68/push 0/imm32/no-r32 +7986 68/push 3/imm32/rm32-in-first-output +7987 68/push "ff 0/subop/increment"/imm32/subx-name +7988 53/push-ebx/outputs/formal-outputs +7989 68/push 0/imm32/inouts +7990 68/push "increment"/imm32/name +7991 89/<- %ebx 4/r32/esp +7992 # var primitives/ebx: primitive +7993 53/push-ebx/next +7994 68/push 0/imm32/output-is-write-only +7995 68/push 0/imm32/no-disp32 +7996 68/push 0/imm32/no-imm32 +7997 68/push 0/imm32/no-r32 +7998 68/push 1/imm32/rm32-is-first-inout +7999 68/push "ff 0/subop/increment"/imm32/subx-name +8000 68/push 0/imm32/outputs +8001 57/push-edi/inouts/real-outputs # hack; in practice we won't have the same var in function definition and call +8002 68/push "increment"/imm32/name +8003 89/<- %ebx 4/r32/esp +8004 # convert +8005 c7 0/subop/copy *Curr-block-depth 0/imm32 +8006 (emit-subx-statement _test-output-buffered-file %esi %ebx 0) +8007 (flush _test-output-buffered-file) +8008 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +8014 # check output +8015 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-statement-select-primitive") +8016 # . epilogue +8017 89/<- %esp 5/r32/ebp +8018 5d/pop-to-ebp +8019 c3/return +8020 +8021 test-emit-subx-statement-select-primitive-2: +8022 # Select the right primitive between overloads. +8023 # foo <- increment +8024 # => +8025 # ff 0/subop/increment %eax # sub-optimal, but should suffice +8026 # +8027 # There's a variable on the var stack as follows: +8028 # name: 'foo' +8029 # type: int +8030 # register: 'eax' +8031 # +8032 # There's two primitives, as follows: +8033 # - name: 'increment' +8034 # out: int/reg +8035 # value: 'ff 0/subop/increment' +8036 # - name: 'increment' +8037 # inout: int/mem +8038 # value: 'ff 0/subop/increment' +8039 # +8040 # There's nothing in functions. +8041 # +8042 # . prologue +8043 55/push-ebp +8044 89/<- %ebp 4/r32/esp +8045 # setup +8046 (clear-stream _test-output-stream) +8047 (clear-stream $_test-output-buffered-file->buffer) +8048 # var type/ecx: (handle tree type-id) = int +8049 68/push 0/imm32/right/null +8050 68/push 1/imm32/left/int +8051 89/<- %ecx 4/r32/esp +8052 # var var-foo/ecx: var in eax +8053 68/push "eax"/imm32/register +8054 68/push 0/imm32/no-stack-offset +8055 68/push 1/imm32/block-depth +8056 51/push-ecx +8057 68/push "foo"/imm32 +8058 89/<- %ecx 4/r32/esp +8059 # var inouts/edi: (handle stmt-var) +8060 68/push 0/imm32/is-deref:false +8061 68/push 0/imm32/next +8062 51/push-ecx/var-foo +8063 89/<- %edi 4/r32/esp +8064 # var stmt/esi: statement +8065 68/push 0/imm32/next +8066 68/push 0/imm32/outputs +8067 57/push-edi/inouts +8068 68/push "increment"/imm32/operation +8069 68/push 1/imm32 +8070 89/<- %esi 4/r32/esp +8071 # var formal-var/ebx: var in any register +8072 68/push Any-register/imm32 +8073 68/push 0/imm32/no-stack-offset +8074 68/push 1/imm32/block-depth +8075 ff 6/subop/push *(ecx+4) # Var-type +8076 68/push "dummy"/imm32 +8077 89/<- %ebx 4/r32/esp +8078 # var operand/ebx: (handle stmt-var) +8079 68/push 0/imm32/is-deref:false +8080 68/push 0/imm32/next +8081 53/push-ebx/formal-var +8082 89/<- %ebx 4/r32/esp +8083 # var primitive1/ebx: primitive +8084 68/push 0/imm32/next +8085 68/push 0/imm32/output-is-write-only +8086 68/push 0/imm32/no-disp32 +8087 68/push 0/imm32/no-imm32 +8088 68/push 0/imm32/no-r32 +8089 68/push 3/imm32/rm32-in-first-output +8090 68/push "ff 0/subop/increment"/imm32/subx-name +8091 53/push-ebx/outputs/formal-outputs +8092 68/push 0/imm32/inouts +8093 68/push "increment"/imm32/name +8094 89/<- %ebx 4/r32/esp +8095 # var primitives/ebx: primitive +8096 53/push-ebx/next +8097 68/push 0/imm32/output-is-write-only +8098 68/push 0/imm32/no-disp32 +8099 68/push 0/imm32/no-imm32 +8100 68/push 0/imm32/no-r32 +8101 68/push 1/imm32/rm32-is-first-inout +8102 68/push "ff 0/subop/increment"/imm32/subx-name +8103 68/push 0/imm32/outputs +8104 57/push-edi/inouts/real-outputs # hack; in practice we won't have the same var in function definition and call +8105 68/push "increment"/imm32/name +8106 89/<- %ebx 4/r32/esp +8107 # convert +8108 c7 0/subop/copy *Curr-block-depth 0/imm32 +8109 (emit-subx-statement _test-output-buffered-file %esi %ebx 0) +8110 (flush _test-output-buffered-file) +8111 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +8117 # check output +8118 (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-statement-select-primitive-2") +8119 # . epilogue +8120 89/<- %esp 5/r32/ebp +8121 5d/pop-to-ebp +8122 c3/return +8123 +8124 test-increment-register: +8125 # Select the right register between overloads. +8126 # foo <- increment +8127 # => +8128 # 50/increment-eax +8129 # +8130 # There's a variable on the var stack as follows: +8131 # name: 'foo' +8132 # type: int +8133 # register: 'eax' +8134 # +8135 # Primitives are the global definitions. +8136 # +8137 # There are no functions defined. +8138 # +8139 # . prologue +8140 55/push-ebp +8141 89/<- %ebp 4/r32/esp +8142 # setup +8143 (clear-stream _test-output-stream) +8144 (clear-stream $_test-output-buffered-file->buffer) +8145 # var type/ecx: (handle tree type-id) = int +8146 68/push 0/imm32/right/null +8147 68/push 1/imm32/left/int +8148 89/<- %ecx 4/r32/esp +8149 # var var-foo/ecx: var in eax +8150 68/push "eax"/imm32/register +8151 68/push 0/imm32/no-stack-offset +8152 68/push 1/imm32/block-depth +8153 51/push-ecx +8154 68/push "foo"/imm32 +8155 89/<- %ecx 4/r32/esp +8156 # var real-outputs/edi: (handle stmt-var) +8157 68/push 0/imm32/is-deref:false +8158 68/push 0/imm32/next +8159 51/push-ecx/var-foo +8160 89/<- %edi 4/r32/esp +8161 # var stmt/esi: statement +8162 68/push 0/imm32/next +8163 57/push-edi/outputs +8164 68/push 0/imm32/inouts +8165 68/push "increment"/imm32/operation +8166 68/push 1/imm32/regular-statement +8167 89/<- %esi 4/r32/esp +8168 # convert +8169 c7 0/subop/copy *Curr-block-depth 0/imm32 +8170 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) +8171 (flush _test-output-buffered-file) +8172 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +8178 # check output +8179 (check-next-stream-line-equal _test-output-stream "40/increment-eax" "F - test-increment-register") +8180 # . epilogue +8181 89/<- %esp 5/r32/ebp +8182 5d/pop-to-ebp +8183 c3/return +8184 +8185 test-increment-var: +8186 # Select the right primitive between overloads. +8187 # foo <- increment +8188 # => +8189 # ff 0/subop/increment %eax # sub-optimal, but should suffice +8190 # +8191 # There's a variable on the var stack as follows: +8192 # name: 'foo' +8193 # type: int +8194 # register: 'eax' +8195 # +8196 # Primitives are the global definitions. +8197 # +8198 # There are no functions defined. +8199 # +8200 # . prologue +8201 55/push-ebp +8202 89/<- %ebp 4/r32/esp +8203 # setup +8204 (clear-stream _test-output-stream) +8205 (clear-stream $_test-output-buffered-file->buffer) +8206 # var type/ecx: (handle tree type-id) = int +8207 68/push 0/imm32/right/null +8208 68/push 1/imm32/left/int +8209 89/<- %ecx 4/r32/esp +8210 # var var-foo/ecx: var in eax +8211 68/push "eax"/imm32/register +8212 68/push 0/imm32/no-stack-offset +8213 68/push 1/imm32/block-depth +8214 51/push-ecx +8215 68/push "foo"/imm32 +8216 89/<- %ecx 4/r32/esp +8217 # var inouts/edi: (handle stmt-var) +8218 68/push 0/imm32/is-deref:false +8219 68/push 0/imm32/next +8220 51/push-ecx/var-foo +8221 89/<- %edi 4/r32/esp +8222 # var stmt/esi: statement +8223 68/push 0/imm32/next +8224 57/push-edi/outputs +8225 68/push 0/imm32/inouts +8226 68/push "increment"/imm32/operation +8227 68/push 1/imm32 +8228 89/<- %esi 4/r32/esp +8229 # convert +8230 c7 0/subop/copy *Curr-block-depth 0/imm32 +8231 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) +8232 (flush _test-output-buffered-file) +8233 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +8239 # check output +8240 (check-next-stream-line-equal _test-output-stream "40/increment-eax" "F - test-increment-var") +8241 # . epilogue +8242 89/<- %esp 5/r32/ebp +8243 5d/pop-to-ebp +8244 c3/return +8245 +8246 test-add-reg-to-reg: +8247 # var1/reg <- add var2/reg +8248 # => +8249 # 01/add %var1 var2 +8250 # +8251 # . prologue +8252 55/push-ebp +8253 89/<- %ebp 4/r32/esp +8254 # setup +8255 (clear-stream _test-output-stream) +8256 (clear-stream $_test-output-buffered-file->buffer) +8257 # var type/ecx: (handle tree type-id) = int +8258 68/push 0/imm32/right/null +8259 68/push 1/imm32/left/int +8260 89/<- %ecx 4/r32/esp +8261 # var var-var1/ecx: var in eax +8262 68/push "eax"/imm32/register +8263 68/push 0/imm32/no-stack-offset +8264 68/push 1/imm32/block-depth +8265 51/push-ecx +8266 68/push "var1"/imm32 +8267 89/<- %ecx 4/r32/esp +8268 # var var-var2/edx: var in ecx +8269 68/push "ecx"/imm32/register +8270 68/push 0/imm32/no-stack-offset +8271 68/push 1/imm32/block-depth +8272 ff 6/subop/push *(ecx+4) # Var-type +8273 68/push "var2"/imm32 +8274 89/<- %edx 4/r32/esp +8275 # var inouts/esi: (handle stmt-var) = [var2] +8276 68/push 0/imm32/is-deref:false +8277 68/push 0/imm32/next +8278 52/push-edx/var-var2 +8279 89/<- %esi 4/r32/esp +8280 # var outputs/edi: (handle stmt-var) = [var1, var2] +8281 68/push 0/imm32/is-deref:false +8282 68/push 0/imm32/next +8283 51/push-ecx/var-var1 +8284 89/<- %edi 4/r32/esp +8285 # var stmt/esi: statement +8286 68/push 0/imm32/next +8287 57/push-edi/outputs +8288 56/push-esi/inouts +8289 68/push "add"/imm32/operation +8290 68/push 1/imm32 +8291 89/<- %esi 4/r32/esp +8292 # convert +8293 c7 0/subop/copy *Curr-block-depth 0/imm32 +8294 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) +8295 (flush _test-output-buffered-file) +8296 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +8302 # check output +8303 (check-next-stream-line-equal _test-output-stream "01/add-to %eax 0x00000001/r32" "F - test-add-reg-to-reg") +8304 # . epilogue +8305 89/<- %esp 5/r32/ebp +8306 5d/pop-to-ebp +8307 c3/return +8308 +8309 test-add-reg-to-mem: +8310 # add-to var1 var2/reg +8311 # => +8312 # 01/add *(ebp+__) var2 +8313 # +8314 # . prologue +8315 55/push-ebp +8316 89/<- %ebp 4/r32/esp +8317 # setup +8318 (clear-stream _test-output-stream) +8319 (clear-stream $_test-output-buffered-file->buffer) +8320 # var type/ecx: (handle tree type-id) = int +8321 68/push 0/imm32/right/null +8322 68/push 1/imm32/left/int +8323 89/<- %ecx 4/r32/esp +8324 # var var-var1/ecx: var +8325 68/push 0/imm32/no-register +8326 68/push 8/imm32/stack-offset +8327 68/push 1/imm32/block-depth +8328 51/push-ecx +8329 68/push "var1"/imm32 +8330 89/<- %ecx 4/r32/esp +8331 # var var-var2/edx: var in ecx +8332 68/push "ecx"/imm32/register +8333 68/push 0/imm32/no-stack-offset +8334 68/push 1/imm32/block-depth +8335 ff 6/subop/push *(ecx+4) # Var-type +8336 68/push "var2"/imm32 +8337 89/<- %edx 4/r32/esp +8338 # var inouts/esi: (handle stmt-var) = [var2] +8339 68/push 0/imm32/is-deref:false +8340 68/push 0/imm32/next +8341 52/push-edx/var-var2 +8342 89/<- %esi 4/r32/esp +8343 # var inouts = (handle stmt-var) = [var1, var2] +8344 56/push-esi/next +8345 51/push-ecx/var-var1 +8346 89/<- %esi 4/r32/esp +8347 # var stmt/esi: statement +8348 68/push 0/imm32/next +8349 68/push 0/imm32/outputs +8350 56/push-esi/inouts +8351 68/push "add-to"/imm32/operation +8352 68/push 1/imm32 +8353 89/<- %esi 4/r32/esp +8354 # convert +8355 c7 0/subop/copy *Curr-block-depth 0/imm32 +8356 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) +8357 (flush _test-output-buffered-file) +8358 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +8364 # check output +8365 (check-next-stream-line-equal _test-output-stream "01/add-to *(ebp+0x00000008) 0x00000001/r32" "F - test-add-reg-to-mem") +8366 # . epilogue +8367 89/<- %esp 5/r32/ebp +8368 5d/pop-to-ebp +8369 c3/return +8370 +8371 test-add-mem-to-reg: +8372 # var1/reg <- add var2 +8373 # => +8374 # 03/add *(ebp+__) var1 +8375 # +8376 # . prologue +8377 55/push-ebp +8378 89/<- %ebp 4/r32/esp +8379 # setup +8380 (clear-stream _test-output-stream) +8381 (clear-stream $_test-output-buffered-file->buffer) +8382 # var type/ecx: (handle tree type-id) = int +8383 68/push 0/imm32/right/null +8384 68/push 1/imm32/left/int +8385 89/<- %ecx 4/r32/esp +8386 # var var-var1/ecx: var in eax +8387 68/push "eax"/imm32/register +8388 68/push 0/imm32/no-stack-offset +8389 68/push 1/imm32/block-depth +8390 51/push-ecx +8391 68/push "var1"/imm32 +8392 89/<- %ecx 4/r32/esp +8393 # var var-var2/edx: var +8394 68/push 0/imm32/no-register +8395 68/push 8/imm32/stack-offset +8396 68/push 1/imm32/block-depth +8397 ff 6/subop/push *(ecx+4) # Var-type +8398 68/push "var2"/imm32 +8399 89/<- %edx 4/r32/esp +8400 # var inouts/esi: (handle stmt-var) = [var2] +8401 68/push 0/imm32/is-deref:false +8402 68/push 0/imm32/next +8403 52/push-edx/var-var2 +8404 89/<- %esi 4/r32/esp +8405 # var outputs/edi = (handle stmt-var) = [var1] +8406 68/push 0/imm32/is-deref:false +8407 68/push 0/imm32/next +8408 51/push-ecx/var-var1 +8409 89/<- %edi 4/r32/esp +8410 # var stmt/esi: statement +8411 68/push 0/imm32/next +8412 57/push-edi/outputs +8413 56/push-esi/inouts +8414 68/push "add"/imm32/operation +8415 68/push 1/imm32 +8416 89/<- %esi 4/r32/esp +8417 # convert +8418 c7 0/subop/copy *Curr-block-depth 0/imm32 +8419 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) +8420 (flush _test-output-buffered-file) +8421 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +8427 # check output +8428 (check-next-stream-line-equal _test-output-stream "03/add *(ebp+0x00000008) 0x00000000/r32" "F - test-add-mem-to-reg") +8429 # . epilogue +8430 89/<- %esp 5/r32/ebp +8431 5d/pop-to-ebp +8432 c3/return +8433 +8434 test-add-literal-to-eax: +8435 # var1/eax <- add 0x34 +8436 # => +8437 # 05/add-to-eax 0x34/imm32 +8438 # +8439 # . prologue +8440 55/push-ebp +8441 89/<- %ebp 4/r32/esp +8442 # setup +8443 (clear-stream _test-output-stream) +8444 (clear-stream $_test-output-buffered-file->buffer) +8445 # var type/ecx: (handle tree type-id) = int +8446 68/push 0/imm32/right/null +8447 68/push 1/imm32/left/int +8448 89/<- %ecx 4/r32/esp +8449 # var var-var1/ecx: var in eax +8450 68/push "eax"/imm32/register +8451 68/push 0/imm32/no-stack-offset +8452 68/push 1/imm32/block-depth +8453 51/push-ecx +8454 68/push "var1"/imm32 +8455 89/<- %ecx 4/r32/esp +8456 # var type/edx: (handle tree type-id) = literal +8457 68/push 0/imm32/right/null +8458 68/push 0/imm32/left/literal +8459 89/<- %edx 4/r32/esp +8460 # var var-var2/edx: var literal +8461 68/push 0/imm32/no-register +8462 68/push 0/imm32/no-stack-offset +8463 68/push 1/imm32/block-depth +8464 52/push-edx +8465 68/push "0x34"/imm32 +8466 89/<- %edx 4/r32/esp +8467 # var inouts/esi: (handle stmt-var) = [var2] +8468 68/push 0/imm32/is-deref:false +8469 68/push 0/imm32/next +8470 52/push-edx/var-var2 +8471 89/<- %esi 4/r32/esp +8472 # var outputs/edi: (handle stmt-var) = [var1] +8473 68/push 0/imm32/is-deref:false +8474 68/push 0/imm32/next +8475 51/push-ecx/var-var1 +8476 89/<- %edi 4/r32/esp +8477 # var stmt/esi: statement +8478 68/push 0/imm32/next +8479 57/push-edi/outputs +8480 56/push-esi/inouts +8481 68/push "add"/imm32/operation +8482 68/push 1/imm32 +8483 89/<- %esi 4/r32/esp +8484 # convert +8485 c7 0/subop/copy *Curr-block-depth 0/imm32 +8486 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) +8487 (flush _test-output-buffered-file) +8488 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +8494 # check output +8495 (check-next-stream-line-equal _test-output-stream "05/add-to-eax 0x34/imm32" "F - test-add-literal-to-eax") +8496 # . epilogue +8497 89/<- %esp 5/r32/ebp +8498 5d/pop-to-ebp +8499 c3/return +8500 +8501 test-add-literal-to-reg: +8502 # var1/ecx <- add 0x34 +8503 # => +8504 # 81 0/subop/add %ecx 0x34/imm32 +8505 # +8506 # . prologue +8507 55/push-ebp +8508 89/<- %ebp 4/r32/esp +8509 # setup +8510 (clear-stream _test-output-stream) +8511 (clear-stream $_test-output-buffered-file->buffer) +8512 # var type/ecx: (handle tree type-id) = int +8513 68/push 0/imm32/right/null +8514 68/push 1/imm32/left/int +8515 89/<- %ecx 4/r32/esp +8516 # var var-var1/ecx: var in ecx +8517 68/push "ecx"/imm32/register +8518 68/push 0/imm32/no-stack-offset +8519 68/push 1/imm32/block-depth +8520 51/push-ecx +8521 68/push "var1"/imm32 +8522 89/<- %ecx 4/r32/esp +8523 # var type/edx: (handle tree type-id) = literal +8524 68/push 0/imm32/right/null +8525 68/push 0/imm32/left/literal +8526 89/<- %edx 4/r32/esp +8527 # var var-var2/edx: var literal +8528 68/push 0/imm32/no-register +8529 68/push 0/imm32/no-stack-offset +8530 68/push 1/imm32/block-depth +8531 52/push-edx +8532 68/push "0x34"/imm32 +8533 89/<- %edx 4/r32/esp +8534 # var inouts/esi: (handle stmt-var) = [var2] +8535 68/push 0/imm32/is-deref:false +8536 68/push 0/imm32/next +8537 52/push-edx/var-var2 +8538 89/<- %esi 4/r32/esp +8539 # var outputs/edi: (handle stmt-var) = [var1] +8540 68/push 0/imm32/is-deref:false +8541 68/push 0/imm32/next +8542 51/push-ecx/var-var1 +8543 89/<- %edi 4/r32/esp +8544 # var stmt/esi: statement +8545 68/push 0/imm32/next +8546 57/push-edi/outputs +8547 56/push-esi/inouts +8548 68/push "add"/imm32/operation +8549 68/push 1/imm32 +8550 89/<- %esi 4/r32/esp +8551 # convert +8552 c7 0/subop/copy *Curr-block-depth 0/imm32 +8553 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) +8554 (flush _test-output-buffered-file) +8555 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +8561 # check output +8562 (check-next-stream-line-equal _test-output-stream "81 0/subop/add %ecx 0x34/imm32" "F - test-add-literal-to-reg") +8563 # . epilogue +8564 89/<- %esp 5/r32/ebp +8565 5d/pop-to-ebp +8566 c3/return +8567 +8568 test-add-literal-to-mem: +8569 # add-to var1, 0x34 +8570 # => +8571 # 81 0/subop/add %eax 0x34/imm32 +8572 # +8573 # . prologue +8574 55/push-ebp +8575 89/<- %ebp 4/r32/esp +8576 # setup +8577 (clear-stream _test-output-stream) +8578 (clear-stream $_test-output-buffered-file->buffer) +8579 # var type/ecx: (handle tree type-id) = int +8580 68/push 0/imm32/right/null +8581 68/push 1/imm32/left/int +8582 89/<- %ecx 4/r32/esp +8583 # var var-var1/ecx: var +8584 68/push 0/imm32/no-register +8585 68/push 8/imm32/stack-offset +8586 68/push 1/imm32/block-depth +8587 51/push-ecx +8588 68/push "var1"/imm32 +8589 89/<- %ecx 4/r32/esp +8590 # var type/edx: (handle tree type-id) = literal +8591 68/push 0/imm32/right/null +8592 68/push 0/imm32/left/literal +8593 89/<- %edx 4/r32/esp +8594 # var var-var2/edx: var literal +8595 68/push 0/imm32/no-register +8596 68/push 0/imm32/no-stack-offset +8597 68/push 1/imm32/block-depth +8598 52/push-edx +8599 68/push "0x34"/imm32 +8600 89/<- %edx 4/r32/esp +8601 # var inouts/esi: (handle stmt-var) = [var2] +8602 68/push 0/imm32/is-deref:false +8603 68/push 0/imm32/next +8604 52/push-edx/var-var2 +8605 89/<- %esi 4/r32/esp +8606 # var inouts = (handle stmt-var) = [var1, var2] +8607 68/push 0/imm32/is-deref:false +8608 56/push-esi/next +8609 51/push-ecx/var-var1 +8610 89/<- %esi 4/r32/esp +8611 # var stmt/esi: statement +8612 68/push 0/imm32/next +8613 68/push 0/imm32/outputs +8614 56/push-esi/inouts +8615 68/push "add-to"/imm32/operation +8616 68/push 1/imm32 +8617 89/<- %esi 4/r32/esp +8618 # convert +8619 c7 0/subop/copy *Curr-block-depth 0/imm32 +8620 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) +8621 (flush _test-output-buffered-file) +8622 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +8628 # check output +8629 (check-next-stream-line-equal _test-output-stream "81 0/subop/add *(ebp+0x00000008) 0x34/imm32" "F - test-add-literal-to-mem") +8630 # . epilogue +8631 89/<- %esp 5/r32/ebp +8632 5d/pop-to-ebp +8633 c3/return +8634 +8635 test-compare-mem-with-reg: +8636 # compare var1, var2/eax +8637 # => +8638 # 39/compare *(ebp+___) 0/r32/eax +8639 # +8640 # . prologue +8641 55/push-ebp +8642 89/<- %ebp 4/r32/esp +8643 # setup +8644 (clear-stream _test-output-stream) +8645 (clear-stream $_test-output-buffered-file->buffer) +8646 # var type/ecx: (handle tree type-id) = int +8647 68/push 0/imm32/right/null +8648 68/push 1/imm32/left/int +8649 89/<- %ecx 4/r32/esp +8650 # var var-var2/ecx: var in eax +8651 68/push "eax"/imm32/register +8652 68/push 0/imm32/no-stack-offset +8653 68/push 1/imm32/block-depth +8654 51/push-ecx +8655 68/push "var2"/imm32 +8656 89/<- %ecx 4/r32/esp +8657 # var var-var1/edx: var +8658 68/push 0/imm32/no-register +8659 68/push 8/imm32/stack-offset +8660 68/push 1/imm32/block-depth +8661 ff 6/subop/push *(ecx+4) # Var-type +8662 68/push "var1"/imm32 +8663 89/<- %edx 4/r32/esp +8664 # var inouts/esi: (handle stmt-var) = [var2] +8665 68/push 0/imm32/is-deref:false +8666 68/push 0/imm32/next +8667 51/push-ecx/var-var2 +8668 89/<- %esi 4/r32/esp +8669 # inouts = [var1, var2] +8670 68/push 0/imm32/is-deref:false +8671 56/push-esi +8672 52/push-edx/var-var1 +8673 89/<- %esi 4/r32/esp +8674 # var stmt/esi: statement +8675 68/push 0/imm32/next +8676 68/push 0/imm32/outputs +8677 56/push-esi/inouts +8678 68/push "compare"/imm32/operation +8679 68/push 1/imm32 +8680 89/<- %esi 4/r32/esp +8681 # convert +8682 c7 0/subop/copy *Curr-block-depth 0/imm32 +8683 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) +8684 (flush _test-output-buffered-file) +8685 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +8691 # check output +8692 (check-next-stream-line-equal _test-output-stream "39/compare-> *(ebp+0x00000008) 0x00000000/r32" "F - test-compare-mem-with-reg") +8693 # . epilogue +8694 89/<- %esp 5/r32/ebp +8695 5d/pop-to-ebp +8696 c3/return +8697 +8698 test-compare-reg-with-mem: +8699 # compare var1/eax, var2 +8700 # => +8701 # 3b/compare *(ebp+___) 0/r32/eax +8702 # +8703 # . prologue +8704 55/push-ebp +8705 89/<- %ebp 4/r32/esp +8706 # setup +8707 (clear-stream _test-output-stream) +8708 (clear-stream $_test-output-buffered-file->buffer) +8709 # var type/ecx: (handle tree type-id) = int +8710 68/push 0/imm32/right/null +8711 68/push 1/imm32/left/int +8712 89/<- %ecx 4/r32/esp +8713 # var var-var1/ecx: var in eax +8714 68/push "eax"/imm32/register +8715 68/push 0/imm32/no-stack-offset +8716 68/push 1/imm32/block-depth +8717 51/push-ecx +8718 68/push "var1"/imm32 +8719 89/<- %ecx 4/r32/esp +8720 # var var-var2/edx: var +8721 68/push 0/imm32/no-register +8722 68/push 8/imm32/stack-offset +8723 68/push 1/imm32/block-depth +8724 ff 6/subop/push *(ecx+4) # Var-type +8725 68/push "var2"/imm32 +8726 89/<- %edx 4/r32/esp +8727 # var inouts/esi: (handle stmt-var) = [var2] +8728 68/push 0/imm32/is-deref:false +8729 68/push 0/imm32/next +8730 52/push-edx/var-var2 +8731 89/<- %esi 4/r32/esp +8732 # inouts = [var1, var2] +8733 68/push 0/imm32/is-deref:false +8734 56/push-esi +8735 51/push-ecx/var-var1 +8736 89/<- %esi 4/r32/esp +8737 # var stmt/esi: statement +8738 68/push 0/imm32/next +8739 68/push 0/imm32/outputs +8740 56/push-esi/inouts +8741 68/push "compare"/imm32/operation +8742 68/push 1/imm32 +8743 89/<- %esi 4/r32/esp +8744 # convert +8745 c7 0/subop/copy *Curr-block-depth 0/imm32 +8746 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) +8747 (flush _test-output-buffered-file) +8748 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +8754 # check output +8755 (check-next-stream-line-equal _test-output-stream "3b/compare<- *(ebp+0x00000008) 0x00000000/r32" "F - test-compare-reg-with-mem") +8756 # . epilogue +8757 89/<- %esp 5/r32/ebp +8758 5d/pop-to-ebp +8759 c3/return +8760 +8761 test-compare-mem-with-literal: +8762 # compare var1, 0x34 +8763 # => +8764 # 81 7/subop/compare *(ebp+___) 0x34/imm32 +8765 # +8766 # . prologue +8767 55/push-ebp +8768 89/<- %ebp 4/r32/esp +8769 # setup +8770 (clear-stream _test-output-stream) +8771 (clear-stream $_test-output-buffered-file->buffer) +8772 # var type/ecx: (handle tree type-id) = int +8773 68/push 0/imm32/right/null +8774 68/push 1/imm32/left/int +8775 89/<- %ecx 4/r32/esp +8776 # var var-var1/ecx: var +8777 68/push 0/imm32/no-register +8778 68/push 8/imm32/stack-offset +8779 68/push 1/imm32/block-depth +8780 51/push-ecx +8781 68/push "var1"/imm32 +8782 89/<- %ecx 4/r32/esp +8783 # var type/edx: (handle tree type-id) = literal +8784 68/push 0/imm32/right/null +8785 68/push 0/imm32/left/literal +8786 89/<- %edx 4/r32/esp +8787 # var var-var2/edx: var literal +8788 68/push 0/imm32/no-register +8789 68/push 0/imm32/no-stack-offset +8790 68/push 1/imm32/block-depth +8791 52/push-edx +8792 68/push "0x34"/imm32 +8793 89/<- %edx 4/r32/esp +8794 # var inouts/esi: (handle stmt-var) = [var2] +8795 68/push 0/imm32/is-deref:false +8796 68/push 0/imm32/next +8797 52/push-edx/var-var2 +8798 89/<- %esi 4/r32/esp +8799 # inouts = [var1, var2] +8800 68/push 0/imm32/is-deref:false +8801 56/push-esi/next +8802 51/push-ecx/var-var1 +8803 89/<- %esi 4/r32/esp +8804 # var stmt/esi: statement +8805 68/push 0/imm32/next +8806 68/push 0/imm32/outputs +8807 56/push-esi/inouts +8808 68/push "compare"/imm32/operation +8809 68/push 1/imm32 +8810 89/<- %esi 4/r32/esp +8811 # convert +8812 c7 0/subop/copy *Curr-block-depth 0/imm32 +8813 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) +8814 (flush _test-output-buffered-file) +8815 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +8821 # check output +8822 (check-next-stream-line-equal _test-output-stream "81 7/subop/compare *(ebp+0x00000008) 0x34/imm32" "F - test-compare-mem-with-literal") +8823 # . epilogue +8824 89/<- %esp 5/r32/ebp +8825 5d/pop-to-ebp +8826 c3/return +8827 +8828 test-compare-eax-with-literal: +8829 # compare var1/eax 0x34 +8830 # => +8831 # 3d/compare-eax-with 0x34/imm32 +8832 # +8833 # . prologue +8834 55/push-ebp +8835 89/<- %ebp 4/r32/esp +8836 # setup +8837 (clear-stream _test-output-stream) +8838 (clear-stream $_test-output-buffered-file->buffer) +8839 # var type/ecx: (handle tree type-id) = int +8840 68/push 0/imm32/right/null +8841 68/push 1/imm32/left/int +8842 89/<- %ecx 4/r32/esp +8843 # var var-var1/ecx: var in eax +8844 68/push "eax"/imm32/register +8845 68/push 0/imm32/no-stack-offset +8846 68/push 1/imm32/block-depth +8847 51/push-ecx +8848 68/push "var1"/imm32 +8849 89/<- %ecx 4/r32/esp +8850 # var type/edx: (handle tree type-id) = literal +8851 68/push 0/imm32/right/null +8852 68/push 0/imm32/left/literal +8853 89/<- %edx 4/r32/esp +8854 # var var-var2/edx: var literal +8855 68/push 0/imm32/no-register +8856 68/push 0/imm32/no-stack-offset +8857 68/push 1/imm32/block-depth +8858 52/push-edx +8859 68/push "0x34"/imm32 +8860 89/<- %edx 4/r32/esp +8861 # var inouts/esi: (handle stmt-var) = [var2] +8862 68/push 0/imm32/is-deref:false +8863 68/push 0/imm32/next +8864 52/push-edx/var-var2 +8865 89/<- %esi 4/r32/esp +8866 # inouts = [var1, var2] +8867 68/push 0/imm32/is-deref:false +8868 56/push-esi/next +8869 51/push-ecx/var-var1 +8870 89/<- %esi 4/r32/esp +8871 # var stmt/esi: statement +8872 68/push 0/imm32/next +8873 68/push 0/imm32/outputs +8874 56/push-esi/inouts +8875 68/push "compare"/imm32/operation +8876 68/push 1/imm32/regular-stmt +8877 89/<- %esi 4/r32/esp +8878 # convert +8879 c7 0/subop/copy *Curr-block-depth 0/imm32 +8880 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) +8881 (flush _test-output-buffered-file) +8882 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +8888 # check output +8889 (check-next-stream-line-equal _test-output-stream "3d/compare-eax-with 0x34/imm32" "F - test-compare-eax-with-literal") +8890 # . epilogue +8891 89/<- %esp 5/r32/ebp +8892 5d/pop-to-ebp +8893 c3/return +8894 +8895 test-compare-reg-with-literal: +8896 # compare var1/ecx 0x34 +8897 # => +8898 # 81 7/subop/compare %ecx 0x34/imm32 +8899 # +8900 # . prologue +8901 55/push-ebp +8902 89/<- %ebp 4/r32/esp +8903 # setup +8904 (clear-stream _test-output-stream) +8905 (clear-stream $_test-output-buffered-file->buffer) +8906 # var type/ecx: (handle tree type-id) = int +8907 68/push 0/imm32/right/null +8908 68/push 1/imm32/left/int +8909 89/<- %ecx 4/r32/esp +8910 # var var-var1/ecx: var in ecx +8911 68/push "ecx"/imm32/register +8912 68/push 0/imm32/no-stack-offset +8913 68/push 1/imm32/block-depth +8914 51/push-ecx +8915 68/push "var1"/imm32 +8916 89/<- %ecx 4/r32/esp +8917 # var type/edx: (handle tree type-id) = literal +8918 68/push 0/imm32/right/null +8919 68/push 0/imm32/left/literal +8920 89/<- %edx 4/r32/esp +8921 # var var-var2/edx: var literal +8922 68/push 0/imm32/no-register +8923 68/push 0/imm32/no-stack-offset +8924 68/push 1/imm32/block-depth +8925 52/push-edx +8926 68/push "0x34"/imm32 +8927 89/<- %edx 4/r32/esp +8928 # var inouts/esi: (handle stmt-var) = [var2] +8929 68/push 0/imm32/is-deref:false +8930 68/push 0/imm32/next +8931 52/push-edx/var-var2 +8932 89/<- %esi 4/r32/esp +8933 # inouts = [var1, var2] +8934 68/push 0/imm32/is-deref:false +8935 56/push-esi/next +8936 51/push-ecx/var-var1 +8937 89/<- %esi 4/r32/esp +8938 # var stmt/esi: statement +8939 68/push 0/imm32/next +8940 68/push 0/imm32/outputs +8941 56/push-esi/inouts +8942 68/push "compare"/imm32/operation +8943 68/push 1/imm32/regular-stmt +8944 89/<- %esi 4/r32/esp +8945 # convert +8946 c7 0/subop/copy *Curr-block-depth 0/imm32 +8947 (emit-subx-statement _test-output-buffered-file %esi Primitives 0) +8948 (flush _test-output-buffered-file) +8949 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +8955 # check output +8956 (check-next-stream-line-equal _test-output-stream "81 7/subop/compare %ecx 0x34/imm32" "F - test-compare-reg-with-literal") +8957 # . epilogue +8958 89/<- %esp 5/r32/ebp +8959 5d/pop-to-ebp +8960 c3/return +8961 +8962 test-emit-subx-statement-function-call: +8963 # Call a function on a variable on the stack. +8964 # f foo +8965 # => +8966 # (f2 *(ebp-8)) +8967 # (Changing the function name supports overloading in general, but here it +8968 # just serves to help disambiguate things.) +8969 # +8970 # There's a variable on the var stack as follows: +8971 # name: 'foo' +8972 # type: int +8973 # stack-offset: -8 +8974 # +8975 # There's nothing in primitives. +8976 # +8977 # There's a function with this info: +8978 # name: 'f' +8979 # inout: int/mem +8980 # value: 'f2' +8981 # +8982 # . prologue +8983 55/push-ebp +8984 89/<- %ebp 4/r32/esp +8985 # setup +8986 (clear-stream _test-output-stream) +8987 (clear-stream $_test-output-buffered-file->buffer) +8988 # var type/ecx: (handle tree type-id) = int +8989 68/push 0/imm32/right/null +8990 68/push 1/imm32/left/int +8991 89/<- %ecx 4/r32/esp +8992 # var var-foo/ecx: var +8993 68/push 0/imm32/no-register +8994 68/push -8/imm32/stack-offset +8995 68/push 0/imm32/block-depth +8996 51/push-ecx +8997 68/push "foo"/imm32 +8998 89/<- %ecx 4/r32/esp +8999 # var inouts/esi: (handle stmt-var) +9000 68/push 0/imm32/is-deref:false +9001 68/push 0/imm32/next +9002 51/push-ecx/var-foo +9003 89/<- %esi 4/r32/esp +9004 # var stmt/esi: statement +9005 68/push 0/imm32/next +9006 68/push 0/imm32/outputs +9007 56/push-esi/inouts +9008 68/push "f"/imm32/operation +9009 68/push 1/imm32 +9010 89/<- %esi 4/r32/esp +9011 # var functions/ebx: function +9012 68/push 0/imm32/next +9013 68/push 0/imm32/body +9014 68/push 0/imm32/outputs +9015 51/push-ecx/inouts # hack; in practice we won't have the same var in function definition and call +9016 68/push "f2"/imm32/subx-name +9017 68/push "f"/imm32/name +9018 89/<- %ebx 4/r32/esp +9019 # convert +9020 c7 0/subop/copy *Curr-block-depth 0/imm32 +9021 (emit-subx-statement _test-output-buffered-file %esi 0 %ebx) +9022 (flush _test-output-buffered-file) +9023 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +9029 # check output +9030 (check-next-stream-line-equal _test-output-stream "(f2 *(ebp+0xfffffff8))" "F - test-emit-subx-statement-function-call") +9031 # . epilogue +9032 89/<- %esp 5/r32/ebp +9033 5d/pop-to-ebp +9034 c3/return +9035 +9036 test-emit-subx-statement-function-call-with-literal-arg: +9037 # Call a function on a literal. +9038 # f 34 +9039 # => +9040 # (f2 34) +9041 # +9042 # . prologue +9043 55/push-ebp +9044 89/<- %ebp 4/r32/esp +9045 # setup +9046 (clear-stream _test-output-stream) +9047 (clear-stream $_test-output-buffered-file->buffer) +9048 # var type/ecx: (handle tree type-id) = literal +9049 68/push 0/imm32/right/null +9050 68/push 0/imm32/left/literal +9051 89/<- %ecx 4/r32/esp +9052 # var var-foo/ecx: var literal +9053 68/push 0/imm32/no-register +9054 68/push 0/imm32/no-stack-offset +9055 68/push 0/imm32/block-depth +9056 51/push-ecx +9057 68/push "34"/imm32 +9058 89/<- %ecx 4/r32/esp +9059 # var inouts/esi: (handle stmt-var) +9060 68/push 0/imm32/is-deref:false +9061 68/push 0/imm32/next +9062 51/push-ecx/var-foo +9063 89/<- %esi 4/r32/esp +9064 # var stmt/esi: statement +9065 68/push 0/imm32/next +9066 68/push 0/imm32/outputs +9067 56/push-esi/inouts +9068 68/push "f"/imm32/operation +9069 68/push 1/imm32 +9070 89/<- %esi 4/r32/esp +9071 # var functions/ebx: function +9072 68/push 0/imm32/next +9073 68/push 0/imm32/body +9074 68/push 0/imm32/outputs +9075 51/push-ecx/inouts # hack; in practice we won't have the same var in function definition and call +9076 68/push "f2"/imm32/subx-name +9077 68/push "f"/imm32/name +9078 89/<- %ebx 4/r32/esp +9079 # convert +9080 c7 0/subop/copy *Curr-block-depth 0/imm32 +9081 (emit-subx-statement _test-output-buffered-file %esi 0 %ebx) +9082 (flush _test-output-buffered-file) +9083 +-- 6 lines: #? # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------------------- +9089 # check output +9090 (check-next-stream-line-equal _test-output-stream "(f2 34)" "F - test-emit-subx-statement-function-call-with-literal-arg") +9091 # . epilogue +9092 89/<- %esp 5/r32/ebp +9093 5d/pop-to-ebp +9094 c3/return +9095 +9096 emit-indent: # out: (addr buffered-file), n: int +9097 # . prologue +9098 55/push-ebp +9099 89/<- %ebp 4/r32/esp +9100 # . save registers +9101 50/push-eax +9102 # var i/eax: int = n +9103 8b/-> *(ebp+0xc) 0/r32/eax +9104 { +9105 # if (i <= 0) break +9106 3d/compare-eax-with 0/imm32 +9107 7e/jump-if-<= break/disp8 +9108 (write-buffered *(ebp+8) " ") +9109 48/decrement-eax +9110 eb/jump loop/disp8 +9111 } +9112 $emit-indent:end: +9113 # . restore registers +9114 58/pop-to-eax +9115 # . epilogue +9116 89/<- %esp 5/r32/ebp +9117 5d/pop-to-ebp +9118 c3/return +9119 +9120 emit-subx-prologue: # out: (addr buffered-file) +9121 # . prologue +9122 55/push-ebp +9123 89/<- %ebp 4/r32/esp +9124 # +9125 (write-buffered *(ebp+8) " # . prologue\n") +9126 (write-buffered *(ebp+8) " 55/push-ebp\n") +9127 (write-buffered *(ebp+8) " 89/<- %ebp 4/r32/esp\n") +9128 $emit-subx-prologue:end: +9129 # . epilogue +9130 89/<- %esp 5/r32/ebp +9131 5d/pop-to-ebp +9132 c3/return +9133 +9134 emit-subx-epilogue: # out: (addr buffered-file) +9135 # . prologue +9136 55/push-ebp +9137 89/<- %ebp 4/r32/esp +9138 # +9139 (write-buffered *(ebp+8) " # . epilogue\n") +9140 (write-buffered *(ebp+8) " 89/<- %esp 5/r32/ebp\n") +9141 (write-buffered *(ebp+8) " 5d/pop-to-ebp\n") +9142 (write-buffered *(ebp+8) " c3/return\n") +9143 $emit-subx-epilogue:end: +9144 # . epilogue +9145 89/<- %esp 5/r32/ebp +9146 5d/pop-to-ebp +9147 c3/return -- cgit 1.4.1-2-gfad0