# Mu - linux/mu.subx

https://github.com/akkartik/mu/blob/main/linux/mu.subx

        1 # The Mu computer's level-2 language, also called Mu.
        2 # http://akkartik.name/post/mu-2019-2
        3 #
        4 # To run:
        5 #   $ ./translate_subx init.linux [0-9]*.subx mu.subx
        6 #   $ ./a.elf < prog.mu > prog.elf
        7
        8 # == Goals
        9 # 1. Be memory safe. It should be impossible to corrupt the heap, or to create
       10 # a bad pointer. (Requires strong type safety.)
       11 # 2. Do as little as possible to achieve goal 1. The translator should be
       12 # implementable in machine code.
       13 #   - minimize impedance mismatch between source language and SubX target
       14 #     (e.g. programmer manages registers manually)
       15 #   - checks over syntax
       16 #     (e.g. programmer's register allocation is checked)
       17 #   - runtime checks to avoid complex static analysis
       18 #     (e.g. array indexing always checks bounds)
       19
       20 # == Language description
       21 # A program is a sequence of function and type definitions.
       22 #
       23 # Function example:
       24 #   fn foo n: int -> _/eax: int {
       25 #     ...
       26 #   }
       27 #
       28 # Functions consist of a name, optional inputs, optional outputs and a block.
       29 #
       30 # Function inputs and outputs are variables. All variables have a type and
       31 # storage specifier. They can be placed either in memory (on the stack) or in
       32 # one of 6 named registers.
       33 #   eax ecx edx ebx esi edi
       34 # Variables in registers must be primitive 32-bit types.
       35 # Variables not explicitly placed in a register are on the stack.
       36 #
       37 # Function inputs are always passed in memory (on the stack), while outputs
       38 # are always returned in registers. Outputs can't be named; they use the
       39 # dummy value '_'.
       40 #
       41 # Blocks mostly consist of statements.
       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.
       47 #
       48 # Statement outputs, like function outputs, must be variables in registers.
       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 #   union types
       83 #
       84 # Formal types:
       85 #   A program is a linked list of functions
       86 #   A function contains:
       87 #     name: (handle array byte)
       88 #     inouts: linked list of vars  <-- 'inouts' is more precise than 'inputs'
       89 #       data: (handle var)
       90 #       next: (handle list)
       91 #     outputs: linked list of vars
       92 #       data: (handle var)
       93 #       next: (handle list)
       94 #     body: (handle block)
       95 #   A var-type contains:
       96 #     name: (handle array byte)
       97 #     type: (handle type-tree)
       98 #
       99 #   A statement can be:
      100 #     tag 0: a block
      101 #     tag 1: a simple statement (stmt1)
      102 #     tag 2: a variable defined on the stack
      103 #     tag 3: a variable defined in a register
      104 #
      105 #   A block contains:
      106 #     tag: 0
      107 #     statements: (handle list stmt)
      108 #     name: (handle array byte) -- starting with '$'
      109 #
      110 #   A regular statement contains:
      111 #     tag: 1
      112 #     operation: (handle array byte)
      113 #     inouts: (handle list operand)
      114 #     outputs: (handle list var)
      115 #
      116 #   A variable defined on the stack contains:
      117 #     tag: 2
      118 #     name: (handle array byte)
      119 #     type: (handle type-tree)
      120 #
      121 #   A variable defined in a register contains:
      122 #     tag: 3
      123 #     name: (handle array byte)
      124 #     type: (handle type-tree)
      125 #     reg: (handle array byte)
      126
      127 # == Translation: managing the stack
      128 # Now that we know what the language looks like in the large, let's think
      129 # about how translation happens from the bottom up. One crucial piece of the
      130 # puzzle is how Mu will clean up variables defined on the stack for you.
      131 #
      132 # Assume that we maintain a 'functions' list while parsing source code. And a
      133 # 'primitives' list is a global constant. Both these contain enough information
      134 # to perform type-checking on function calls or primitive statements, respectively.
      135 #
      136 # Defining variables pushes them on a stack with the current block depth and
      137 # enough information about their location (stack offset or register).
      138 # Starting a block increments the current block id.
      139 # Each statement now has enough information to emit code for it.
      140 # Ending a block is where the magic happens:
      141 #   pop all variables at the current block depth
      142 #   emit code to restore all register variables introduced at the current depth
      143 #   emit code to clean up all stack variables at the current depth (just increment esp)
      144 #   decrement the current block depth
      145 #
      146 # Formal types:
      147 #   live-vars: stack of vars
      148 #   var:
      149 #     name: (handle array byte)
      150 #     type: (handle type-tree)
      151 #     block: int
      152 #     stack-offset: int  (added to ebp)
      153 #     register: (handle array byte)
      154 #       either usual register names
      155 #       or '*' to indicate any register
      156 #   At most one of stack-offset or register-index must be non-zero.
      157 #   A register of '*' designates a variable _template_. Only legal in formal
      158 #   parameters for primitives.
      159
      160 # == Translating a single function call
      161 # This one's easy. Assuming we've already checked things, we just drop the
      162 # outputs (which use hard-coded registers) and emit inputs in a standard format.
      163 #
      164 # out1, out2, out3, ... <- name inout1, inout2, inout3, ...
      165 # =>
      166 # (name inout1 inout2 inout3)
      167 #
      168 # Formal types:
      169 #   functions: linked list of info
      170 #     name: (handle array byte)
      171 #     inouts: linked list of vars
      172 #     outputs: linked list of vars
      173 #     body: block (linked list of statements)
      174
      175 # == Translating a single primitive instruction
      176 # A second crucial piece of the puzzle is how Mu converts fairly regular
      177 # primitives with their uniform syntax to SubX instructions with their gnarly
      178 # x86 details.
      179 #
      180 # Mu instructions have inputs and outputs. Primitives can have up to 2 of
      181 # them.
      182 # SubX instructions have rm32 and r32 operands.
      183 # The translation between them covers almost all the possibilities.
      184 #   Instructions with 1 inout may turn into ones with 1 rm32
      185 #     (e.g. incrementing a var on the stack)
      186 #   Instructions with 1 output may turn into ones with 1 rm32
      187 #     (e.g. incrementing a var in a register)
      188 #   1 inout and 1 output may turn into 1 rm32 and 1 r32
      189 #     (e.g. adding a var to a reg)
      190 #   2 inouts may turn into 1 rm32 and 1 r32
      191 #     (e.g. adding a reg to a var)
      192 #   1 inout and 1 literal may turn into 1 rm32 and 1 imm32
      193 #     (e.g. adding a constant to a var)
      194 #   1 output and 1 literal may turn into 1 rm32 and 1 imm32
      195 #     (e.g. adding a constant to a reg)
      196 #   2 outputs to hardcoded registers and 1 inout may turn into 1 rm32
      197 #     (special-case: divide edx:eax by a var or reg)
      198 # Observations:
      199 #   We always emit rm32. It may be the first inout or the first output.
      200 #   We may emit r32 or imm32 or neither.
      201 #   When we emit r32 it may come from first inout or second inout or first output.
      202 #
      203 # Accordingly, the formal data structure for a primitive looks like this:
      204 #   primitives: linked list of info
      205 #     name: (handle array byte)
      206 #     mu-inouts: linked list of vars to check
      207 #     mu-outputs: linked list of vars to check; at most a singleton
      208 #     subx-name: (handle array byte)
      209 #     subx-rm32: enum arg-location
      210 #     subx-r32: enum arg-location
      211 #     subx-imm32: enum arg-location
      212 #     subx-imm8: enum arg-location
      213 #     subx-disp32: enum arg-location
      214 #     subx-xm32: enum arg-location
      215 #     subx-x32: enum arg-location
      216 #   arg-location: enum
      217 #     0 means none
      218 #     1 means first inout
      219 #     2 means second inout
      220 #     3 means first output
      221
      222 # == Translating a block
      223 # Emit block name if necessary
      224 # Emit '{'
      225 # When you encounter a statement, emit it as above
      226 # When you encounter a variable declaration
      227 #   emit any code needed for it (bzeros)
      228 #   push it on the var stack
      229 #   update register dict if necessary
      230 # When you encounter '}'
      231 #   While popping variables off the var stack until block id changes
      232 #     Emit code needed to clean up the stack
      233 #       either increment esp
      234 #       or pop into appropriate register
      235
      236 # The rest is straightforward.
      237
      238 == data
      239
      240 Program:
      241 _Program-functions:  # (handle function)
      242   0/imm32
      243 _Program-functions->payload:
      244   0/imm32
      245 _Program-types:  # (handle typeinfo)
      246   0/imm32
      247 _Program-types->payload:
      248   0/imm32
      249 _Program-signatures:  # (handle function)
      250   0/imm32
      251 _Program-signatures->payload:
      252   0/imm32
      253
      254 # Some constants for simulating the data structures described above.
      255 # Many constants here come with a type in a comment.
      256 #
      257 # Sometimes the type is of the value at that offset for the given type. For
      258 # example, if you start at a function record and move forward Function-inouts
      259 # bytes, you'll find a (handle list var).
      260 #
      261 # At other times, the type is of the constant itself. For example, the type of
      262 # the constant Function-size is (addr int). To get the size of a function,
      263 # look in *Function-size.
      264
      265 Function-name:  # (handle array byte)
      266   0/imm32
      267 Function-inouts:  # (handle list var)
      268   8/imm32
      269 Function-outputs:  # (handle list var)
      270   0x10/imm32
      271 Function-body:  # (handle block)
      272   0x18/imm32
      273 Function-next:  # (handle function)
      274   0x20/imm32
      275 Function-size:  # (addr int)
      276   0x28/imm32/40
      277
      278 Primitive-name:  # (handle array byte)
      279   0/imm32
      280 Primitive-inouts:  # (handle list var)
      281   8/imm32
      282 Primitive-outputs:  # (handle list var)
      283   0x10/imm32
      284 Primitive-subx-name:  # (handle array byte)
      285   0x18/imm32
      286 Primitive-subx-rm32:  # enum arg-location
      287   0x20/imm32
      288 Primitive-subx-r32:  # enum arg-location
      289   0x24/imm32
      290 Primitive-subx-imm32:  # enum arg-location
      291   0x28/imm32
      292 Primitive-subx-imm8:  # enum arg-location  -- only for bit shifts
      293   0x2c/imm32
      294 Primitive-subx-disp32:  # enum arg-location  -- only for branches
      295   0x30/imm32
      296 Primitive-subx-xm32:  # enum arg-location
      297   0x34/imm32
      298 Primitive-subx-x32:  # enum arg-location
      299   0x38/imm32
      300 Primitive-next:  # (handle function)
      301   0x3c/imm32
      302 Primitive-size:  # (addr int)
      303   0x44/imm32/68
      304
      305 Stmt-tag:  # int
      306   0/imm32
      307
      308 Block-stmts:  # (handle list stmt)
      309   4/imm32
      310 Block-var:  # (handle var)
      311   0xc/imm32
      312
      313 Stmt1-operation:  # (handle array byte)
      314   4/imm32
      315 Stmt1-inouts:  # (handle stmt-var)
      316   0xc/imm32
      317 Stmt1-outputs:  # (handle stmt-var)
      318   0x14/imm32
      319
      320 Vardef-var:  # (handle var)
      321   4/imm32
      322
      323 Regvardef-operation:  # (handle array byte)
      324   4/imm32
      325 Regvardef-inouts:  # (handle stmt-var)
      326   0xc/imm32
      327 Regvardef-outputs:  # (handle stmt-var)  # will have exactly one element
      328   0x14/imm32
      329
      330 Stmt-size:  # (addr int)
      331   0x1c/imm32
      332
      333 Var-name:  # (handle array byte)
      334   0/imm32
      335 Var-type:  # (handle type-tree)
      336   8/imm32
      337 Var-block-depth:  # int -- not available until code-generation time
      338   0x10/imm32
      339 Var-offset:  # int -- not available until code-generation time
      340   0x14/imm32
      341 Var-register:  # (handle array byte) -- name of a register
      342   0x18/imm32
      343 Var-size:  # (addr int)
      344   0x20/imm32
      345
      346 List-value:  # (handle _)
      347   0/imm32
      348 List-next:  # (handle list _)
      349   8/imm32
      350 List-size:  # (addr int)
      351   0x10/imm32
      352
      353 # A stmt-var is like a list of vars with call-site specific metadata
      354 Stmt-var-value:  # (handle var)
      355   0/imm32
      356 Stmt-var-next:  # (handle stmt-var)
      357   8/imm32
      358 Stmt-var-is-deref:  # boolean
      359   0x10/imm32
      360 Stmt-var-size:  # (addr int)
      361   0x14/imm32
      362
      363 # A live-var is a var augmented with information needed for tracking live
      364 # variables.
      365 Live-var-value:  # (handle var)
      366   0/imm32
      367 Live-var-register-spilled:  # boolean; only used if value is in a register, and only during code-gen
      368   8/imm32
      369 Live-var-size:  # (addr int)
      370   0xc/imm32
      371
      372 # Types are expressed as trees (s-expressions) of type-ids (ints).
      373
      374 Type-tree-is-atom:  # boolean
      375   0/imm32
      376 # if is-atom?
      377 Type-tree-value:  # type-id
      378   4/imm32
      379 Type-tree-value-size:  # int (for static data structure sizes)
      380   8/imm32
      381 Type-tree-parameter-name:  # (handle array byte) for type parameters
      382   8/imm32
      383 # unless is-atom?
      384 Type-tree-left:  # (addr type-tree)
      385   4/imm32
      386 Type-tree-right:  # (addr type-tree)
      387   0xc/imm32
      388 #
      389 Type-tree-size:  # (addr int)
      390   0x14/imm32
      391
      392 # Types
      393
      394 # TODO: Turn this data structure into valid Mu, with (fake) handles rather than addrs.
      395 Type-id:  # (stream (addr array byte))
      396   0/imm32/write  # initialized later from Primitive-type-ids
      397   0/imm32/read
      398   0x100/imm32/size
      399   # data
      400   0/imm32  # 0 reserved for literals; value is just the name
      401            # Not to be used directly, so we don't include a name here.
      402   "int"/imm32  # 1
      403   "addr"/imm32  # 2
      404   "array"/imm32  # 3
      405   "handle"/imm32  # 4
      406   "boolean"/imm32  # 5
      407   0/imm32  # 6 reserved for constants; they're like literals, but value is an int in Var-offset
      408            # Not to be used directly, so we don't include a name here.
      409   "offset"/imm32  # 7: (offset T) is guaranteed to be a 32-bit multiple of size-of(T)
      410   # 0x20
      411   "byte"/imm32  # 8
      412   0/imm32  # 9 reserved for array-capacity; value is in Type-tree-size.
      413            # Not to be used directly, so we don't include a name here.
      414   0/imm32  # 10 reserved for type parameters; value is (address array byte) in Type-tree-value2.
      415            # Not to be used directly, so we don't include a name here.
      416   "stream"/imm32  # 11
      417   "slice"/imm32  # 12
      418   "code-point"/imm32  # 13; smallest scannable unit from a text stream
      419   "grapheme"/imm32  # 14; smallest printable unit; will eventually be composed of multiple code-points, but currently corresponds 1:1
      420                     # only 4-byte graphemes in utf-8 are currently supported;
      421                     # unclear how we should deal with larger clusters.
      422   "float"/imm32     # 15
      423   # 0x40
      424   0/imm32  # 16 reserved for literal strings; value is just the name
      425            # Not to be used directly, so we don't include a name here.
      426            # TODO: move this up next to literal ints
      427   # Keep Primitive-type-ids in sync if you add types here.
      428           0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32
      429   0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32
      430   0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32
      431   0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32
      432   0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32
      433   0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32 0/imm32
      434
      435 Primitive-type-ids:  # (addr int)
      436   0x44
      437
      438 # == Type definitions
      439 # Program->types contains some typeinfo for each type definition.
      440 # Types contain vars with types, but can't specify registers.
      441 Typeinfo-id:  # type-id
      442   0/imm32
      443 Typeinfo-fields:  # (handle table (handle array byte) (handle typeinfo-entry))
      444   4/imm32
      445 # Total size must be >= 0
      446 # During parsing it may take on two additional values:
      447 #   -2: not yet initialized
      448 #   -1: in process of being computed
      449 # See populate-mu-type-sizes for details.
      450 Typeinfo-total-size-in-bytes:  # int
      451   0xc/imm32
      452 Typeinfo-next:  # (handle typeinfo)
      453   0x10/imm32
      454 Typeinfo-size:  # (addr int)
      455   0x18/imm32
      456
      457 # Each entry in the typeinfo->fields table has a pointer to a string and a
      458 # pointer to a typeinfo-entry.
      459 Typeinfo-fields-row-size:  # (addr int)
      460   0x10/imm32
      461
      462 # typeinfo-entry objects have information about a field in a single record type
      463 #
      464 # each field of a type is represented using two var's:
      465 #   1. the input var: expected type of the field; convenient for creating using parse-var-with-type
      466 #   2. the output var: a constant containing the byte offset; convenient for code-generation
      467 # computing the output happens after parsing; in the meantime we preserve the
      468 # order of fields in the 'index' field.
      469 Typeinfo-entry-input-var:  # (handle var)
      470   0/imm32
      471 Typeinfo-entry-index:  # int
      472   8/imm32
      473 Typeinfo-entry-output-var:  # (handle var)
      474   0xc/imm32
      475 Typeinfo-entry-size:  # (addr int)
      476   0x14/imm32
      477
      478 == code
      479
      480 Entry:
      481     # . prologue
      482     89/<- %ebp 4/r32/esp
      483     (new-segment *Heap-size Heap)
      484 #?     (test-address-with-right-type-for-stream)
      485     # if (argv[1] == "test') run-tests()
      486     {
      487       # if (argc <= 1) break
      488       81 7/subop/compare *ebp 1/imm32
      489       7e/jump-if-<= break/disp8
      490       # if (argv[1] != "test") break
      491       (kernel-string-equal? *(ebp+8) "test")  # => eax
      492       3d/compare-eax-and 0/imm32/false
      493       74/jump-if-= break/disp8
      494       #
      495       (run-tests)
      496       # syscall(exit, *Num-test-failures)
      497       8b/-> *Num-test-failures 3/r32/ebx
      498       eb/jump $mu-main:end/disp8
      499     }
      500     # otherwise convert Stdin
      501     (write-buffered Stdout "== code\n")
      502     (convert-mu Stdin Stdout Stderr 0)
      503     (flush Stdout)
      504     # syscall(exit, 0)
      505     bb/copy-to-ebx 0/imm32
      506 $mu-main:end:
      507     e8/call syscall_exit/disp32
      508
      509 convert-mu:  # in: (addr buffered-file), out: (addr buffered-file), err: (addr buffered-file), ed: (addr exit-descriptor)
      510     # . prologue
      511     55/push-ebp
      512     89/<- %ebp 4/r32/esp
      513     # . save registers
      514     50/push-eax
      515     # initialize global data structures
      516     c7 0/subop/copy *Next-block-index 1/imm32
      517     8b/-> *Primitive-type-ids 0/r32/eax
      518     89/<- *Type-id 0/r32/eax  # stream-write
      519     c7 0/subop/copy *_Program-functions 0/imm32
      520     c7 0/subop/copy *_Program-functions->payload 0/imm32
      521     c7 0/subop/copy *_Program-types 0/imm32
      522     c7 0/subop/copy *_Program-types->payload 0/imm32
      523     c7 0/subop/copy *_Program-signatures 0/imm32
      524     c7 0/subop/copy *_Program-signatures->payload 0/imm32
      525     #
      526     (parse-mu *(ebp+8) *(ebp+0x10) *(ebp+0x14))
      527     (populate-mu-type-sizes *(ebp+0x10) *(ebp+0x14))
      528 #?     (dump-typeinfos "=== typeinfos\n")
      529     (check-mu-types *(ebp+0x10) *(ebp+0x14))
      530     (emit-subx *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
      531 $convert-mu:end:
      532     # . restore registers
      533     58/pop-to-eax
      534     # . epilogue
      535     89/<- %esp 5/r32/ebp
      536     5d/pop-to-ebp
      537     c3/return
      538
      539 test-convert-empty-input:
      540     # empty input => empty output
      541     # . prologue
      542     55/push-ebp
      543     89/<- %ebp 4/r32/esp
      544     # setup
      545     (clear-stream _test-input-stream)
      546     (clear-stream $_test-input-buffered-file->buffer)
      547     (clear-stream _test-output-stream)
      548     (clear-stream $_test-output-buffered-file->buffer)
      549     #
      550     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
      551     (flush _test-output-buffered-file)
      552     (check-stream-equal _test-output-stream "" "F - test-convert-empty-input")
      553     # . epilogue
      554     89/<- %esp 5/r32/ebp
      555     5d/pop-to-ebp
      556     c3/return
      557
      558 test-convert-function-skeleton:
      559     # . prologue
      560     55/push-ebp
      561     89/<- %ebp 4/r32/esp
      562     # setup
      563     (clear-stream _test-input-stream)
      564     (clear-stream $_test-input-buffered-file->buffer)
      565     (clear-stream _test-output-stream)
      566     (clear-stream $_test-output-buffered-file->buffer)
      567     #
      568     (write _test-input-stream "fn foo {\n")
      569     (write _test-input-stream "}\n")
      570     # convert
      571     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
      572     (flush _test-output-buffered-file)
      573 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
      579     # check output
      580     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-skeleton/0")
      581     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-skeleton/1")
      582     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-skeleton/2")
      583     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-skeleton/3")
      584     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-skeleton/4")
      585     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-skeleton/5")
      586     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-skeleton/6")
      587     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-skeleton/7")
      588     # . epilogue
      589     89/<- %esp 5/r32/ebp
      590     5d/pop-to-ebp
      591     c3/return
      592
      593 test-convert-multiple-function-skeletons:
      594     # . prologue
      595     55/push-ebp
      596     89/<- %ebp 4/r32/esp
      597     # setup
      598     (clear-stream _test-input-stream)
      599     (clear-stream $_test-input-buffered-file->buffer)
      600     (clear-stream _test-output-stream)
      601     (clear-stream $_test-output-buffered-file->buffer)
      602     #
      603     (write _test-input-stream "fn foo {\n")
      604     (write _test-input-stream "}\n")
      605     (write _test-input-stream "fn bar {\n")
      606     (write _test-input-stream "}\n")
      607     # convert
      608     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
      609     (flush _test-output-buffered-file)
      610 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
      616     # check first function
      617     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-multiple-function-skeletons/0")
      618     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-multiple-function-skeletons/1")
      619     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-multiple-function-skeletons/2")
      620     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-multiple-function-skeletons/3")
      621     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-multiple-function-skeletons/4")
      622     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-multiple-function-skeletons/5")
      623     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-multiple-function-skeletons/6")
      624     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-multiple-function-skeletons/7")
      625     # check second function
      626     (check-next-stream-line-equal _test-output-stream "bar:"                    "F - test-convert-multiple-function-skeletons/10")
      627     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-multiple-function-skeletons/11")
      628     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-multiple-function-skeletons/12")
      629     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-multiple-function-skeletons/13")
      630     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-multiple-function-skeletons/14")
      631     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-multiple-function-skeletons/15")
      632     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-multiple-function-skeletons/16")
      633     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-multiple-function-skeletons/17")
      634     # . epilogue
      635     89/<- %esp 5/r32/ebp
      636     5d/pop-to-ebp
      637     c3/return
      638
      639 test-convert-function-with-arg:
      640     # . prologue
      641     55/push-ebp
      642     89/<- %ebp 4/r32/esp
      643     # setup
      644     (clear-stream _test-input-stream)
      645     (clear-stream $_test-input-buffered-file->buffer)
      646     (clear-stream _test-output-stream)
      647     (clear-stream $_test-output-buffered-file->buffer)
      648     #
      649     (write _test-input-stream "fn foo n: int {\n")
      650     (write _test-input-stream "}\n")
      651     # convert
      652     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
      653     (flush _test-output-buffered-file)
      654 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
      660     # check output
      661     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-arg/0")
      662     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-arg/1")
      663     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-arg/2")
      664     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-arg/3")
      665     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-arg/4")
      666     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-arg/5")
      667     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-arg/6")
      668     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-arg/7")
      669     # . epilogue
      670     89/<- %esp 5/r32/ebp
      671     5d/pop-to-ebp
      672     c3/return
      673
      674 test-function-with-redefined-name:
      675     # . prologue
      676     55/push-ebp
      677     89/<- %ebp 4/r32/esp
      678     # setup
      679     (clear-stream _test-input-stream)
      680     (clear-stream $_test-input-buffered-file->buffer)
      681     (clear-stream _test-output-stream)
      682     (clear-stream $_test-output-buffered-file->buffer)
      683     (clear-stream _test-error-stream)
      684     (clear-stream $_test-error-buffered-file->buffer)
      685     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
      686     68/push 0/imm32
      687     68/push 0/imm32
      688     89/<- %edx 4/r32/esp
      689     (tailor-exit-descriptor %edx 0x10)
      690     #
      691     (write _test-input-stream "fn foo {\n")
      692     (write _test-input-stream "}\n")
      693     (write _test-input-stream "fn foo {\n")
      694     (write _test-input-stream "}\n")
      695     # convert
      696     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
      697     # registers except esp clobbered at this point
      698     # restore ed
      699     89/<- %edx 4/r32/esp
      700     (flush _test-output-buffered-file)
      701     (flush _test-error-buffered-file)
      702 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
      708     # check output
      709     (check-stream-equal _test-output-stream  ""  "F - test-function-with-redefined-name: output should be empty")
      710     (check-next-stream-line-equal _test-error-stream  "fn foo defined more than once"  "F - test-function-with-redefined-name: error message")
      711     # check that stop(1) was called
      712     (check-ints-equal *(edx+4) 2 "F - test-function-with-redefined-name: exit status")
      713     # don't restore from ebp
      714     81 0/subop/add %esp 8/imm32
      715     # . epilogue
      716     5d/pop-to-ebp
      717     c3/return
      718
      719 test-function-with-redefined-name-2:
      720     # . prologue
      721     55/push-ebp
      722     89/<- %ebp 4/r32/esp
      723     # setup
      724     (clear-stream _test-input-stream)
      725     (clear-stream $_test-input-buffered-file->buffer)
      726     (clear-stream _test-output-stream)
      727     (clear-stream $_test-output-buffered-file->buffer)
      728     (clear-stream _test-error-stream)
      729     (clear-stream $_test-error-buffered-file->buffer)
      730     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
      731     68/push 0/imm32
      732     68/push 0/imm32
      733     89/<- %edx 4/r32/esp
      734     (tailor-exit-descriptor %edx 0x10)
      735     #
      736     (write _test-input-stream "fn foo {\n")
      737     (write _test-input-stream "}\n")
      738     (write _test-input-stream "sig foo\n")
      739     # convert
      740     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
      741     # registers except esp clobbered at this point
      742     # restore ed
      743     89/<- %edx 4/r32/esp
      744     (flush _test-output-buffered-file)
      745     (flush _test-error-buffered-file)
      746 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
      752     # check output
      753     (check-stream-equal _test-output-stream  ""  "F - test-function-with-redefined-name-2: output should be empty")
      754     (check-next-stream-line-equal _test-error-stream  "fn foo defined more than once"  "F - test-function-with-redefined-name-2: error message")
      755     # check that stop(1) was called
      756     (check-ints-equal *(edx+4) 2 "F - test-function-with-redefined-name-2: exit status")
      757     # don't restore from ebp
      758     81 0/subop/add %esp 8/imm32
      759     # . epilogue
      760     5d/pop-to-ebp
      761     c3/return
      762
      763 test-function-with-redefined-name-3:
      764     # . prologue
      765     55/push-ebp
      766     89/<- %ebp 4/r32/esp
      767     # setup
      768     (clear-stream _test-input-stream)
      769     (clear-stream $_test-input-buffered-file->buffer)
      770     (clear-stream _test-output-stream)
      771     (clear-stream $_test-output-buffered-file->buffer)
      772     (clear-stream _test-error-stream)
      773     (clear-stream $_test-error-buffered-file->buffer)
      774     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
      775     68/push 0/imm32
      776     68/push 0/imm32
      777     89/<- %edx 4/r32/esp
      778     (tailor-exit-descriptor %edx 0x10)
      779     #
      780     (write _test-input-stream "sig foo\n")
      781     (write _test-input-stream "fn foo {\n")
      782     (write _test-input-stream "}\n")
      783     # convert
      784     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
      785     # registers except esp clobbered at this point
      786     # restore ed
      787     89/<- %edx 4/r32/esp
      788     (flush _test-output-buffered-file)
      789     (flush _test-error-buffered-file)
      790 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
      796     # check output
      797     (check-stream-equal _test-output-stream  ""  "F - test-function-with-redefined-name-3: output should be empty")
      798     (check-next-stream-line-equal _test-error-stream  "fn foo defined more than once"  "F - test-function-with-redefined-name-3: error message")
      799     # check that stop(1) was called
      800     (check-ints-equal *(edx+4) 2 "F - test-function-with-redefined-name-3: exit status")
      801     # don't restore from ebp
      802     81 0/subop/add %esp 8/imm32
      803     # . epilogue
      804     5d/pop-to-ebp
      805     c3/return
      806
      807 test-function-with-inout-in-register:
      808     # . prologue
      809     55/push-ebp
      810     89/<- %ebp 4/r32/esp
      811     # setup
      812     (clear-stream _test-input-stream)
      813     (clear-stream $_test-input-buffered-file->buffer)
      814     (clear-stream _test-output-stream)
      815     (clear-stream $_test-output-buffered-file->buffer)
      816     (clear-stream _test-error-stream)
      817     (clear-stream $_test-error-buffered-file->buffer)
      818     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
      819     68/push 0/imm32
      820     68/push 0/imm32
      821     89/<- %edx 4/r32/esp
      822     (tailor-exit-descriptor %edx 0x10)
      823     #
      824     (write _test-input-stream "fn foo x/eax: int {\n")
      825     (write _test-input-stream "}\n")
      826     # convert
      827     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
      828     # registers except esp clobbered at this point
      829     # restore ed
      830     89/<- %edx 4/r32/esp
      831     (flush _test-output-buffered-file)
      832     (flush _test-error-buffered-file)
      833 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
      839     # check output
      840     (check-stream-equal _test-output-stream  ""  "F - test-function-with-inout-in-register: output should be empty")
      841     (check-next-stream-line-equal _test-error-stream  "fn foo: function inout 'x' cannot be in a register"  "F - test-function-with-inout-in-register: error message")
      842     # check that stop(1) was called
      843     (check-ints-equal *(edx+4) 2 "F - test-function-with-inout-in-register: exit status")
      844     # don't restore from ebp
      845     81 0/subop/add %esp 8/imm32
      846     # . epilogue
      847     5d/pop-to-ebp
      848     c3/return
      849
      850 test-function-with-addr-output:
      851     # . prologue
      852     55/push-ebp
      853     89/<- %ebp 4/r32/esp
      854     # setup
      855     (clear-stream _test-input-stream)
      856     (clear-stream $_test-input-buffered-file->buffer)
      857     (clear-stream _test-output-stream)
      858     (clear-stream $_test-output-buffered-file->buffer)
      859     (clear-stream _test-error-stream)
      860     (clear-stream $_test-error-buffered-file->buffer)
      861     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
      862     68/push 0/imm32
      863     68/push 0/imm32
      864     89/<- %edx 4/r32/esp
      865     (tailor-exit-descriptor %edx 0x10)
      866     #
      867     (write _test-input-stream "fn foo -> _/eax: (addr int) {\n")
      868     (write _test-input-stream "}\n")
      869     # convert
      870     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
      871     # registers except esp clobbered at this point
      872     # restore ed
      873     89/<- %edx 4/r32/esp
      874     (flush _test-output-buffered-file)
      875     (flush _test-error-buffered-file)
      876 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
      882     # check output
      883     (check-stream-equal _test-output-stream  ""  "F - test-function-with-addr-output: output should be empty")
      884     (check-next-stream-line-equal _test-error-stream  "fn foo: output cannot have an addr type; that could allow unsafe addresses to escape the function"  "F - test-function-with-addr-output: error message")
      885     # check that stop(1) was called
      886     (check-ints-equal *(edx+4) 2 "F - test-function-with-addr-output: exit status")
      887     # don't restore from ebp
      888     81 0/subop/add %esp 8/imm32
      889     # . epilogue
      890     5d/pop-to-ebp
      891     c3/return
      892
      893 test-function-with-addr-inout:
      894     # . prologue
      895     55/push-ebp
      896     89/<- %ebp 4/r32/esp
      897     # setup
      898     (clear-stream _test-input-stream)
      899     (clear-stream $_test-input-buffered-file->buffer)
      900     (clear-stream _test-output-stream)
      901     (clear-stream $_test-output-buffered-file->buffer)
      902     (clear-stream _test-error-stream)
      903     (clear-stream $_test-error-buffered-file->buffer)
      904     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
      905     68/push 0/imm32
      906     68/push 0/imm32
      907     89/<- %edx 4/r32/esp
      908     (tailor-exit-descriptor %edx 0x10)
      909     #
      910     (write _test-input-stream "fn foo a: (addr addr int) {\n")
      911     (write _test-input-stream "}\n")
      912     # convert
      913     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
      914     # registers except esp clobbered at this point
      915     # restore ed
      916     89/<- %edx 4/r32/esp
      917     (flush _test-output-buffered-file)
      918     (flush _test-error-buffered-file)
      919 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
      925     # check output
      926     (check-stream-equal _test-output-stream  ""  "F - test-function-with-addr-inout: output should be empty")
      927     (check-next-stream-line-equal _test-error-stream  "fn foo: inout 'a' cannot contain 'addr' anywhere in the type except the first word; that could allow unsafe addresses to escape the function"  "F - test-function-with-addr-inout: error message")
      928     # check that stop(1) was called
      929     (check-ints-equal *(edx+4) 2 "F - test-function-with-addr-inout: exit status")
      930     # don't restore from ebp
      931     81 0/subop/add %esp 8/imm32
      932     # . epilogue
      933     5d/pop-to-ebp
      934     c3/return
      935
      936 test-function-with-addr-inout-2:
      937     # . prologue
      938     55/push-ebp
      939     89/<- %ebp 4/r32/esp
      940     # setup
      941     (clear-stream _test-input-stream)
      942     (clear-stream $_test-input-buffered-file->buffer)
      943     (clear-stream _test-output-stream)
      944     (clear-stream $_test-output-buffered-file->buffer)
      945     (clear-stream _test-error-stream)
      946     (clear-stream $_test-error-buffered-file->buffer)
      947     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
      948     68/push 0/imm32
      949     68/push 0/imm32
      950     89/<- %edx 4/r32/esp
      951     (tailor-exit-descriptor %edx 0x10)
      952     #
      953     (write _test-input-stream "fn foo a: (addr array addr int) {\n")
      954     (write _test-input-stream "}\n")
      955     # convert
      956     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
      957     # registers except esp clobbered at this point
      958     # restore ed
      959     89/<- %edx 4/r32/esp
      960     (flush _test-output-buffered-file)
      961     (flush _test-error-buffered-file)
      962 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
      968     # check output
      969     (check-stream-equal _test-output-stream  ""  "F - test-function-with-addr-inout-2: output should be empty")
      970     (check-next-stream-line-equal _test-error-stream  "fn foo: inout 'a' cannot contain 'addr' anywhere in the type except the first word; that could allow unsafe addresses to escape the function"  "F - test-function-with-addr-inout-2: error message")
      971     # check that stop(1) was called
      972     (check-ints-equal *(edx+4) 2 "F - test-function-with-addr-inout-2: exit status")
      973     # don't restore from ebp
      974     81 0/subop/add %esp 8/imm32
      975     # . epilogue
      976     5d/pop-to-ebp
      977     c3/return
      978
      979 test-function-with-addr-inout-3:
      980     # . prologue
      981     55/push-ebp
      982     89/<- %ebp 4/r32/esp
      983     # setup
      984     (clear-stream _test-input-stream)
      985     (clear-stream $_test-input-buffered-file->buffer)
      986     (clear-stream _test-output-stream)
      987     (clear-stream $_test-output-buffered-file->buffer)
      988     (clear-stream _test-error-stream)
      989     (clear-stream $_test-error-buffered-file->buffer)
      990     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
      991     68/push 0/imm32
      992     68/push 0/imm32
      993     89/<- %edx 4/r32/esp
      994     (tailor-exit-descriptor %edx 0x10)
      995     #
      996     (write _test-input-stream "fn foo a: (addr array (addr int) 3) {\n")
      997     (write _test-input-stream "}\n")
      998     # convert
      999     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     1000     # registers except esp clobbered at this point
     1001     # restore ed
     1002     89/<- %edx 4/r32/esp
     1003     (flush _test-output-buffered-file)
     1004     (flush _test-error-buffered-file)
     1005 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     1011     # check output
     1012     (check-stream-equal _test-output-stream  ""  "F - test-function-with-addr-inout-3: output should be empty")
     1013     (check-next-stream-line-equal _test-error-stream  "fn foo: inout 'a' cannot contain 'addr' anywhere in the type except the first word; that could allow unsafe addresses to escape the function"  "F - test-function-with-addr-inout-3: error message")
     1014     # check that stop(1) was called
     1015     (check-ints-equal *(edx+4) 2 "F - test-function-with-addr-inout-3: exit status")
     1016     # don't restore from ebp
     1017     81 0/subop/add %esp 8/imm32
     1018     # . epilogue
     1019     5d/pop-to-ebp
     1020     c3/return
     1021
     1022 test-function-with-addr-inout-4:
     1023     # . prologue
     1024     55/push-ebp
     1025     89/<- %ebp 4/r32/esp
     1026     # setup
     1027     (clear-stream _test-input-stream)
     1028     (clear-stream $_test-input-buffered-file->buffer)
     1029     (clear-stream _test-output-stream)
     1030     (clear-stream $_test-output-buffered-file->buffer)
     1031     (clear-stream _test-error-stream)
     1032     (clear-stream $_test-error-buffered-file->buffer)
     1033     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     1034     68/push 0/imm32
     1035     68/push 0/imm32
     1036     89/<- %edx 4/r32/esp
     1037     (tailor-exit-descriptor %edx 0x10)
     1038     #
     1039     (write _test-input-stream "fn foo a: (array (addr int) 3) {\n")
     1040     (write _test-input-stream "}\n")
     1041     # convert
     1042     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     1043     # registers except esp clobbered at this point
     1044     # restore ed
     1045     89/<- %edx 4/r32/esp
     1046     (flush _test-output-buffered-file)
     1047     (flush _test-error-buffered-file)
     1048 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     1054     # check output
     1055     (check-stream-equal _test-output-stream  ""  "F - test-function-with-addr-inout-4: output should be empty")
     1056     (check-next-stream-line-equal _test-error-stream  "fn foo: inout 'a' cannot contain 'addr' anywhere in the type except the first word; that could allow unsafe addresses to escape the function"  "F - test-function-with-addr-inout-4: error message")
     1057     # check that stop(1) was called
     1058     (check-ints-equal *(edx+4) 2 "F - test-function-with-addr-inout-4: exit status")
     1059     # don't restore from ebp
     1060     81 0/subop/add %esp 8/imm32
     1061     # . epilogue
     1062     5d/pop-to-ebp
     1063     c3/return
     1064
     1065 # 'main' is an exception
     1066 test-function-main-with-addr-inout:
     1067     # . prologue
     1068     55/push-ebp
     1069     89/<- %ebp 4/r32/esp
     1070     # setup
     1071     (clear-stream _test-input-stream)
     1072     (clear-stream $_test-input-buffered-file->buffer)
     1073     (clear-stream _test-output-stream)
     1074     (clear-stream $_test-output-buffered-file->buffer)
     1075     #
     1076     (write _test-input-stream "fn main a: (addr addr int) {\n")
     1077     (write _test-input-stream "}\n")
     1078     # convert
     1079     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     1080     (flush _test-output-buffered-file)
     1081     # no errors
     1082     # . epilogue
     1083     89/<- %esp 5/r32/ebp
     1084     5d/pop-to-ebp
     1085     c3/return
     1086
     1087 # 'lookup' is an exception, but only in signatures
     1088 test-signature-lookup-with-addr-inout:
     1089     # . prologue
     1090     55/push-ebp
     1091     89/<- %ebp 4/r32/esp
     1092     # setup
     1093     (clear-stream _test-input-stream)
     1094     (clear-stream $_test-input-buffered-file->buffer)
     1095     (clear-stream _test-output-stream)
     1096     (clear-stream $_test-output-buffered-file->buffer)
     1097     #
     1098     (write _test-input-stream "sig lookup h: (handle _T) -> _/eax: (addr _T)\n")
     1099     # convert
     1100     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     1101     (flush _test-output-buffered-file)
     1102     # no errors
     1103     # . epilogue
     1104     89/<- %esp 5/r32/ebp
     1105     5d/pop-to-ebp
     1106     c3/return
     1107
     1108 test-convert-function-with-arg-and-body:
     1109     # . prologue
     1110     55/push-ebp
     1111     89/<- %ebp 4/r32/esp
     1112     # setup
     1113     (clear-stream _test-input-stream)
     1114     (clear-stream $_test-input-buffered-file->buffer)
     1115     (clear-stream _test-output-stream)
     1116     (clear-stream $_test-output-buffered-file->buffer)
     1117     #
     1118     (write _test-input-stream "fn foo n: int {\n")
     1119     (write _test-input-stream "  increment n\n")
     1120     (write _test-input-stream "}\n")
     1121     # convert
     1122     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     1123     (flush _test-output-buffered-file)
     1124 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     1130     # check output
     1131     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-arg-and-body/0")
     1132     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-arg-and-body/1")
     1133     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-arg-and-body/2")
     1134     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-arg-and-body/3")
     1135     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-arg-and-body/4")
     1136     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-arg-and-body/5")
     1137     (check-next-stream-line-equal _test-output-stream "    ff 0/subop/increment *(ebp+0x00000008)"  "F - test-convert-function-with-arg-and-body/6")
     1138     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-arg-and-body/7")
     1139     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-arg-and-body/8")
     1140     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-arg-and-body/9")
     1141     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-arg-and-body/10")
     1142     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-arg-and-body/11")
     1143     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-arg-and-body/12")
     1144     # . epilogue
     1145     89/<- %esp 5/r32/ebp
     1146     5d/pop-to-ebp
     1147     c3/return
     1148
     1149 test-convert-function-distinguishes-args:
     1150     # . prologue
     1151     55/push-ebp
     1152     89/<- %ebp 4/r32/esp
     1153     # setup
     1154     (clear-stream _test-input-stream)
     1155     (clear-stream $_test-input-buffered-file->buffer)
     1156     (clear-stream _test-output-stream)
     1157     (clear-stream $_test-output-buffered-file->buffer)
     1158     #
     1159     (write _test-input-stream "fn foo a: int, b: int {\n")
     1160     (write _test-input-stream "  increment b\n")
     1161     (write _test-input-stream "}\n")
     1162     # convert
     1163     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     1164     (flush _test-output-buffered-file)
     1165 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     1171     # check output
     1172     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-distinguishes-args/0")
     1173     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-distinguishes-args/1")
     1174     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-distinguishes-args/2")
     1175     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-distinguishes-args/3")
     1176     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-distinguishes-args/4")
     1177     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-distinguishes-args/5")
     1178     (check-next-stream-line-equal _test-output-stream "    ff 0/subop/increment *(ebp+0x0000000c)"  "F - test-convert-function-distinguishes-args/6")
     1179     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-distinguishes-args/7")
     1180     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-distinguishes-args/8")
     1181     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-distinguishes-args/9")
     1182     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-distinguishes-args/10")
     1183     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-distinguishes-args/11")
     1184     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-distinguishes-args/12")
     1185     # . epilogue
     1186     89/<- %esp 5/r32/ebp
     1187     5d/pop-to-ebp
     1188     c3/return
     1189
     1190 test-convert-function-with-return-literal:
     1191     # . prologue
     1192     55/push-ebp
     1193     89/<- %ebp 4/r32/esp
     1194     # setup
     1195     (clear-stream _test-input-stream)
     1196     (clear-stream $_test-input-buffered-file->buffer)
     1197     (clear-stream _test-output-stream)
     1198     (clear-stream $_test-output-buffered-file->buffer)
     1199     #
     1200     (write _test-input-stream "fn foo -> _/eax: int {\n")
     1201     (write _test-input-stream "  return 0\n")
     1202     (write _test-input-stream "}\n")
     1203     # convert
     1204     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     1205     (flush _test-output-buffered-file)
     1206 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     1212     # check output
     1213     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return-literal/0")
     1214     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return-literal/1")
     1215     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return-literal/2")
     1216     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return-literal/3")
     1217     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return-literal/4")
     1218     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return-literal/5")
     1219     (check-next-stream-line-equal _test-output-stream "    c7 0/subop/copy %eax 0/imm32"  "F - test-convert-function-with-return-literal/6")
     1220     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-return-literal/7")
     1221     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return-literal/8")
     1222     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return-literal/9")
     1223     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return-literal/10")
     1224     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return-literal/11")
     1225     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return-literal/12")
     1226     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return-literal/13")
     1227     # . epilogue
     1228     89/<- %esp 5/r32/ebp
     1229     5d/pop-to-ebp
     1230     c3/return
     1231
     1232 test-convert-function-with-return:
     1233     # . prologue
     1234     55/push-ebp
     1235     89/<- %ebp 4/r32/esp
     1236     # setup
     1237     (clear-stream _test-input-stream)
     1238     (clear-stream $_test-input-buffered-file->buffer)
     1239     (clear-stream _test-output-stream)
     1240     (clear-stream $_test-output-buffered-file->buffer)
     1241     #
     1242     (write _test-input-stream "fn foo -> _/eax: int {\n")
     1243     (write _test-input-stream "  var y: int\n")
     1244     (write _test-input-stream "  return y\n")
     1245     (write _test-input-stream "}\n")
     1246     # convert
     1247     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     1248     (flush _test-output-buffered-file)
     1249 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     1255     # check output
     1256     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return/0")
     1257     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return/1")
     1258     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return/2")
     1259     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return/3")
     1260     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return/4")
     1261     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return/5")
     1262     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-with-return/6")  # y
     1263     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0xfffffffc) 0x00000000/r32" "F - test-convert-function-with-return/7")
     1264     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-return/8")
     1265     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-return/9")
     1266     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return/10")
     1267     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return/11")
     1268     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return/12")
     1269     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return/13")
     1270     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return/14")
     1271     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return/15")
     1272     # . epilogue
     1273     89/<- %esp 5/r32/ebp
     1274     5d/pop-to-ebp
     1275     c3/return
     1276
     1277 test-convert-function-with-return-float:
     1278     # . prologue
     1279     55/push-ebp
     1280     89/<- %ebp 4/r32/esp
     1281     # setup
     1282     (clear-stream _test-input-stream)
     1283     (clear-stream $_test-input-buffered-file->buffer)
     1284     (clear-stream _test-output-stream)
     1285     (clear-stream $_test-output-buffered-file->buffer)
     1286     #
     1287     (write _test-input-stream "fn foo -> _/xmm0: float {\n")
     1288     (write _test-input-stream "  var y: float\n")
     1289     (write _test-input-stream "  return y\n")
     1290     (write _test-input-stream "}\n")
     1291     # convert
     1292     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     1293     (flush _test-output-buffered-file)
     1294 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     1300     # check output
     1301     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return/0")
     1302     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return/1")
     1303     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return/2")
     1304     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return/3")
     1305     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return/4")
     1306     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return/5")
     1307     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-with-return/6")  # y
     1308     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/-> *(ebp+0xfffffffc) 0x00000000/x32" "F - test-convert-function-with-return/7")
     1309     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-return/8")
     1310     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-return/9")
     1311     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return/10")
     1312     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return/11")
     1313     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return/12")
     1314     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return/13")
     1315     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return/14")
     1316     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return/15")
     1317     # . epilogue
     1318     89/<- %esp 5/r32/ebp
     1319     5d/pop-to-ebp
     1320     c3/return
     1321
     1322 test-convert-function-with-return-register:
     1323     # . prologue
     1324     55/push-ebp
     1325     89/<- %ebp 4/r32/esp
     1326     # setup
     1327     (clear-stream _test-input-stream)
     1328     (clear-stream $_test-input-buffered-file->buffer)
     1329     (clear-stream _test-output-stream)
     1330     (clear-stream $_test-output-buffered-file->buffer)
     1331     #
     1332     (write _test-input-stream "fn foo -> _/eax: int {\n")
     1333     (write _test-input-stream "  var y/eax: int <- copy 3\n")
     1334     (write _test-input-stream "  return y\n")
     1335     (write _test-input-stream "}\n")
     1336     # convert
     1337     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     1338     (flush _test-output-buffered-file)
     1339 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     1345     # check output
     1346     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return-register/0")
     1347     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return-register/1")
     1348     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return-register/2")
     1349     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return-register/3")
     1350     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return-register/4")
     1351     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return-register/5")
     1352     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-with-return-register/6")
     1353     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 3/imm32"  "F - test-convert-function-with-return-register/7")
     1354     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000000/r32" "F - test-convert-function-with-return-register/8")
     1355     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-function-with-return-register/9")
     1356     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-return-register/10")
     1357     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return-register/11")
     1358     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return-register/12")
     1359     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return-register/13")
     1360     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return-register/14")
     1361     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return-register/15")
     1362     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return-register/16")
     1363     # . epilogue
     1364     89/<- %esp 5/r32/ebp
     1365     5d/pop-to-ebp
     1366     c3/return
     1367
     1368 test-function-with-output-without-register:
     1369     # . prologue
     1370     55/push-ebp
     1371     89/<- %ebp 4/r32/esp
     1372     # setup
     1373     (clear-stream _test-input-stream)
     1374     (clear-stream $_test-input-buffered-file->buffer)
     1375     (clear-stream _test-output-stream)
     1376     (clear-stream $_test-output-buffered-file->buffer)
     1377     (clear-stream _test-error-stream)
     1378     (clear-stream $_test-error-buffered-file->buffer)
     1379     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     1380     68/push 0/imm32
     1381     68/push 0/imm32
     1382     89/<- %edx 4/r32/esp
     1383     (tailor-exit-descriptor %edx 0x10)
     1384     #
     1385     (write _test-input-stream "fn foo -> _: int {\n")
     1386     (write _test-input-stream "}\n")
     1387     # convert
     1388     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     1389     # registers except esp clobbered at this point
     1390     # restore ed
     1391     89/<- %edx 4/r32/esp
     1392     (flush _test-output-buffered-file)
     1393     (flush _test-error-buffered-file)
     1394 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     1400     # check output
     1401     (check-stream-equal _test-output-stream  ""  "F - test-function-with-output-without-register: output should be empty")
     1402     (check-next-stream-line-equal _test-error-stream  "fn foo: function output '_' must be in a register, in instruction 'fn foo -> _: int {"  "F - test-function-with-output-without-register: error message")
     1403     # check that stop(1) was called
     1404     (check-ints-equal *(edx+4) 2 "F - test-function-with-output-without-register: exit status")
     1405     # don't restore from ebp
     1406     81 0/subop/add %esp 8/imm32
     1407     # . epilogue
     1408     5d/pop-to-ebp
     1409     c3/return
     1410
     1411 test-function-with-outputs-in-conflicting-registers:
     1412     # . prologue
     1413     55/push-ebp
     1414     89/<- %ebp 4/r32/esp
     1415     # setup
     1416     (clear-stream _test-input-stream)
     1417     (clear-stream $_test-input-buffered-file->buffer)
     1418     (clear-stream _test-output-stream)
     1419     (clear-stream $_test-output-buffered-file->buffer)
     1420     (clear-stream _test-error-stream)
     1421     (clear-stream $_test-error-buffered-file->buffer)
     1422     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     1423     68/push 0/imm32
     1424     68/push 0/imm32
     1425     89/<- %edx 4/r32/esp
     1426     (tailor-exit-descriptor %edx 0x10)
     1427     #
     1428     (write _test-input-stream "fn foo -> _/eax: int, _/eax: int {\n")
     1429     (write _test-input-stream "}\n")
     1430     # convert
     1431     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     1432     # registers except esp clobbered at this point
     1433     # restore ed
     1434     89/<- %edx 4/r32/esp
     1435     (flush _test-output-buffered-file)
     1436     (flush _test-error-buffered-file)
     1437 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     1443     # check output
     1444     (check-stream-equal _test-output-stream  ""  "F - test-function-with-outputs-in-conflicting-registers: output should be empty")
     1445     (check-next-stream-line-equal _test-error-stream  "fn foo: outputs must be in unique registers"  "F - test-function-with-outputs-in-conflicting-registers: error message")
     1446     # check that stop(1) was called
     1447     (check-ints-equal *(edx+4) 2 "F - test-function-with-outputs-in-conflicting-registers: exit status")
     1448     # don't restore from ebp
     1449     81 0/subop/add %esp 8/imm32
     1450     # . epilogue
     1451     5d/pop-to-ebp
     1452     c3/return
     1453
     1454 test-function-with-named-output:
     1455     # . prologue
     1456     55/push-ebp
     1457     89/<- %ebp 4/r32/esp
     1458     # setup
     1459     (clear-stream _test-input-stream)
     1460     (clear-stream $_test-input-buffered-file->buffer)
     1461     (clear-stream _test-output-stream)
     1462     (clear-stream $_test-output-buffered-file->buffer)
     1463     (clear-stream _test-error-stream)
     1464     (clear-stream $_test-error-buffered-file->buffer)
     1465     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     1466     68/push 0/imm32
     1467     68/push 0/imm32
     1468     89/<- %edx 4/r32/esp
     1469     (tailor-exit-descriptor %edx 0x10)
     1470     #
     1471     (write _test-input-stream "fn foo -> x/eax: int {\n")
     1472     (write _test-input-stream "  return 0\n")
     1473     (write _test-input-stream "}\n")
     1474     # convert
     1475     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     1476     # registers except esp clobbered at this point
     1477     # restore ed
     1478     89/<- %edx 4/r32/esp
     1479     (flush _test-output-buffered-file)
     1480     (flush _test-error-buffered-file)
     1481 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     1487     # check output
     1488     (check-stream-equal _test-output-stream  ""  "F - test-function-with-named-output: output should be empty")
     1489     (check-next-stream-line-equal _test-error-stream  "fn foo: function outputs cannot be named; rename 'x' in the header to '_'"  "F - test-function-with-named-output: error message")
     1490     # check that stop(1) was called
     1491     (check-ints-equal *(edx+4) 2 "F - test-function-with-named-output: exit status")
     1492     # don't restore from ebp
     1493     81 0/subop/add %esp 8/imm32
     1494     # . epilogue
     1495     5d/pop-to-ebp
     1496     c3/return
     1497
     1498 test-return-with-wrong-type:
     1499     # . prologue
     1500     55/push-ebp
     1501     89/<- %ebp 4/r32/esp
     1502     # setup
     1503     (clear-stream _test-input-stream)
     1504     (clear-stream $_test-input-buffered-file->buffer)
     1505     (clear-stream _test-output-stream)
     1506     (clear-stream $_test-output-buffered-file->buffer)
     1507     (clear-stream _test-error-stream)
     1508     (clear-stream $_test-error-buffered-file->buffer)
     1509     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     1510     68/push 0/imm32
     1511     68/push 0/imm32
     1512     89/<- %edx 4/r32/esp
     1513     (tailor-exit-descriptor %edx 0x10)
     1514     #
     1515     (write _test-input-stream "fn foo -> _/eax: int {\n")
     1516     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
     1517     (write _test-input-stream "  return x\n")
     1518     (write _test-input-stream "}\n")
     1519     # convert
     1520     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     1521     # registers except esp clobbered at this point
     1522     # restore ed
     1523     89/<- %edx 4/r32/esp
     1524     (flush _test-output-buffered-file)
     1525     (flush _test-error-buffered-file)
     1526 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     1532     # check output
     1533     (check-stream-equal _test-output-stream  ""  "F - test-return-with-wrong-type: output should be empty")
     1534     (check-next-stream-line-equal _test-error-stream  "fn foo: return: 'x' has the wrong type"  "F - test-return-with-wrong-type: error message")
     1535     # check that stop(1) was called
     1536     (check-ints-equal *(edx+4) 2 "F - test-return-with-wrong-type: exit status")
     1537     # don't restore from ebp
     1538     81 0/subop/add %esp 8/imm32
     1539     # . epilogue
     1540     5d/pop-to-ebp
     1541     c3/return
     1542
     1543 test-missing-return:
     1544     # . prologue
     1545     55/push-ebp
     1546     89/<- %ebp 4/r32/esp
     1547     # setup
     1548     (clear-stream _test-input-stream)
     1549     (clear-stream $_test-input-buffered-file->buffer)
     1550     (clear-stream _test-output-stream)
     1551     (clear-stream $_test-output-buffered-file->buffer)
     1552     (clear-stream _test-error-stream)
     1553     (clear-stream $_test-error-buffered-file->buffer)
     1554     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     1555     68/push 0/imm32
     1556     68/push 0/imm32
     1557     89/<- %edx 4/r32/esp
     1558     (tailor-exit-descriptor %edx 0x10)
     1559     #
     1560     (write _test-input-stream "fn foo -> _/eax: int {\n")
     1561     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
     1562     (write _test-input-stream "}\n")
     1563     # convert
     1564     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     1565     # registers except esp clobbered at this point
     1566     # restore ed
     1567     89/<- %edx 4/r32/esp
     1568     (flush _test-output-buffered-file)
     1569     (flush _test-error-buffered-file)
     1570 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     1576     # check output
     1577     (check-stream-equal _test-output-stream  ""  "F - test-missing-return: output should be empty")
     1578     (check-next-stream-line-equal _test-error-stream  "fn foo: final statement should be a 'return'"  "F - test-missing-return: error message")
     1579     # check that stop(1) was called
     1580     (check-ints-equal *(edx+4) 2 "F - test-missing-return: exit status")
     1581     # don't restore from ebp
     1582     81 0/subop/add %esp 8/imm32
     1583     # . epilogue
     1584     5d/pop-to-ebp
     1585     c3/return
     1586
     1587 test-missing-return-2:
     1588     # . prologue
     1589     55/push-ebp
     1590     89/<- %ebp 4/r32/esp
     1591     # setup
     1592     (clear-stream _test-input-stream)
     1593     (clear-stream $_test-input-buffered-file->buffer)
     1594     (clear-stream _test-output-stream)
     1595     (clear-stream $_test-output-buffered-file->buffer)
     1596     (clear-stream _test-error-stream)
     1597     (clear-stream $_test-error-buffered-file->buffer)
     1598     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     1599     68/push 0/imm32
     1600     68/push 0/imm32
     1601     89/<- %edx 4/r32/esp
     1602     (tailor-exit-descriptor %edx 0x10)
     1603     #
     1604     (write _test-input-stream "fn foo -> _/eax: int {\n")
     1605     (write _test-input-stream "}\n")
     1606     # convert
     1607     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     1608     # registers except esp clobbered at this point
     1609     # restore ed
     1610     89/<- %edx 4/r32/esp
     1611     (flush _test-output-buffered-file)
     1612     (flush _test-error-buffered-file)
     1613 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     1619     # check output
     1620     (check-stream-equal _test-output-stream  ""  "F - test-missing-return-2: output should be empty")
     1621     (check-next-stream-line-equal _test-error-stream  "fn foo: final statement should be a 'return'"  "F - test-missing-return-2: error message")
     1622     # check that stop(1) was called
     1623     (check-ints-equal *(edx+4) 2 "F - test-missing-return-2: exit status")
     1624     # don't restore from ebp
     1625     81 0/subop/add %esp 8/imm32
     1626     # . epilogue
     1627     5d/pop-to-ebp
     1628     c3/return
     1629
     1630 test-early-exit-without-return:
     1631     # . prologue
     1632     55/push-ebp
     1633     89/<- %ebp 4/r32/esp
     1634     # setup
     1635     (clear-stream _test-input-stream)
     1636     (clear-stream $_test-input-buffered-file->buffer)
     1637     (clear-stream _test-output-stream)
     1638     (clear-stream $_test-output-buffered-file->buffer)
     1639     (clear-stream _test-error-stream)
     1640     (clear-stream $_test-error-buffered-file->buffer)
     1641     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     1642     68/push 0/imm32
     1643     68/push 0/imm32
     1644     89/<- %edx 4/r32/esp
     1645     (tailor-exit-descriptor %edx 0x10)
     1646     #
     1647     (write _test-input-stream "fn foo -> _/eax: int {\n")
     1648     (write _test-input-stream "  break\n")
     1649     (write _test-input-stream "  return 0\n")
     1650     (write _test-input-stream "}\n")
     1651     # convert
     1652     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     1653     # registers except esp clobbered at this point
     1654     # restore ed
     1655     89/<- %edx 4/r32/esp
     1656     (flush _test-output-buffered-file)
     1657     (flush _test-error-buffered-file)
     1658 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     1664     # check output
     1665     (check-stream-equal _test-output-stream  ""  "F - test-early-exit-without-return: output should be empty")
     1666     (check-next-stream-line-equal _test-error-stream  "fn foo has outputs, so you cannot 'break' out of the outermost block. Use 'return'."  "F - test-early-exit-without-return: error message")
     1667     # check that stop(1) was called
     1668     (check-ints-equal *(edx+4) 2 "F - test-early-exit-without-return: exit status")
     1669     # don't restore from ebp
     1670     81 0/subop/add %esp 8/imm32
     1671     # . epilogue
     1672     5d/pop-to-ebp
     1673     c3/return
     1674
     1675 test-return-with-too-few-inouts:
     1676     # . prologue
     1677     55/push-ebp
     1678     89/<- %ebp 4/r32/esp
     1679     # setup
     1680     (clear-stream _test-input-stream)
     1681     (clear-stream $_test-input-buffered-file->buffer)
     1682     (clear-stream _test-output-stream)
     1683     (clear-stream $_test-output-buffered-file->buffer)
     1684     (clear-stream _test-error-stream)
     1685     (clear-stream $_test-error-buffered-file->buffer)
     1686     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     1687     68/push 0/imm32
     1688     68/push 0/imm32
     1689     89/<- %edx 4/r32/esp
     1690     (tailor-exit-descriptor %edx 0x10)
     1691     #
     1692     (write _test-input-stream "fn foo -> _/eax: int {\n")
     1693     (write _test-input-stream "  return\n")
     1694     (write _test-input-stream "}\n")
     1695     # convert
     1696     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     1697     # registers except esp clobbered at this point
     1698     # restore ed
     1699     89/<- %edx 4/r32/esp
     1700     (flush _test-output-buffered-file)
     1701     (flush _test-error-buffered-file)
     1702 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     1708     # check output
     1709     (check-stream-equal _test-output-stream  ""  "F - test-return-with-too-few-inouts: output should be empty")
     1710     (check-next-stream-line-equal _test-error-stream  "fn foo: return: too few inouts"  "F - test-return-with-too-few-inouts: error message")
     1711     # check that stop(1) was called
     1712     (check-ints-equal *(edx+4) 2 "F - test-return-with-too-few-inouts: exit status")
     1713     # don't restore from ebp
     1714     81 0/subop/add %esp 8/imm32
     1715     # . epilogue
     1716     5d/pop-to-ebp
     1717     c3/return
     1718
     1719 test-return-with-too-many-inouts:
     1720     # . prologue
     1721     55/push-ebp
     1722     89/<- %ebp 4/r32/esp
     1723     # setup
     1724     (clear-stream _test-input-stream)
     1725     (clear-stream $_test-input-buffered-file->buffer)
     1726     (clear-stream _test-output-stream)
     1727     (clear-stream $_test-output-buffered-file->buffer)
     1728     (clear-stream _test-error-stream)
     1729     (clear-stream $_test-error-buffered-file->buffer)
     1730     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     1731     68/push 0/imm32
     1732     68/push 0/imm32
     1733     89/<- %edx 4/r32/esp
     1734     (tailor-exit-descriptor %edx 0x10)
     1735     #
     1736     (write _test-input-stream "fn foo -> _/eax: int {\n")
     1737     (write _test-input-stream "  return 0, 0\n")
     1738     (write _test-input-stream "}\n")
     1739     # convert
     1740     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     1741     # registers except esp clobbered at this point
     1742     # restore ed
     1743     89/<- %edx 4/r32/esp
     1744     (flush _test-output-buffered-file)
     1745     (flush _test-error-buffered-file)
     1746 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     1752     # check output
     1753     (check-stream-equal _test-output-stream  ""  "F - test-return-with-too-many-inouts: output should be empty")
     1754     (check-next-stream-line-equal _test-error-stream  "fn foo: return: too many inouts"  "F - test-return-with-too-many-inouts: error message")
     1755     # check that stop(1) was called
     1756     (check-ints-equal *(edx+4) 2 "F - test-return-with-too-many-inouts: exit status")
     1757     # don't restore from ebp
     1758     81 0/subop/add %esp 8/imm32
     1759     # . epilogue
     1760     5d/pop-to-ebp
     1761     c3/return
     1762
     1763 test-return-unavailable-value:
     1764     # . prologue
     1765     55/push-ebp
     1766     89/<- %ebp 4/r32/esp
     1767     # setup
     1768     (clear-stream _test-input-stream)
     1769     (clear-stream $_test-input-buffered-file->buffer)
     1770     (clear-stream _test-output-stream)
     1771     (clear-stream $_test-output-buffered-file->buffer)
     1772     (clear-stream _test-error-stream)
     1773     (clear-stream $_test-error-buffered-file->buffer)
     1774     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     1775     68/push 0/imm32
     1776     68/push 0/imm32
     1777     89/<- %edx 4/r32/esp
     1778     (tailor-exit-descriptor %edx 0x10)
     1779     #
     1780     (write _test-input-stream "fn foo -> _/eax: int, _/ecx: int {\n")
     1781     (write _test-input-stream "  var x/eax: int <- copy 0\n")
     1782     (write _test-input-stream "  var y/ecx: int <- copy 0\n")
     1783     (write _test-input-stream "  return y, x\n")
     1784     (write _test-input-stream "}\n")
     1785     # convert
     1786     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     1787     # registers except esp clobbered at this point
     1788     # restore ed
     1789     89/<- %edx 4/r32/esp
     1790     (flush _test-output-buffered-file)
     1791     (flush _test-error-buffered-file)
     1792 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     1798     # check output
     1799     (check-stream-equal _test-output-stream  ""  "F - test-return-unavailable-value: output should be empty")
     1800     (check-next-stream-line-equal _test-error-stream  "fn foo: return: 'x' is no longer available"  "F - test-return-unavailable-value: error message")
     1801     # check that stop(1) was called
     1802     (check-ints-equal *(edx+4) 2 "F - test-return-unavailable-value: exit status")
     1803     # don't restore from ebp
     1804     81 0/subop/add %esp 8/imm32
     1805     # . epilogue
     1806     5d/pop-to-ebp
     1807     c3/return
     1808
     1809 test-return-literal-to-float:
     1810     # . prologue
     1811     55/push-ebp
     1812     89/<- %ebp 4/r32/esp
     1813     # setup
     1814     (clear-stream _test-input-stream)
     1815     (clear-stream $_test-input-buffered-file->buffer)
     1816     (clear-stream _test-output-stream)
     1817     (clear-stream $_test-output-buffered-file->buffer)
     1818     (clear-stream _test-error-stream)
     1819     (clear-stream $_test-error-buffered-file->buffer)
     1820     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     1821     68/push 0/imm32
     1822     68/push 0/imm32
     1823     89/<- %edx 4/r32/esp
     1824     (tailor-exit-descriptor %edx 0x10)
     1825     #
     1826     (write _test-input-stream "fn foo -> _/xmm0: float {\n")
     1827     (write _test-input-stream "  return 0\n")
     1828     (write _test-input-stream "}\n")
     1829     # convert
     1830     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     1831     # registers except esp clobbered at this point
     1832     # restore ed
     1833     89/<- %edx 4/r32/esp
     1834     (flush _test-output-buffered-file)
     1835     (flush _test-error-buffered-file)
     1836 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     1842     # check output
     1843     (check-stream-equal _test-output-stream  ""  "F - test-return-literal-to-float: output should be empty")
     1844     (check-next-stream-line-equal _test-error-stream  "fn foo: return: cannot copy literal '0' to float"  "F - test-return-literal-to-float: error message")
     1845     # check that stop(1) was called
     1846     (check-ints-equal *(edx+4) 2 "F - test-return-literal-to-float: exit status")
     1847     # don't restore from ebp
     1848     81 0/subop/add %esp 8/imm32
     1849     # . epilogue
     1850     5d/pop-to-ebp
     1851     c3/return
     1852
     1853 test-convert-return-with-duplicate-values:
     1854     # . prologue
     1855     55/push-ebp
     1856     89/<- %ebp 4/r32/esp
     1857     # setup
     1858     (clear-stream _test-input-stream)
     1859     (clear-stream $_test-input-buffered-file->buffer)
     1860     (clear-stream _test-output-stream)
     1861     (clear-stream $_test-output-buffered-file->buffer)
     1862     #
     1863     (write _test-input-stream "fn foo -> _/eax: int, _/ecx: int {\n")
     1864     (write _test-input-stream "  var x/eax: int <- copy 0x34\n")
     1865     (write _test-input-stream "  return x, x\n")
     1866     (write _test-input-stream "}\n")
     1867     # convert
     1868     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     1869     (flush _test-output-buffered-file)
     1870 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     1876     # check output
     1877     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-return-with-duplicate-values/0")
     1878     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-return-with-duplicate-values/1")
     1879     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-return-with-duplicate-values/2")
     1880     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-return-with-duplicate-values/3")
     1881     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-return-with-duplicate-values/4")
     1882     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-return-with-duplicate-values/5")
     1883     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-return-with-duplicate-values/6")
     1884     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0x34/imm32"  "F - test-convert-return-with-duplicate-values/7")
     1885     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000000/r32"  "F - test-convert-return-with-duplicate-values/8")
     1886     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000001/r32"  "F - test-convert-return-with-duplicate-values/9")
     1887     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-return-with-duplicate-values/10")
     1888     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-return-with-duplicate-values/11")
     1889     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-return-with-duplicate-values/12")
     1890     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-return-with-duplicate-values/13")
     1891     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-return-with-duplicate-values/14")
     1892     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-return-with-duplicate-values/15")
     1893     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-return-with-duplicate-values/16")
     1894     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-return-with-duplicate-values/17")
     1895     # . epilogue
     1896     89/<- %esp 5/r32/ebp
     1897     5d/pop-to-ebp
     1898     c3/return
     1899
     1900 test-convert-return-with-duplicate-values-2:
     1901     # . prologue
     1902     55/push-ebp
     1903     89/<- %ebp 4/r32/esp
     1904     # setup
     1905     (clear-stream _test-input-stream)
     1906     (clear-stream $_test-input-buffered-file->buffer)
     1907     (clear-stream _test-output-stream)
     1908     (clear-stream $_test-output-buffered-file->buffer)
     1909     #
     1910     (write _test-input-stream "fn foo -> _/eax: int, _/ecx: int {\n")
     1911     (write _test-input-stream "  var x/ecx: int <- copy 0x34\n")
     1912     (write _test-input-stream "  return x, x\n")
     1913     (write _test-input-stream "}\n")
     1914     # convert
     1915     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     1916     (flush _test-output-buffered-file)
     1917 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     1923     # check output
     1924     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-return-with-duplicate-values-2/0")
     1925     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-return-with-duplicate-values-2/1")
     1926     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-return-with-duplicate-values-2/2")
     1927     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-return-with-duplicate-values-2/3")
     1928     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-return-with-duplicate-values-2/4")
     1929     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-return-with-duplicate-values-2/5")
     1930     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-return-with-duplicate-values-2/6")
     1931     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0x34/imm32"  "F - test-convert-return-with-duplicate-values-2/7")
     1932     (check-next-stream-line-equal _test-output-stream "    8b/-> %ecx 0x00000000/r32"  "F - test-convert-return-with-duplicate-values-2/8")
     1933     (check-next-stream-line-equal _test-output-stream "    8b/-> %ecx 0x00000001/r32"  "F - test-convert-return-with-duplicate-values-2/9")
     1934     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-return-with-duplicate-values-2/10")
     1935     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-return-with-duplicate-values-2/11")
     1936     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-return-with-duplicate-values-2/12")
     1937     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-return-with-duplicate-values-2/13")
     1938     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-return-with-duplicate-values-2/14")
     1939     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-return-with-duplicate-values-2/15")
     1940     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-return-with-duplicate-values-2/16")
     1941     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-return-with-duplicate-values-2/17")
     1942     # . epilogue
     1943     89/<- %esp 5/r32/ebp
     1944     5d/pop-to-ebp
     1945     c3/return
     1946
     1947 test-stmt-with-unknown-var:
     1948     # . prologue
     1949     55/push-ebp
     1950     89/<- %ebp 4/r32/esp
     1951     # setup
     1952     (clear-stream _test-input-stream)
     1953     (clear-stream $_test-input-buffered-file->buffer)
     1954     (clear-stream _test-output-stream)
     1955     (clear-stream $_test-output-buffered-file->buffer)
     1956     (clear-stream _test-error-stream)
     1957     (clear-stream $_test-error-buffered-file->buffer)
     1958     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     1959     68/push 0/imm32
     1960     68/push 0/imm32
     1961     89/<- %edx 4/r32/esp
     1962     (tailor-exit-descriptor %edx 0x10)
     1963     #
     1964     (write _test-input-stream "fn foo {\n")
     1965     (write _test-input-stream "  x <- copy 0x34\n")
     1966     (write _test-input-stream "}\n")
     1967     # convert
     1968     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     1969     # registers except esp clobbered at this point
     1970     # restore ed
     1971     89/<- %edx 4/r32/esp
     1972     (flush _test-output-buffered-file)
     1973     (flush _test-error-buffered-file)
     1974 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     1980     # check output
     1981     (check-stream-equal _test-output-stream  ""  "F - test-stmt-with-unknown-var: output should be empty")
     1982     (check-next-stream-line-equal _test-error-stream  "fn foo: unknown variable 'x'"  "F - test-stmt-with-unknown-var: error message")
     1983     # check that stop(1) was called
     1984     (check-ints-equal *(edx+4) 2 "F - test-stmt-with-unknown-var: exit status")
     1985     # don't restore from ebp
     1986     81 0/subop/add %esp 8/imm32
     1987     # . epilogue
     1988     5d/pop-to-ebp
     1989     c3/return
     1990
     1991 test-stmt-with-invalid-identifier:
     1992     # . prologue
     1993     55/push-ebp
     1994     89/<- %ebp 4/r32/esp
     1995     # setup
     1996     (clear-stream _test-input-stream)
     1997     (clear-stream $_test-input-buffered-file->buffer)
     1998     (clear-stream _test-output-stream)
     1999     (clear-stream $_test-output-buffered-file->buffer)
     2000     (clear-stream _test-error-stream)
     2001     (clear-stream $_test-error-buffered-file->buffer)
     2002     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     2003     68/push 0/imm32
     2004     68/push 0/imm32
     2005     89/<- %edx 4/r32/esp
     2006     (tailor-exit-descriptor %edx 0x10)
     2007     #
     2008     (write _test-input-stream "fn foo {\n")
     2009     (write _test-input-stream "  1 <- copy 0x34\n")
     2010     (write _test-input-stream "}\n")
     2011     # convert
     2012     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     2013     # registers except esp clobbered at this point
     2014     # restore ed
     2015     89/<- %edx 4/r32/esp
     2016     (flush _test-output-buffered-file)
     2017     (flush _test-error-buffered-file)
     2018 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     2024     # check output
     2025     (check-stream-equal _test-output-stream  ""  "F - test-stmt-with-invalid-identifier: output should be empty")
     2026     (check-next-stream-line-equal _test-error-stream  "fn foo: invalid identifier '1'"  "F - test-stmt-with-invalid-identifier: error message")
     2027     # check that stop(1) was called
     2028     (check-ints-equal *(edx+4) 2 "F - test-stmt-with-invalid-identifier: exit status")
     2029     # don't restore from ebp
     2030     81 0/subop/add %esp 8/imm32
     2031     # . epilogue
     2032     5d/pop-to-ebp
     2033     c3/return
     2034
     2035 test-stmt-with-deref-var:
     2036     # . prologue
     2037     55/push-ebp
     2038     89/<- %ebp 4/r32/esp
     2039     # setup
     2040     (clear-stream _test-input-stream)
     2041     (clear-stream $_test-input-buffered-file->buffer)
     2042     (clear-stream _test-output-stream)
     2043     (clear-stream $_test-output-buffered-file->buffer)
     2044     (clear-stream _test-error-stream)
     2045     (clear-stream $_test-error-buffered-file->buffer)
     2046     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     2047     68/push 0/imm32
     2048     68/push 0/imm32
     2049     89/<- %edx 4/r32/esp
     2050     (tailor-exit-descriptor %edx 0x10)
     2051     #
     2052     (write _test-input-stream "fn foo {\n")
     2053     (write _test-input-stream "  *x <- copy 0x34\n")
     2054     (write _test-input-stream "}\n")
     2055     # convert
     2056     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     2057     # registers except esp clobbered at this point
     2058     # restore ed
     2059     89/<- %edx 4/r32/esp
     2060     (flush _test-output-buffered-file)
     2061     (flush _test-error-buffered-file)
     2062 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     2068     # check output
     2069     (check-stream-equal _test-output-stream  ""  "F - test-stmt-with-deref-var: output should be empty")
     2070     (check-next-stream-line-equal _test-error-stream  "fn foo: output '*x' should write to a register, and therefore cannot be dereferenced"  "F - test-stmt-with-deref-var: error message")
     2071     # check that stop(1) was called
     2072     (check-ints-equal *(edx+4) 2 "F - test-stmt-with-deref-var: exit status")
     2073     # don't restore from ebp
     2074     81 0/subop/add %esp 8/imm32
     2075     # . epilogue
     2076     5d/pop-to-ebp
     2077     c3/return
     2078
     2079 test-convert-function-with-literal-arg:
     2080     # . prologue
     2081     55/push-ebp
     2082     89/<- %ebp 4/r32/esp
     2083     # setup
     2084     (clear-stream _test-input-stream)
     2085     (clear-stream $_test-input-buffered-file->buffer)
     2086     (clear-stream _test-output-stream)
     2087     (clear-stream $_test-output-buffered-file->buffer)
     2088     #
     2089     (write _test-input-stream "fn foo a: int, b: int -> _/eax: int {\n")
     2090     (write _test-input-stream "  var result/eax: int <- copy a\n")
     2091     (write _test-input-stream "  result <- add 1\n")
     2092     (write _test-input-stream "  return result\n")
     2093     (write _test-input-stream "}\n")
     2094     # convert
     2095     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     2096     (flush _test-output-buffered-file)
     2097 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     2103     # check output
     2104     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-literal-arg/0")
     2105     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-literal-arg/1")
     2106     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-literal-arg/2")
     2107     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-literal-arg/3")
     2108     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-literal-arg/4")
     2109     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-literal-arg/5")
     2110     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-with-literal-arg/6")
     2111     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000000/r32"  "F - test-convert-function-with-literal-arg/7")
     2112     (check-next-stream-line-equal _test-output-stream "    05/add-to-eax 1/imm32"  "F - test-convert-function-with-literal-arg/8")
     2113     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000000/r32" "F - test-convert-function-with-literal-arg/9")
     2114     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-function-with-literal-arg/10")
     2115     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-literal-arg/11")
     2116     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-literal-arg/12")
     2117     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-literal-arg/13")
     2118     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-literal-arg/14")
     2119     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-literal-arg/15")
     2120     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-literal-arg/16")
     2121     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-literal-arg/17")
     2122     # . epilogue
     2123     89/<- %esp 5/r32/ebp
     2124     5d/pop-to-ebp
     2125     c3/return
     2126
     2127 test-convert-function-with-literal-arg-2:
     2128     # . prologue
     2129     55/push-ebp
     2130     89/<- %ebp 4/r32/esp
     2131     # setup
     2132     (clear-stream _test-input-stream)
     2133     (clear-stream $_test-input-buffered-file->buffer)
     2134     (clear-stream _test-output-stream)
     2135     (clear-stream $_test-output-buffered-file->buffer)
     2136     #
     2137     (write _test-input-stream "fn foo a: int, b: int -> _/ebx: int {\n")
     2138     (write _test-input-stream "  var result/ebx: int <- copy a\n")
     2139     (write _test-input-stream "  result <- add 1\n")
     2140     (write _test-input-stream "  return result\n")
     2141     (write _test-input-stream "}\n")
     2142     # convert
     2143     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     2144     (flush _test-output-buffered-file)
     2145 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     2151     # check output
     2152     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-literal-arg-2/0")
     2153     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-literal-arg-2/1")
     2154     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-literal-arg-2/2")
     2155     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-literal-arg-2/3")
     2156     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-literal-arg-2/4")
     2157     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-literal-arg-2/5")
     2158     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ebx"  "F - test-convert-function-with-literal-arg-2/6")
     2159     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000003/r32"  "F - test-convert-function-with-literal-arg-2/7")
     2160     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %ebx 1/imm32"  "F - test-convert-function-with-literal-arg-2/8")
     2161     (check-next-stream-line-equal _test-output-stream "    8b/-> %ebx 0x00000003/r32" "F - test-convert-function-with-literal-arg-2/9")
     2162     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-function-with-literal-arg-2/10")
     2163     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-literal-arg-2/11")
     2164     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-literal-arg-2/12")
     2165     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-literal-arg-2/13")
     2166     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-literal-arg-2/14")
     2167     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-literal-arg-2/15")
     2168     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-literal-arg-2/16")
     2169     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-literal-arg-2/17")
     2170     # . epilogue
     2171     89/<- %esp 5/r32/ebp
     2172     5d/pop-to-ebp
     2173     c3/return
     2174
     2175 test-convert-function-call-with-literal-arg:
     2176     # . prologue
     2177     55/push-ebp
     2178     89/<- %ebp 4/r32/esp
     2179     # setup
     2180     (clear-stream _test-input-stream)
     2181     (clear-stream $_test-input-buffered-file->buffer)
     2182     (clear-stream _test-output-stream)
     2183     (clear-stream $_test-output-buffered-file->buffer)
     2184     #
     2185     (write _test-input-stream "fn main -> _/ebx: int {\n")
     2186     (write _test-input-stream "  var result/eax: int <- do-add 3 4\n")
     2187     (write _test-input-stream "  return result\n")
     2188     (write _test-input-stream "}\n")
     2189     (write _test-input-stream "fn do-add a: int, b: int -> _/eax: int {\n")
     2190     (write _test-input-stream "  var result/eax: int <- copy a\n")
     2191     (write _test-input-stream "  result <- add b\n")
     2192     (write _test-input-stream "  return result\n")
     2193     (write _test-input-stream "}\n")
     2194     # convert
     2195     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     2196     (flush _test-output-buffered-file)
     2197 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     2203     # check output
     2204     (check-next-stream-line-equal _test-output-stream "main:"                   "F - test-convert-function-call-with-literal-arg/0")
     2205     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-literal-arg/1")
     2206     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-literal-arg/2")
     2207     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call-with-literal-arg/3")
     2208     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-literal-arg/4")
     2209     (check-next-stream-line-equal _test-output-stream "$main:0x00000001:loop:"  "F - test-convert-function-call-with-literal-arg/5")
     2210     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-call-with-literal-arg/6")
     2211     (check-next-stream-line-equal _test-output-stream "    (do-add 3 4)"        "F - test-convert-function-call-with-literal-arg/7")
     2212     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000003/r32" "F - test-convert-function-call-with-literal-arg/8")
     2213     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax" "F - test-convert-function-with-local-var-in-reg/9")
     2214     (check-next-stream-line-equal _test-output-stream "    e9/jump $main:0x00000001:break/disp32"  "F - test-convert-function-call-with-literal-arg/10")
     2215     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-literal-arg/11")
     2216     (check-next-stream-line-equal _test-output-stream "$main:0x00000001:break:" "F - test-convert-function-call-with-literal-arg/12")
     2217     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-literal-arg/13")
     2218     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call-with-literal-arg/14")
     2219     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-literal-arg/15")
     2220     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-literal-arg/16")
     2221     (check-next-stream-line-equal _test-output-stream "do-add:"                 "F - test-convert-function-call-with-literal-arg/17")
     2222     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-literal-arg/18")
     2223     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-literal-arg/19")
     2224     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call-with-literal-arg/20")
     2225     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-literal-arg/21")
     2226     (check-next-stream-line-equal _test-output-stream "$do-add:0x00000002:loop:"  "F - test-convert-function-call-with-literal-arg/22")
     2227     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-call-with-literal-arg/23")
     2228     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000000/r32"  "F - test-convert-function-call-with-literal-arg/24")
     2229     (check-next-stream-line-equal _test-output-stream "    03/add *(ebp+0x0000000c) 0x00000000/r32"  "F - test-convert-function-call-with-literal-arg/25")
     2230     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000000/r32" "F - test-convert-function-call-with-literal-arg/26")
     2231     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-function-call-with-literal-arg/27")
     2232     (check-next-stream-line-equal _test-output-stream "    e9/jump $do-add:0x00000002:break/disp32"  "F - test-convert-function-call-with-literal-arg/28")
     2233     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-literal-arg/29")
     2234     (check-next-stream-line-equal _test-output-stream "$do-add:0x00000002:break:"  "F - test-convert-function-call-with-literal-arg/30")
     2235     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-literal-arg/31")
     2236     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call-with-literal-arg/32")
     2237     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-literal-arg/33")
     2238     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-literal-arg/34")
     2239     # . epilogue
     2240     89/<- %esp 5/r32/ebp
     2241     5d/pop-to-ebp
     2242     c3/return
     2243
     2244 test-convert-function-call-with-literal-string-arg:
     2245     # . prologue
     2246     55/push-ebp
     2247     89/<- %ebp 4/r32/esp
     2248     # setup
     2249     (clear-stream _test-input-stream)
     2250     (clear-stream $_test-input-buffered-file->buffer)
     2251     (clear-stream _test-output-stream)
     2252     (clear-stream $_test-output-buffered-file->buffer)
     2253     #
     2254     (write _test-input-stream "fn foo {\n")
     2255     (write _test-input-stream "  string-func \"abc\"\n")
     2256     (write _test-input-stream "}\n")
     2257     (write _test-input-stream "sig string-func in: (addr array byte)\n")
     2258     # convert
     2259     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     2260     # no errors
     2261     # not bothering checking output
     2262     # . epilogue
     2263     89/<- %esp 5/r32/ebp
     2264     5d/pop-to-ebp
     2265     c3/return
     2266
     2267 test-convert-function-call-with-null-addr:
     2268     # . prologue
     2269     55/push-ebp
     2270     89/<- %ebp 4/r32/esp
     2271     # setup
     2272     (clear-stream _test-input-stream)
     2273     (clear-stream $_test-input-buffered-file->buffer)
     2274     (clear-stream _test-output-stream)
     2275     (clear-stream $_test-output-buffered-file->buffer)
     2276     #
     2277     (write _test-input-stream "fn foo {\n")
     2278     (write _test-input-stream "  bar 0\n")
     2279     (write _test-input-stream "}\n")
     2280     (write _test-input-stream "sig bar in: (addr int)\n")
     2281     # convert
     2282     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     2283     # no errors
     2284     # not bothering checking output
     2285     # . epilogue
     2286     89/<- %esp 5/r32/ebp
     2287     5d/pop-to-ebp
     2288     c3/return
     2289
     2290 test-convert-function-call-with-signature:
     2291     # . prologue
     2292     55/push-ebp
     2293     89/<- %ebp 4/r32/esp
     2294     # setup
     2295     (clear-stream _test-input-stream)
     2296     (clear-stream $_test-input-buffered-file->buffer)
     2297     (clear-stream _test-output-stream)
     2298     (clear-stream $_test-output-buffered-file->buffer)
     2299     #
     2300     (write _test-input-stream "fn main -> _/ebx: int {\n")
     2301     (write _test-input-stream "  var result/eax: int <- do-add 3 4\n")
     2302     (write _test-input-stream "  return result\n")
     2303     (write _test-input-stream "}\n")
     2304     (write _test-input-stream "sig do-add a: int, b: int -> _/eax: int\n")
     2305     # convert
     2306     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     2307     (flush _test-output-buffered-file)
     2308 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     2314     # check output
     2315     (check-next-stream-line-equal _test-output-stream "main:"                   "F - test-convert-function-call-with-signature/0")
     2316     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-signature/1")
     2317     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-signature/2")
     2318     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call-with-signature/3")
     2319     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-signature/4")
     2320     (check-next-stream-line-equal _test-output-stream "$main:0x00000001:loop:"  "F - test-convert-function-call-with-signature/5")
     2321     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-call-with-literal-arg/6")
     2322     (check-next-stream-line-equal _test-output-stream "    (do-add 3 4)"        "F - test-convert-function-call-with-signature/6")
     2323     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000003/r32" "F - test-convert-function-call-with-literal-arg/8")
     2324     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax" "F - test-convert-function-with-local-var-in-reg/9")
     2325     (check-next-stream-line-equal _test-output-stream "    e9/jump $main:0x00000001:break/disp32"  "F - test-convert-function-call-with-literal-arg/10")
     2326     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-signature/7")
     2327     (check-next-stream-line-equal _test-output-stream "$main:0x00000001:break:" "F - test-convert-function-call-with-signature/8")
     2328     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-signature/9")
     2329     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call-with-signature/10")
     2330     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-signature/11")
     2331     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-signature/12")
     2332     # . epilogue
     2333     89/<- %esp 5/r32/ebp
     2334     5d/pop-to-ebp
     2335     c3/return
     2336
     2337 test-convert-function-with-local-var-in-mem:
     2338     # . prologue
     2339     55/push-ebp
     2340     89/<- %ebp 4/r32/esp
     2341     # setup
     2342     (clear-stream _test-input-stream)
     2343     (clear-stream $_test-input-buffered-file->buffer)
     2344     (clear-stream _test-output-stream)
     2345     (clear-stream $_test-output-buffered-file->buffer)
     2346     #
     2347     (write _test-input-stream "fn foo {\n")
     2348     (write _test-input-stream "  var x: int\n")
     2349     (write _test-input-stream "  increment x\n")
     2350     (write _test-input-stream "}\n")
     2351     # convert
     2352     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     2353     (flush _test-output-buffered-file)
     2354 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     2360     # check output
     2361     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-in-mem/0")
     2362     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-in-mem/1")
     2363     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-in-mem/2")
     2364     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-in-mem/3")
     2365     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-in-mem/4")
     2366     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-in-mem/5")
     2367     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-with-local-var-in-mem/6")
     2368     (check-next-stream-line-equal _test-output-stream "    ff 0/subop/increment *(ebp+0xfffffffc)"  "F - test-convert-function-with-local-var-in-mem/7")
     2369     (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")
     2370     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-in-mem/9")
     2371     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-in-mem/10")
     2372     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-in-mem/11")
     2373     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-in-mem/12")
     2374     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-in-mem/13")
     2375     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-in-mem/14")
     2376     # . epilogue
     2377     89/<- %esp 5/r32/ebp
     2378     5d/pop-to-ebp
     2379     c3/return
     2380
     2381 test-convert-invalid-literal:
     2382     # . prologue
     2383     55/push-ebp
     2384     89/<- %ebp 4/r32/esp
     2385     # setup
     2386     (clear-stream _test-input-stream)
     2387     (clear-stream $_test-input-buffered-file->buffer)
     2388     (clear-stream _test-output-stream)
     2389     (clear-stream $_test-output-buffered-file->buffer)
     2390     (clear-stream _test-error-stream)
     2391     (clear-stream $_test-error-buffered-file->buffer)
     2392     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     2393     68/push 0/imm32
     2394     68/push 0/imm32
     2395     89/<- %edx 4/r32/esp
     2396     (tailor-exit-descriptor %edx 0x10)
     2397     #
     2398     (write _test-input-stream "fn foo {\n")
     2399     (write _test-input-stream "  increment 1n\n")
     2400     (write _test-input-stream "}\n")
     2401     # convert
     2402     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     2403     # registers except esp clobbered at this point
     2404     # restore ed
     2405     89/<- %edx 4/r32/esp
     2406     (flush _test-output-buffered-file)
     2407     (flush _test-error-buffered-file)
     2408 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     2414     # check output
     2415     (check-stream-equal _test-output-stream  ""  "F - test-convert-invalid-literal: output should be empty")
     2416     (check-next-stream-line-equal _test-error-stream  "fn foo: variable '1n' cannot begin with a digit (or do you have a typo in a number?)"  "F - test-convert-invalid-literal: error message")
     2417     # check that stop(1) was called
     2418     (check-ints-equal *(edx+4) 2 "F - test-convert-invalid-literal: exit status")
     2419     # don't restore from ebp
     2420     81 0/subop/add %esp 8/imm32
     2421     # . epilogue
     2422     5d/pop-to-ebp
     2423     c3/return
     2424
     2425 test-convert-valid-literal-with-metadata:
     2426     # . prologue
     2427     55/push-ebp
     2428     89/<- %ebp 4/r32/esp
     2429     # setup
     2430     (clear-stream _test-input-stream)
     2431     (clear-stream $_test-input-buffered-file->buffer)
     2432     (clear-stream _test-output-stream)
     2433     (clear-stream $_test-output-buffered-file->buffer)
     2434     #
     2435     (write _test-input-stream "fn foo {\n")
     2436     (write _test-input-stream "  var x/eax: int <- copy 1/abc\n")
     2437     (write _test-input-stream "}\n")
     2438     # convert
     2439     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     2440     (flush _test-output-buffered-file)
     2441 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     2447     # no errors
     2448     # . epilogue
     2449     89/<- %esp 5/r32/ebp
     2450     5d/pop-to-ebp
     2451     c3/return
     2452
     2453 test-local-var-in-mem-has-no-initializer:
     2454     # . prologue
     2455     55/push-ebp
     2456     89/<- %ebp 4/r32/esp
     2457     # setup
     2458     (clear-stream _test-input-stream)
     2459     (clear-stream $_test-input-buffered-file->buffer)
     2460     (clear-stream _test-output-stream)
     2461     (clear-stream $_test-output-buffered-file->buffer)
     2462     (clear-stream _test-error-stream)
     2463     (clear-stream $_test-error-buffered-file->buffer)
     2464     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     2465     68/push 0/imm32
     2466     68/push 0/imm32
     2467     89/<- %edx 4/r32/esp
     2468     (tailor-exit-descriptor %edx 0x10)
     2469     #
     2470     (write _test-input-stream "fn foo {\n")
     2471     (write _test-input-stream "  var x: int <- copy 0\n")
     2472     (write _test-input-stream "  increment x\n")
     2473     (write _test-input-stream "}\n")
     2474     # convert
     2475     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     2476     # registers except esp clobbered at this point
     2477     # restore ed
     2478     89/<- %edx 4/r32/esp
     2479     (flush _test-output-buffered-file)
     2480     (flush _test-error-buffered-file)
     2481 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     2487     # check output
     2488     (check-stream-equal _test-output-stream  ""  "F - test-var-in-mem-has-no-initializer: output should be empty")
     2489     (check-next-stream-line-equal _test-error-stream  "fn foo: var x: variables on the stack can't take an initializer"  "F - test-var-in-mem-has-no-initializer: error message")
     2490     # check that stop(1) was called
     2491     (check-ints-equal *(edx+4) 2 "F - test-var-in-mem-has-no-initializer: exit status")
     2492     # don't restore from ebp
     2493     81 0/subop/add %esp 8/imm32
     2494     # . epilogue
     2495     5d/pop-to-ebp
     2496     c3/return
     2497
     2498 test-convert-function-with-local-var-with-compound-type-in-mem:
     2499     # . prologue
     2500     55/push-ebp
     2501     89/<- %ebp 4/r32/esp
     2502     # setup
     2503     (clear-stream _test-input-stream)
     2504     (clear-stream $_test-input-buffered-file->buffer)
     2505     (clear-stream _test-output-stream)
     2506     (clear-stream $_test-output-buffered-file->buffer)
     2507     #
     2508     (write _test-input-stream "fn foo {\n")
     2509     (write _test-input-stream "  var x: (addr int)\n")
     2510     (write _test-input-stream "  copy-to x, 0\n")
     2511     (write _test-input-stream "}\n")
     2512     # convert
     2513     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     2514     (flush _test-output-buffered-file)
     2515 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     2521     # check output
     2522     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-with-compound-type-in-mem/0")
     2523     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-with-compound-type-in-mem/1")
     2524     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-with-compound-type-in-mem/2")
     2525     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-with-compound-type-in-mem/3")
     2526     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-with-compound-type-in-mem/4")
     2527     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-with-compound-type-in-mem/5")
     2528     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-with-local-var-with-compound-type-in-mem/6")
     2529     (check-next-stream-line-equal _test-output-stream "    c7 0/subop/copy *(ebp+0xfffffffc) 0/imm32"  "F - test-convert-function-with-local-var-with-compound-type-in-mem/7")
     2530     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-local-var-with-compound-type-in-mem/8")
     2531     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-with-compound-type-in-mem/9")
     2532     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-with-compound-type-in-mem/10")
     2533     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-with-compound-type-in-mem/11")
     2534     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-with-compound-type-in-mem/12")
     2535     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-with-compound-type-in-mem/13")
     2536     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-with-compound-type-in-mem/14")
     2537     # . epilogue
     2538     89/<- %esp 5/r32/ebp
     2539     5d/pop-to-ebp
     2540     c3/return
     2541
     2542 test-convert-function-with-local-var-in-reg:
     2543     # . prologue
     2544     55/push-ebp
     2545     89/<- %ebp 4/r32/esp
     2546     # setup
     2547     (clear-stream _test-input-stream)
     2548     (clear-stream $_test-input-buffered-file->buffer)
     2549     (clear-stream _test-output-stream)
     2550     (clear-stream $_test-output-buffered-file->buffer)
     2551     #
     2552     (write _test-input-stream "fn foo {\n")
     2553     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
     2554     (write _test-input-stream "  x <- increment\n")
     2555     (write _test-input-stream "}\n")
     2556     # convert
     2557     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     2558     (flush _test-output-buffered-file)
     2559 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     2565     # check output
     2566     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-in-reg/0")
     2567     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-in-reg/1")
     2568     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-in-reg/2")
     2569     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-in-reg/3")
     2570     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-in-reg/4")
     2571     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-in-reg/5")
     2572     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-local-var-in-reg/6")
     2573     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-convert-function-with-local-var-in-reg/7")
     2574     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-convert-function-with-local-var-in-reg/8")
     2575     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-function-with-local-var-in-reg/9")
     2576     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-in-reg/10")
     2577     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-in-reg/11")
     2578     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-in-reg/12")
     2579     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-in-reg/13")
     2580     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-in-reg/14")
     2581     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-in-reg/15")
     2582     # . epilogue
     2583     89/<- %esp 5/r32/ebp
     2584     5d/pop-to-ebp
     2585     c3/return
     2586
     2587 test-convert-function-with-local-var-in-same-reg:
     2588     # . prologue
     2589     55/push-ebp
     2590     89/<- %ebp 4/r32/esp
     2591     # setup
     2592     (clear-stream _test-input-stream)
     2593     (clear-stream $_test-input-buffered-file->buffer)
     2594     (clear-stream _test-output-stream)
     2595     (clear-stream $_test-output-buffered-file->buffer)
     2596     #
     2597     (write _test-input-stream "fn foo {\n")
     2598     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
     2599     (write _test-input-stream "  var y/ecx: int <- copy x\n")
     2600     (write _test-input-stream "}\n")
     2601     # convert
     2602     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     2603     (flush _test-output-buffered-file)
     2604 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     2610     # check output
     2611     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-in-same-reg/0")
     2612     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-in-same-reg/1")
     2613     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-in-same-reg/2")
     2614     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-in-same-reg/3")
     2615     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-in-same-reg/4")
     2616     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-in-same-reg/5")
     2617     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-local-var-in-same-reg/6")
     2618     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-convert-function-with-local-var-in-same-reg/7")
     2619     # optimization: skip the second copy
     2620     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-function-with-local-var-in-same-reg/8")
     2621     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-in-same-reg/9")
     2622     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-in-same-reg/10")
     2623     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-in-same-reg/11")
     2624     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-in-same-reg/12")
     2625     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-in-same-reg/13")
     2626     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-in-same-reg/14")
     2627     # . epilogue
     2628     89/<- %esp 5/r32/ebp
     2629     5d/pop-to-ebp
     2630     c3/return
     2631
     2632 test-convert-function-with-local-var-in-same-reg-dereferenced:
     2633     # . prologue
     2634     55/push-ebp
     2635     89/<- %ebp 4/r32/esp
     2636     # setup
     2637     (clear-stream _test-input-stream)
     2638     (clear-stream $_test-input-buffered-file->buffer)
     2639     (clear-stream _test-output-stream)
     2640     (clear-stream $_test-output-buffered-file->buffer)
     2641     #
     2642     (write _test-input-stream "fn foo {\n")
     2643     (write _test-input-stream "  var x/ecx: (addr int) <- copy 0\n")
     2644     (write _test-input-stream "  var y/ecx: int <- copy *x\n")
     2645     (write _test-input-stream "}\n")
     2646     # convert
     2647     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     2648     (flush _test-output-buffered-file)
     2649 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     2655     # check output
     2656     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-in-same-reg-dereferenced/0")
     2657     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-in-same-reg-dereferenced/1")
     2658     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-in-same-reg-dereferenced/2")
     2659     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-in-same-reg-dereferenced/3")
     2660     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-in-same-reg-dereferenced/4")
     2661     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-in-same-reg-dereferenced/5")
     2662     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-local-var-in-same-reg-dereferenced/6")
     2663     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"  "F - test-convert-function-with-local-var-in-same-reg-dereferenced/7")
     2664     (check-next-stream-line-equal _test-output-stream "    8b/-> *ecx 0x00000001/r32"  "F - test-convert-function-with-local-var-in-same-reg-dereferenced/8")  # don't optimize this away
     2665     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-function-with-local-var-in-same-reg-dereferenced/9")
     2666     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-in-same-reg-dereferenced/10")
     2667     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-in-same-reg-dereferenced/11")
     2668     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-in-same-reg-dereferenced/12")
     2669     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-in-same-reg-dereferenced/13")
     2670     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-in-same-reg-dereferenced/14")
     2671     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-in-same-reg-dereferenced/15")
     2672     # . epilogue
     2673     89/<- %esp 5/r32/ebp
     2674     5d/pop-to-ebp
     2675     c3/return
     2676
     2677 test-float-var-in-wrong-register:
     2678     # . prologue
     2679     55/push-ebp
     2680     89/<- %ebp 4/r32/esp
     2681     # setup
     2682     (clear-stream _test-input-stream)
     2683     (clear-stream $_test-input-buffered-file->buffer)
     2684     (clear-stream _test-output-stream)
     2685     (clear-stream $_test-output-buffered-file->buffer)
     2686     (clear-stream _test-error-stream)
     2687     (clear-stream $_test-error-buffered-file->buffer)
     2688     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     2689     68/push 0/imm32
     2690     68/push 0/imm32
     2691     89/<- %edx 4/r32/esp
     2692     (tailor-exit-descriptor %edx 0x10)
     2693     #
     2694     (write _test-input-stream "fn foo {\n")
     2695     (write _test-input-stream "  var x/eax: int <- copy 0\n")
     2696     (write _test-input-stream "  var y/eax: float <- convert x\n")
     2697     (write _test-input-stream "}\n")
     2698     # convert
     2699     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     2700     # registers except esp clobbered at this point
     2701     # restore ed
     2702     89/<- %edx 4/r32/esp
     2703     (flush _test-output-buffered-file)
     2704     (flush _test-error-buffered-file)
     2705 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     2711     # check output
     2712     (check-stream-equal _test-output-stream  ""  "F - test-float-var-in-wrong-register: output should be empty")
     2713     (check-next-stream-line-equal _test-error-stream  "fn foo: float var 'y' should be in a floating-point register"  "F - test-float-var-in-wrong-register: error message")
     2714     # check that stop(1) was called
     2715     (check-ints-equal *(edx+4) 2 "F - test-float-var-in-wrong-register: exit status")
     2716     # don't restore from ebp
     2717     81 0/subop/add %esp 8/imm32
     2718     # . epilogue
     2719     5d/pop-to-ebp
     2720     c3/return
     2721
     2722 test-non-float-var-in-wrong-register:
     2723     # . prologue
     2724     55/push-ebp
     2725     89/<- %ebp 4/r32/esp
     2726     # setup
     2727     (clear-stream _test-input-stream)
     2728     (clear-stream $_test-input-buffered-file->buffer)
     2729     (clear-stream _test-output-stream)
     2730     (clear-stream $_test-output-buffered-file->buffer)
     2731     (clear-stream _test-error-stream)
     2732     (clear-stream $_test-error-buffered-file->buffer)
     2733     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     2734     68/push 0/imm32
     2735     68/push 0/imm32
     2736     89/<- %edx 4/r32/esp
     2737     (tailor-exit-descriptor %edx 0x10)
     2738     #
     2739     (write _test-input-stream "fn foo {\n")
     2740     (write _test-input-stream "  var x/xmm5: int <- copy 0\n")
     2741     (write _test-input-stream "}\n")
     2742     # convert
     2743     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     2744     # registers except esp clobbered at this point
     2745     # restore ed
     2746     89/<- %edx 4/r32/esp
     2747     (flush _test-output-buffered-file)
     2748     (flush _test-error-buffered-file)
     2749 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     2755     # check output
     2756     (check-stream-equal _test-output-stream  ""  "F - test-non-float-var-in-wrong-register: output should be empty")
     2757     (check-next-stream-line-equal _test-error-stream  "fn foo: non-float var 'x' should be in an integer register"  "F - test-non-float-var-in-wrong-register: error message")
     2758     # check that stop(1) was called
     2759     (check-ints-equal *(edx+4) 2 "F - test-non-float-var-in-wrong-register: exit status")
     2760     # don't restore from ebp
     2761     81 0/subop/add %esp 8/imm32
     2762     # . epilogue
     2763     5d/pop-to-ebp
     2764     c3/return
     2765
     2766 test-convert-function-with-allocate:
     2767     # . prologue
     2768     55/push-ebp
     2769     89/<- %ebp 4/r32/esp
     2770     # setup
     2771     (clear-stream _test-input-stream)
     2772     (clear-stream $_test-input-buffered-file->buffer)
     2773     (clear-stream _test-output-stream)
     2774     (clear-stream $_test-output-buffered-file->buffer)
     2775     #
     2776     (write _test-input-stream "fn foo {\n")
     2777     (write _test-input-stream "  var x/ecx: (addr handle int) <- copy 0\n")
     2778     (write _test-input-stream "  allocate x\n")
     2779     (write _test-input-stream "}\n")
     2780     # convert
     2781     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     2782     (flush _test-output-buffered-file)
     2783 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     2789     # check output
     2790     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-allocate/0")
     2791     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-allocate/1")
     2792     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-allocate/2")
     2793     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-allocate/3")
     2794     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-allocate/4")
     2795     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-allocate/5")
     2796     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-allocate/6")
     2797     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"  "F - test-convert-function-with-allocate/7")
     2798     (check-next-stream-line-equal _test-output-stream "    (allocate Heap 0x00000004 %ecx)"  "F - test-convert-function-with-allocate/8")  # 4 = size-of(int)
     2799     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-function-with-allocate/9")
     2800     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-allocate/10")
     2801     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-allocate/11")
     2802     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-allocate/12")
     2803     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-allocate/13")
     2804     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-allocate/14")
     2805     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-allocate/15")
     2806     # . epilogue
     2807     89/<- %esp 5/r32/ebp
     2808     5d/pop-to-ebp
     2809     c3/return
     2810
     2811 test-initializer-in-hex:
     2812     # . prologue
     2813     55/push-ebp
     2814     89/<- %ebp 4/r32/esp
     2815     # setup
     2816     (clear-stream _test-input-stream)
     2817     (clear-stream $_test-input-buffered-file->buffer)
     2818     (clear-stream _test-output-stream)
     2819     (clear-stream $_test-output-buffered-file->buffer)
     2820     (clear-stream _test-error-stream)
     2821     (clear-stream $_test-error-buffered-file->buffer)
     2822     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     2823     68/push 0/imm32
     2824     68/push 0/imm32
     2825     89/<- %edx 4/r32/esp
     2826     (tailor-exit-descriptor %edx 0x10)
     2827     #
     2828     (write _test-input-stream "fn foo {\n")
     2829     (write _test-input-stream "  var x/ecx: int <- copy 10\n")
     2830     (write _test-input-stream "}\n")
     2831     # convert
     2832     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     2833     # registers except esp clobbered at this point
     2834     # restore ed
     2835     89/<- %edx 4/r32/esp
     2836     (flush _test-output-buffered-file)
     2837     (flush _test-error-buffered-file)
     2838 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     2844     # check output
     2845     (check-stream-equal _test-output-stream  ""  "F - test-initializer-in-hex: output should be empty")
     2846     (check-next-stream-line-equal _test-error-stream  "literal integers are always hex in Mu; start '10' with a '0x' to be unambiguous, converting it to hexadecimal as necessary."  "F - test-initializer-in-hex: error message")
     2847     # check that stop(1) was called
     2848     (check-ints-equal *(edx+4) 2 "F - test-initializer-in-hex: exit status")
     2849     # don't restore from ebp
     2850     81 0/subop/add %esp 8/imm32
     2851     # . epilogue
     2852     5d/pop-to-ebp
     2853     c3/return
     2854
     2855 test-convert-function-with-second-local-var-in-same-reg:
     2856     # . prologue
     2857     55/push-ebp
     2858     89/<- %ebp 4/r32/esp
     2859     # setup
     2860     (clear-stream _test-input-stream)
     2861     (clear-stream $_test-input-buffered-file->buffer)
     2862     (clear-stream _test-output-stream)
     2863     (clear-stream $_test-output-buffered-file->buffer)
     2864     #
     2865     (write _test-input-stream "fn foo {\n")
     2866     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
     2867     (write _test-input-stream "  var y/ecx: int <- copy 4\n")
     2868     (write _test-input-stream "  y <- increment\n")
     2869     (write _test-input-stream "}\n")
     2870     # convert
     2871     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     2872     (flush _test-output-buffered-file)
     2873 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     2879     # check output
     2880     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-second-local-var-in-same-reg/0")
     2881     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-second-local-var-in-same-reg/1")
     2882     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-second-local-var-in-same-reg/2")
     2883     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-second-local-var-in-same-reg/3")
     2884     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-second-local-var-in-same-reg/4")
     2885     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-second-local-var-in-same-reg/5")
     2886     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-second-local-var-in-same-reg/6")
     2887     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-convert-function-with-second-local-var-in-same-reg/7")
     2888     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 4/imm32"  "F - test-convert-function-with-second-local-var-in-same-reg/8")
     2889     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-convert-function-with-second-local-var-in-same-reg/9")
     2890     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-function-with-second-local-var-in-same-reg/10")
     2891     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-second-local-var-in-same-reg/11")
     2892     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-second-local-var-in-same-reg/12")
     2893     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-second-local-var-in-same-reg/13")
     2894     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-second-local-var-in-same-reg/14")
     2895     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-second-local-var-in-same-reg/15")
     2896     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-second-local-var-in-same-reg/16")
     2897     # . epilogue
     2898     89/<- %esp 5/r32/ebp
     2899     5d/pop-to-ebp
     2900     c3/return
     2901
     2902 test-read-clobbered-reg-var:
     2903     # . prologue
     2904     55/push-ebp
     2905     89/<- %ebp 4/r32/esp
     2906     # setup
     2907     (clear-stream _test-input-stream)
     2908     (clear-stream $_test-input-buffered-file->buffer)
     2909     (clear-stream _test-output-stream)
     2910     (clear-stream $_test-output-buffered-file->buffer)
     2911     (clear-stream _test-error-stream)
     2912     (clear-stream $_test-error-buffered-file->buffer)
     2913     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)  # bytes of args in call to convert-mu
     2914     68/push 0/imm32
     2915     68/push 0/imm32
     2916     89/<- %edx 4/r32/esp
     2917     (tailor-exit-descriptor %edx 0x10)
     2918     #
     2919     (write _test-input-stream "fn foo {\n")
     2920     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
     2921     (write _test-input-stream "  var y/ecx: int <- copy 4\n")
     2922     (write _test-input-stream "  x <- increment\n")
     2923     (write _test-input-stream "}\n")
     2924     # convert
     2925     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     2926     # registers except esp clobbered at this point
     2927     # restore ed
     2928     89/<- %edx 4/r32/esp
     2929     (flush _test-output-buffered-file)
     2930     (flush _test-error-buffered-file)
     2931 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     2937     # check output
     2938     (check-stream-equal _test-output-stream  ""  "F - test-read-clobbered-reg-var: output should be empty")
     2939     (check-next-stream-line-equal _test-error-stream  "fn foo: register ecx reads var 'x' after writing var 'y'"  "F - test-read-clobbered-reg-var: error message")
     2940     # check that stop(1) was called
     2941     (check-ints-equal *(edx+4) 2 "F - test-read-clobbered-reg-var: exit status")
     2942     # don't restore from ebp
     2943     81 0/subop/add %esp 8/imm32
     2944     # . epilogue
     2945     5d/pop-to-ebp
     2946     c3/return
     2947
     2948 test-overlapping-int-fp-registers:
     2949     # . prologue
     2950     55/push-ebp
     2951     89/<- %ebp 4/r32/esp
     2952     # setup
     2953     (clear-stream _test-input-stream)
     2954     (clear-stream $_test-input-buffered-file->buffer)
     2955     (clear-stream _test-output-stream)
     2956     (clear-stream $_test-output-buffered-file->buffer)
     2957     (clear-stream _test-error-stream)
     2958     (clear-stream $_test-error-buffered-file->buffer)
     2959     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)  # bytes of args in call to convert-mu
     2960     68/push 0/imm32
     2961     68/push 0/imm32
     2962     89/<- %edx 4/r32/esp
     2963     (tailor-exit-descriptor %edx 0x10)
     2964     #
     2965     (write _test-input-stream "fn foo {\n")
     2966     (write _test-input-stream "  var x/eax: int <- copy 3\n")
     2967     (write _test-input-stream "  var y/xmm0: float <- convert x\n")
     2968     (write _test-input-stream "  x <- increment\n")
     2969     (write _test-input-stream "}\n")
     2970     # convert
     2971     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     2972     # registers except esp clobbered at this point
     2973     # restore ed
     2974     89/<- %edx 4/r32/esp
     2975     (flush _test-output-buffered-file)
     2976     (flush _test-error-buffered-file)
     2977 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     2983     # no errors
     2984     (check-next-stream-line-equal _test-error-stream  ""  "F - test-overlapping-int-fp-registers: error message")
     2985     # don't bother checking the generated code
     2986     # don't restore from ebp
     2987     81 0/subop/add %esp 8/imm32
     2988     # . epilogue
     2989     5d/pop-to-ebp
     2990     c3/return
     2991
     2992 test-convert-function-call:
     2993     # . prologue
     2994     55/push-ebp
     2995     89/<- %ebp 4/r32/esp
     2996     # setup
     2997     (clear-stream _test-input-stream)
     2998     (clear-stream $_test-input-buffered-file->buffer)
     2999     (clear-stream _test-output-stream)
     3000     (clear-stream $_test-output-buffered-file->buffer)
     3001     #
     3002     (write _test-input-stream "fn main -> _/ebx: int {\n")
     3003     (write _test-input-stream "  var result/ebx: int <- foo\n")
     3004     (write _test-input-stream "  return result\n")
     3005     (write _test-input-stream "}\n")
     3006     (write _test-input-stream "fn foo -> _/ebx: int {\n")
     3007     (write _test-input-stream "  var result/ebx: int <- copy 3\n")
     3008     (write _test-input-stream "  return result\n")
     3009     (write _test-input-stream "}\n")
     3010     # convert
     3011     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     3012     (flush _test-output-buffered-file)
     3013 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     3019     # check output
     3020     (check-next-stream-line-equal _test-output-stream "main:"                   "F - test-convert-function-call/0")
     3021     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call/1")
     3022     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call/2")
     3023     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call/3")
     3024     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call/4")
     3025     (check-next-stream-line-equal _test-output-stream "$main:0x00000001:loop:"  "F - test-convert-function-call/5")
     3026     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ebx"  "F - test-convert-function-call-with-literal-arg/6")
     3027     (check-next-stream-line-equal _test-output-stream "    (foo)"               "F - test-convert-function-call/6")
     3028     (check-next-stream-line-equal _test-output-stream "    8b/-> %ebx 0x00000003/r32" "F - test-convert-function-call-with-literal-arg/8")
     3029     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-function-call-with-literal-arg/27")
     3030     (check-next-stream-line-equal _test-output-stream "    e9/jump $main:0x00000001:break/disp32"  "F - test-convert-function-call-with-literal-arg/10")
     3031     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call/7")
     3032     (check-next-stream-line-equal _test-output-stream "$main:0x00000001:break:" "F - test-convert-function-call/8")
     3033     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call/9")
     3034     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call/10")
     3035     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call/11")
     3036     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call/12")
     3037     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-call/13")
     3038     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call/14")
     3039     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call/15")
     3040     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call/16")
     3041     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call/17")
     3042     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"  "F - test-convert-function-call/18")
     3043     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ebx"  "F - test-convert-function-call-with-literal-arg/6")
     3044     (check-next-stream-line-equal _test-output-stream "    bb/copy-to-ebx 3/imm32"  "F - test-convert-function-call/19")
     3045     (check-next-stream-line-equal _test-output-stream "    8b/-> %ebx 0x00000003/r32" "F - test-convert-function-call-with-literal-arg/8")
     3046     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-function-call-with-literal-arg/27")
     3047     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000002:break/disp32"  "F - test-convert-function-call-with-literal-arg/10")
     3048     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call/20")
     3049     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-call/21")
     3050     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call/22")
     3051     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call/23")
     3052     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call/24")
     3053     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call/25")
     3054     # . epilogue
     3055     89/<- %esp 5/r32/ebp
     3056     5d/pop-to-ebp
     3057     c3/return
     3058
     3059 test-convert-function-call-with-inout-with-compound-type:
     3060     # . prologue
     3061     55/push-ebp
     3062     89/<- %ebp 4/r32/esp
     3063     # setup
     3064     (clear-stream _test-input-stream)
     3065     (clear-stream $_test-input-buffered-file->buffer)
     3066     (clear-stream _test-output-stream)
     3067     (clear-stream $_test-output-buffered-file->buffer)
     3068     #
     3069     (write _test-input-stream "fn f {\n")
     3070     (write _test-input-stream "  var x: (addr int)\n")
     3071     (write _test-input-stream "  g x\n")
     3072     (write _test-input-stream "}\n")
     3073     (write _test-input-stream "fn g a: (addr int) {\n")
     3074     (write _test-input-stream "}\n")
     3075     # convert
     3076     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     3077     (flush _test-output-buffered-file)
     3078 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     3084     # check output
     3085     (check-next-stream-line-equal _test-output-stream "f:"                      "F - test-convert-function-call-with-inout-with-compound-type/0")
     3086     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-inout-with-compound-type/1")
     3087     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-inout-with-compound-type/2")
     3088     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call-with-inout-with-compound-type/3")
     3089     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-inout-with-compound-type/4")
     3090     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:loop:"     "F - test-convert-function-call-with-inout-with-compound-type/5")
     3091     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-call-with-inout-with-compound-type/6")
     3092     (check-next-stream-line-equal _test-output-stream "    (g *(ebp+0xfffffffc))"  "F - test-convert-function-call-with-inout-with-compound-type/7")
     3093     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-call-with-inout-with-compound-type/8")
     3094     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-inout-with-compound-type/9")
     3095     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:break:"    "F - test-convert-function-call-with-inout-with-compound-type/10")
     3096     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-inout-with-compound-type/11")
     3097     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call-with-inout-with-compound-type/12")
     3098     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-inout-with-compound-type/13")
     3099     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-inout-with-compound-type/14")
     3100     (check-next-stream-line-equal _test-output-stream "g:"                      "F - test-convert-function-call-with-inout-with-compound-type/15")
     3101     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-inout-with-compound-type/16")
     3102     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-inout-with-compound-type/17")
     3103     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call-with-inout-with-compound-type/18")
     3104     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-inout-with-compound-type/19")
     3105     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call-with-inout-with-compound-type/20")
     3106     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-inout-with-compound-type/21")
     3107     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-inout-with-compound-type/22")
     3108     # . epilogue
     3109     89/<- %esp 5/r32/ebp
     3110     5d/pop-to-ebp
     3111     c3/return
     3112
     3113 test-convert-function-call-with-inout-with-type-parameter:
     3114     # . prologue
     3115     55/push-ebp
     3116     89/<- %ebp 4/r32/esp
     3117     # setup
     3118     (clear-stream _test-input-stream)
     3119     (clear-stream $_test-input-buffered-file->buffer)
     3120     (clear-stream _test-output-stream)
     3121     (clear-stream $_test-output-buffered-file->buffer)
     3122     (clear-stream _test-error-stream)
     3123     (clear-stream $_test-error-buffered-file->buffer)
     3124     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     3125     68/push 0/imm32
     3126     68/push 0/imm32
     3127     89/<- %edx 4/r32/esp
     3128     (tailor-exit-descriptor %edx 0x10)
     3129     #
     3130     (write _test-input-stream "fn f {\n")
     3131     (write _test-input-stream "  var x: (addr int)\n")
     3132     (write _test-input-stream "  g x\n")
     3133     (write _test-input-stream "}\n")
     3134     (write _test-input-stream "fn g a: (addr _) {\n")
     3135     (write _test-input-stream "}\n")
     3136     # convert
     3137     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     3138     # registers except esp clobbered at this point
     3139     # restore ed
     3140     89/<- %edx 4/r32/esp
     3141     (flush _test-output-buffered-file)
     3142     (flush _test-error-buffered-file)
     3143 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     3149     # no error; types matched
     3150     (check-stream-equal _test-error-stream  ""  "F - test-convert-function-call-with-inout-with-type-parameter: error stream should be empty")
     3151     # don't bother checking the generated code; that's in the test 'test-local-clobbered-by-fn-output' below
     3152     # don't restore from ebp
     3153     81 0/subop/add %esp 8/imm32
     3154     # . epilogue
     3155     5d/pop-to-ebp
     3156     c3/return
     3157
     3158 test-convert-function-call-with-incorrect-inout-type:
     3159     # . prologue
     3160     55/push-ebp
     3161     89/<- %ebp 4/r32/esp
     3162     # setup
     3163     (clear-stream _test-input-stream)
     3164     (clear-stream $_test-input-buffered-file->buffer)
     3165     (clear-stream _test-output-stream)
     3166     (clear-stream $_test-output-buffered-file->buffer)
     3167     (clear-stream _test-error-stream)
     3168     (clear-stream $_test-error-buffered-file->buffer)
     3169     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     3170     68/push 0/imm32
     3171     68/push 0/imm32
     3172     89/<- %edx 4/r32/esp
     3173     (tailor-exit-descriptor %edx 0x10)
     3174     #
     3175     (write _test-input-stream "fn f {\n")
     3176     (write _test-input-stream "  var x: int\n")
     3177     (write _test-input-stream "  g x\n")
     3178     (write _test-input-stream "}\n")
     3179     (write _test-input-stream "fn g a: foo {\n")
     3180     (write _test-input-stream "}\n")
     3181     # convert
     3182     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     3183     # registers except esp clobbered at this point
     3184     # restore ed
     3185     89/<- %edx 4/r32/esp
     3186     (flush _test-output-buffered-file)
     3187     (flush _test-error-buffered-file)
     3188 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     3194     # check output
     3195     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-incorrect-inout-type: output should be empty")
     3196     (check-next-stream-line-equal _test-error-stream  "fn f: call g: type for inout 'x' is not right"  "F - test-convert-function-call-with-incorrect-inout-type: error message")
     3197     # check that stop(1) was called
     3198     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-incorrect-inout-type: exit status")
     3199     # don't restore from ebp
     3200     81 0/subop/add %esp 8/imm32
     3201     5d/pop-to-ebp
     3202     c3/return
     3203
     3204 test-convert-function-call-with-inout-with-incorrect-compound-type:
     3205     # . prologue
     3206     55/push-ebp
     3207     89/<- %ebp 4/r32/esp
     3208     # setup
     3209     (clear-stream _test-input-stream)
     3210     (clear-stream $_test-input-buffered-file->buffer)
     3211     (clear-stream _test-output-stream)
     3212     (clear-stream $_test-output-buffered-file->buffer)
     3213     (clear-stream _test-error-stream)
     3214     (clear-stream $_test-error-buffered-file->buffer)
     3215     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     3216     68/push 0/imm32
     3217     68/push 0/imm32
     3218     89/<- %edx 4/r32/esp
     3219     (tailor-exit-descriptor %edx 0x10)
     3220     #
     3221     (write _test-input-stream "fn f {\n")
     3222     (write _test-input-stream "  var x: (addr int)\n")
     3223     (write _test-input-stream "  g x\n")
     3224     (write _test-input-stream "}\n")
     3225     (write _test-input-stream "fn g a: (addr bool) {\n")
     3226     (write _test-input-stream "}\n")
     3227     # convert
     3228     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     3229     # registers except esp clobbered at this point
     3230     # restore ed
     3231     89/<- %edx 4/r32/esp
     3232     (flush _test-output-buffered-file)
     3233     (flush _test-error-buffered-file)
     3234 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     3240     # check output
     3241     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-inout-with-incorrect-compound-type: output should be empty")
     3242     (check-next-stream-line-equal _test-error-stream  "fn f: call g: type for inout 'x' is not right"  "F - test-convert-function-call-with-inout-with-incorrect-compound-type: error message")
     3243     # don't restore from ebp
     3244     81 0/subop/add %esp 8/imm32
     3245     # . epilogue
     3246     5d/pop-to-ebp
     3247     c3/return
     3248
     3249 test-convert-function-call-with-inout-with-multiple-type-parameters:
     3250     # . prologue
     3251     55/push-ebp
     3252     89/<- %ebp 4/r32/esp
     3253     # setup
     3254     (clear-stream _test-input-stream)
     3255     (clear-stream $_test-input-buffered-file->buffer)
     3256     (clear-stream _test-output-stream)
     3257     (clear-stream $_test-output-buffered-file->buffer)
     3258     (clear-stream _test-error-stream)
     3259     (clear-stream $_test-error-buffered-file->buffer)
     3260     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     3261     68/push 0/imm32
     3262     68/push 0/imm32
     3263     89/<- %edx 4/r32/esp
     3264     (tailor-exit-descriptor %edx 0x10)
     3265     #
     3266     (write _test-input-stream "fn f {\n")
     3267     (write _test-input-stream "  var x: (addr int)\n")
     3268     (write _test-input-stream "  var y: (addr int)\n")
     3269     (write _test-input-stream "  g x, y\n")
     3270     (write _test-input-stream "}\n")
     3271     (write _test-input-stream "fn g a: (addr _), b: (addr _) {\n")
     3272     (write _test-input-stream "}\n")
     3273     # convert
     3274     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     3275     # registers except esp clobbered at this point
     3276     # restore ed
     3277     89/<- %edx 4/r32/esp
     3278     (flush _test-output-buffered-file)
     3279     (flush _test-error-buffered-file)
     3280 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     3286     # no errors
     3287     (check-stream-equal _test-error-stream  ""  "F - test-convert-function-call-with-inout-with-multiple-type-parameters: error stream should be empty")
     3288     # don't bother checking the generated code
     3289     # don't restore from ebp
     3290     81 0/subop/add %esp 8/imm32
     3291     # . epilogue
     3292     5d/pop-to-ebp
     3293     c3/return
     3294
     3295 test-type-parameter-matches-rest-of-type:
     3296     # . prologue
     3297     55/push-ebp
     3298     89/<- %ebp 4/r32/esp
     3299     # setup
     3300     (clear-stream _test-input-stream)
     3301     (clear-stream $_test-input-buffered-file->buffer)
     3302     (clear-stream _test-output-stream)
     3303     (clear-stream $_test-output-buffered-file->buffer)
     3304     (clear-stream _test-error-stream)
     3305     (clear-stream $_test-error-buffered-file->buffer)
     3306     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     3307     68/push 0/imm32
     3308     68/push 0/imm32
     3309     89/<- %edx 4/r32/esp
     3310     (tailor-exit-descriptor %edx 0x10)
     3311     #
     3312     (write _test-input-stream "fn f {\n")
     3313     (write _test-input-stream "  var x: (addr array int)\n")
     3314     (write _test-input-stream "  g x\n")
     3315     (write _test-input-stream "}\n")
     3316     (write _test-input-stream "fn g a: (addr _) {\n")
     3317     (write _test-input-stream "}\n")
     3318     # convert
     3319     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     3320     # registers except esp clobbered at this point
     3321     # restore ed
     3322     89/<- %edx 4/r32/esp
     3323     (flush _test-output-buffered-file)
     3324     (flush _test-error-buffered-file)
     3325 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     3331     # no errors
     3332     (check-stream-equal _test-error-stream  ""  "F - test-type-parameter-matches-rest-of-type: error stream should be empty")
     3333     # don't bother checking the generated code
     3334     # don't restore from ebp
     3335     81 0/subop/add %esp 8/imm32
     3336     # . epilogue
     3337     5d/pop-to-ebp
     3338     c3/return
     3339
     3340 test-convert-function-call-with-inout-with-incompatible-type-parameters:
     3341     # . prologue
     3342     55/push-ebp
     3343     89/<- %ebp 4/r32/esp
     3344     # setup
     3345     (clear-stream _test-input-stream)
     3346     (clear-stream $_test-input-buffered-file->buffer)
     3347     (clear-stream _test-output-stream)
     3348     (clear-stream $_test-output-buffered-file->buffer)
     3349     (clear-stream _test-error-stream)
     3350     (clear-stream $_test-error-buffered-file->buffer)
     3351     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     3352     68/push 0/imm32
     3353     68/push 0/imm32
     3354     89/<- %edx 4/r32/esp
     3355     (tailor-exit-descriptor %edx 0x10)
     3356     #
     3357     (write _test-input-stream "fn f {\n")
     3358     (write _test-input-stream "  var x: (addr int)\n")
     3359     (write _test-input-stream "  var y: (addr boolean)\n")
     3360     (write _test-input-stream "  g x, y\n")
     3361     (write _test-input-stream "}\n")
     3362     (write _test-input-stream "fn g a: (addr _T), b: (addr _T) {\n")
     3363     (write _test-input-stream "}\n")
     3364     # convert
     3365     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     3366     # registers except esp clobbered at this point
     3367     # restore ed
     3368     89/<- %edx 4/r32/esp
     3369     (flush _test-output-buffered-file)
     3370     (flush _test-error-buffered-file)
     3371 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     3377     # check output
     3378     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-inout-with-incompatible-type-parameters: output should be empty")
     3379     (check-next-stream-line-equal _test-error-stream  "fn f: call g: type for inout 'y' is not right"  "F - test-convert-function-call-with-inout-with-incompatible-type-parameters: error message")
     3380     # don't restore from ebp
     3381     81 0/subop/add %esp 8/imm32
     3382     # . epilogue
     3383     5d/pop-to-ebp
     3384     c3/return
     3385
     3386 test-convert-function-call-with-too-few-inouts:
     3387     # . prologue
     3388     55/push-ebp
     3389     89/<- %ebp 4/r32/esp
     3390     # setup
     3391     (clear-stream _test-input-stream)
     3392     (clear-stream $_test-input-buffered-file->buffer)
     3393     (clear-stream _test-output-stream)
     3394     (clear-stream $_test-output-buffered-file->buffer)
     3395     (clear-stream _test-error-stream)
     3396     (clear-stream $_test-error-buffered-file->buffer)
     3397     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     3398     68/push 0/imm32
     3399     68/push 0/imm32
     3400     89/<- %edx 4/r32/esp
     3401     (tailor-exit-descriptor %edx 0x10)
     3402     #
     3403     (write _test-input-stream "fn f {\n")
     3404     (write _test-input-stream "  g\n")
     3405     (write _test-input-stream "}\n")
     3406     (write _test-input-stream "fn g a: int {\n")
     3407     (write _test-input-stream "}\n")
     3408     # convert
     3409     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     3410     # registers except esp clobbered at this point
     3411     # restore ed
     3412     89/<- %edx 4/r32/esp
     3413     (flush _test-output-buffered-file)
     3414     (flush _test-error-buffered-file)
     3415 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     3421     # check output
     3422     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-too-few-inouts: output should be empty")
     3423     (check-next-stream-line-equal _test-error-stream  "fn f: call g: too few inouts"  "F - test-convert-function-call-with-too-few-inouts: error message")
     3424     # check that stop(1) was called
     3425     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-too-few-inouts: exit status")
     3426     # don't restore from ebp
     3427     81 0/subop/add %esp 8/imm32
     3428     5d/pop-to-ebp
     3429     c3/return
     3430
     3431 test-convert-function-call-with-too-many-inouts:
     3432     # . prologue
     3433     55/push-ebp
     3434     89/<- %ebp 4/r32/esp
     3435     # setup
     3436     (clear-stream _test-input-stream)
     3437     (clear-stream $_test-input-buffered-file->buffer)
     3438     (clear-stream _test-output-stream)
     3439     (clear-stream $_test-output-buffered-file->buffer)
     3440     (clear-stream _test-error-stream)
     3441     (clear-stream $_test-error-buffered-file->buffer)
     3442     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     3443     68/push 0/imm32
     3444     68/push 0/imm32
     3445     89/<- %edx 4/r32/esp
     3446     (tailor-exit-descriptor %edx 0x10)
     3447     #
     3448     (write _test-input-stream "fn f {\n")
     3449     (write _test-input-stream "  var x: int\n")
     3450     (write _test-input-stream "  g x\n")
     3451     (write _test-input-stream "}\n")
     3452     (write _test-input-stream "fn g {\n")
     3453     (write _test-input-stream "}\n")
     3454     # convert
     3455     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     3456     # registers except esp clobbered at this point
     3457     # restore ed
     3458     89/<- %edx 4/r32/esp
     3459     (flush _test-output-buffered-file)
     3460     (flush _test-error-buffered-file)
     3461 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     3467     # check output
     3468     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-too-many-inouts: output should be empty")
     3469     (check-next-stream-line-equal _test-error-stream  "fn f: call g: too many inouts"  "F - test-convert-function-call-with-too-many-inouts: error message")
     3470     # check that stop(1) was called
     3471     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-too-many-inouts: exit status")
     3472     # don't restore from ebp
     3473     81 0/subop/add %esp 8/imm32
     3474     5d/pop-to-ebp
     3475     c3/return
     3476
     3477 test-convert-function-call-with-incorrect-output-type:
     3478     # . prologue
     3479     55/push-ebp
     3480     89/<- %ebp 4/r32/esp
     3481     # setup
     3482     (clear-stream _test-input-stream)
     3483     (clear-stream $_test-input-buffered-file->buffer)
     3484     (clear-stream _test-output-stream)
     3485     (clear-stream $_test-output-buffered-file->buffer)
     3486     (clear-stream _test-error-stream)
     3487     (clear-stream $_test-error-buffered-file->buffer)
     3488     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     3489     68/push 0/imm32
     3490     68/push 0/imm32
     3491     89/<- %edx 4/r32/esp
     3492     (tailor-exit-descriptor %edx 0x10)
     3493     #
     3494     (write _test-input-stream "fn f {\n")
     3495     (write _test-input-stream "  var x/eax: int <- g\n")
     3496     (write _test-input-stream "}\n")
     3497     (write _test-input-stream "fn g -> _/eax: foo {\n")
     3498     (write _test-input-stream "}\n")
     3499     # convert
     3500     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     3501     # registers except esp clobbered at this point
     3502     # restore ed
     3503     89/<- %edx 4/r32/esp
     3504     (flush _test-output-buffered-file)
     3505     (flush _test-error-buffered-file)
     3506 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     3512     # check output
     3513     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-incorrect-output-type: output should be empty")
     3514     (check-next-stream-line-equal _test-error-stream  "fn f: call g: type for output 'x' is not right"  "F - test-convert-function-call-with-incorrect-output-type: error message")
     3515     # check that stop(1) was called
     3516     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-incorrect-output-type: exit status")
     3517     # don't restore from ebp
     3518     81 0/subop/add %esp 8/imm32
     3519     5d/pop-to-ebp
     3520     c3/return
     3521
     3522 test-convert-function-call-with-too-few-outputs:
     3523     # . prologue
     3524     55/push-ebp
     3525     89/<- %ebp 4/r32/esp
     3526     # setup
     3527     (clear-stream _test-input-stream)
     3528     (clear-stream $_test-input-buffered-file->buffer)
     3529     (clear-stream _test-output-stream)
     3530     (clear-stream $_test-output-buffered-file->buffer)
     3531     (clear-stream _test-error-stream)
     3532     (clear-stream $_test-error-buffered-file->buffer)
     3533     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     3534     68/push 0/imm32
     3535     68/push 0/imm32
     3536     89/<- %edx 4/r32/esp
     3537     (tailor-exit-descriptor %edx 0x10)
     3538     #
     3539     (write _test-input-stream "fn f {\n")
     3540     (write _test-input-stream "  g\n")
     3541     (write _test-input-stream "}\n")
     3542     (write _test-input-stream "fn g -> _/eax: int {\n")
     3543     (write _test-input-stream "}\n")
     3544     # convert
     3545     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     3546     # registers except esp clobbered at this point
     3547     # restore ed
     3548     89/<- %edx 4/r32/esp
     3549     (flush _test-output-buffered-file)
     3550     (flush _test-error-buffered-file)
     3551 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     3557     # check output
     3558     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-too-few-outputs: output should be empty")
     3559     (check-next-stream-line-equal _test-error-stream  "fn f: call g: too few outputs"  "F - test-convert-function-call-with-too-few-outputs: error message")
     3560     # check that stop(1) was called
     3561     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-too-few-outputs: exit status")
     3562     # don't restore from ebp
     3563     81 0/subop/add %esp 8/imm32
     3564     5d/pop-to-ebp
     3565     c3/return
     3566
     3567 test-convert-function-call-with-too-many-outputs:
     3568     # . prologue
     3569     55/push-ebp
     3570     89/<- %ebp 4/r32/esp
     3571     # setup
     3572     (clear-stream _test-input-stream)
     3573     (clear-stream $_test-input-buffered-file->buffer)
     3574     (clear-stream _test-output-stream)
     3575     (clear-stream $_test-output-buffered-file->buffer)
     3576     (clear-stream _test-error-stream)
     3577     (clear-stream $_test-error-buffered-file->buffer)
     3578     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     3579     68/push 0/imm32
     3580     68/push 0/imm32
     3581     89/<- %edx 4/r32/esp
     3582     (tailor-exit-descriptor %edx 0x10)
     3583     #
     3584     (write _test-input-stream "fn f {\n")
     3585     (write _test-input-stream "  var x/eax: int <- g\n")
     3586     (write _test-input-stream "}\n")
     3587     (write _test-input-stream "fn g {\n")
     3588     (write _test-input-stream "}\n")
     3589     # convert
     3590     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     3591     # registers except esp clobbered at this point
     3592     # restore ed
     3593     89/<- %edx 4/r32/esp
     3594     (flush _test-output-buffered-file)
     3595     (flush _test-error-buffered-file)
     3596 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     3602     # check output
     3603     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-too-many-outputs: output should be empty")
     3604     (check-next-stream-line-equal _test-error-stream  "fn f: call g: too many outputs"  "F - test-convert-function-call-with-too-many-outputs: error message")
     3605     # check that stop(1) was called
     3606     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-too-many-outputs: exit status")
     3607     # don't restore from ebp
     3608     81 0/subop/add %esp 8/imm32
     3609     5d/pop-to-ebp
     3610     c3/return
     3611
     3612 test-convert-function-call-with-missing-output-register:
     3613     # . prologue
     3614     55/push-ebp
     3615     89/<- %ebp 4/r32/esp
     3616     # setup
     3617     (clear-stream _test-input-stream)
     3618     (clear-stream $_test-input-buffered-file->buffer)
     3619     (clear-stream _test-output-stream)
     3620     (clear-stream $_test-output-buffered-file->buffer)
     3621     (clear-stream _test-error-stream)
     3622     (clear-stream $_test-error-buffered-file->buffer)
     3623     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     3624     68/push 0/imm32
     3625     68/push 0/imm32
     3626     89/<- %edx 4/r32/esp
     3627     (tailor-exit-descriptor %edx 0x10)
     3628     #
     3629     (write _test-input-stream "fn f {\n")
     3630     (write _test-input-stream "  var x: int\n")
     3631     (write _test-input-stream "  x <- g\n")
     3632     (write _test-input-stream "}\n")
     3633     (write _test-input-stream "fn g -> _/eax: int {\n")
     3634     (write _test-input-stream "}\n")
     3635     # convert
     3636     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     3637     # registers except esp clobbered at this point
     3638     # restore ed
     3639     89/<- %edx 4/r32/esp
     3640     (flush _test-output-buffered-file)
     3641     (flush _test-error-buffered-file)
     3642 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     3648     # check output
     3649     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-missing-output-register: output should be empty")
     3650     (check-next-stream-line-equal _test-error-stream  "fn f: call g: output 'x' is not in a register"  "F - test-convert-function-call-with-missing-output-register: error message")
     3651     # check that stop(1) was called
     3652     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-missing-output-register: exit status")
     3653     # don't restore from ebp
     3654     81 0/subop/add %esp 8/imm32
     3655     5d/pop-to-ebp
     3656     c3/return
     3657
     3658 test-convert-function-call-with-incorrect-output-register:
     3659     # . prologue
     3660     55/push-ebp
     3661     89/<- %ebp 4/r32/esp
     3662     # setup
     3663     (clear-stream _test-input-stream)
     3664     (clear-stream $_test-input-buffered-file->buffer)
     3665     (clear-stream _test-output-stream)
     3666     (clear-stream $_test-output-buffered-file->buffer)
     3667     (clear-stream _test-error-stream)
     3668     (clear-stream $_test-error-buffered-file->buffer)
     3669     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     3670     68/push 0/imm32
     3671     68/push 0/imm32
     3672     89/<- %edx 4/r32/esp
     3673     (tailor-exit-descriptor %edx 0x10)
     3674     #
     3675     (write _test-input-stream "fn f {\n")
     3676     (write _test-input-stream "  var x/ecx: int <- g\n")
     3677     (write _test-input-stream "}\n")
     3678     (write _test-input-stream "fn g -> _/eax: int {\n")
     3679     (write _test-input-stream "}\n")
     3680     # convert
     3681     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     3682     # registers except esp clobbered at this point
     3683     # restore ed
     3684     89/<- %edx 4/r32/esp
     3685     (flush _test-output-buffered-file)
     3686     (flush _test-error-buffered-file)
     3687 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     3693     # check output
     3694     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-incorrect-output-register: output should be empty")
     3695     (check-next-stream-line-equal _test-error-stream  "fn f: call g: register for output 'x' is not right"  "F - test-convert-function-call-with-incorrect-output-register: error message")
     3696     # check that stop(1) was called
     3697     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-incorrect-output-register: exit status")
     3698     # don't restore from ebp
     3699     81 0/subop/add %esp 8/imm32
     3700     5d/pop-to-ebp
     3701     c3/return
     3702
     3703 test-convert-function-with-local-var-dereferenced:
     3704     # . prologue
     3705     55/push-ebp
     3706     89/<- %ebp 4/r32/esp
     3707     # setup
     3708     (clear-stream _test-input-stream)
     3709     (clear-stream $_test-input-buffered-file->buffer)
     3710     (clear-stream _test-output-stream)
     3711     (clear-stream $_test-output-buffered-file->buffer)
     3712     #
     3713     (write _test-input-stream "fn foo {\n")
     3714     (write _test-input-stream "  var x/ecx: (addr int) <- copy 0\n")
     3715     (write _test-input-stream "  increment *x\n")
     3716     (write _test-input-stream "}\n")
     3717     # convert
     3718     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     3719     (flush _test-output-buffered-file)
     3720 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     3726     # check output
     3727     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-dereferenced/0")
     3728     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-dereferenced/1")
     3729     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-dereferenced/2")
     3730     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-dereferenced/3")
     3731     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-dereferenced/4")
     3732     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-dereferenced/5")
     3733     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-local-var-dereferenced/6")
     3734     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"  "F - test-convert-function-with-local-var-dereferenced/7")
     3735     (check-next-stream-line-equal _test-output-stream "    ff 0/subop/increment *ecx"  "F - test-convert-function-with-local-var-dereferenced/8")
     3736     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-function-with-local-var-dereferenced/9")
     3737     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-dereferenced/10")
     3738     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-dereferenced/11")
     3739     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-dereferenced/12")
     3740     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-dereferenced/13")
     3741     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-dereferenced/14")
     3742     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-dereferenced/15")
     3743     # . epilogue
     3744     89/<- %esp 5/r32/ebp
     3745     5d/pop-to-ebp
     3746     c3/return
     3747
     3748 test-dereference-of-var-on-stack:
     3749     # . prologue
     3750     55/push-ebp
     3751     89/<- %ebp 4/r32/esp
     3752     # setup
     3753     (clear-stream _test-input-stream)
     3754     (clear-stream $_test-input-buffered-file->buffer)
     3755     (clear-stream _test-output-stream)
     3756     (clear-stream $_test-output-buffered-file->buffer)
     3757     (clear-stream _test-error-stream)
     3758     (clear-stream $_test-error-buffered-file->buffer)
     3759     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     3760     68/push 0/imm32
     3761     68/push 0/imm32
     3762     89/<- %edx 4/r32/esp
     3763     (tailor-exit-descriptor %edx 0x10)
     3764     #
     3765     (write _test-input-stream "fn foo {\n")
     3766     (write _test-input-stream "  var x: (addr int)\n")
     3767     (write _test-input-stream "  increment *x\n")
     3768     (write _test-input-stream "}\n")
     3769     # convert
     3770     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     3771     # registers except esp clobbered at this point
     3772     # restore ed
     3773     89/<- %edx 4/r32/esp
     3774     (flush _test-output-buffered-file)
     3775     (flush _test-error-buffered-file)
     3776 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     3782     # check output
     3783     (check-stream-equal _test-output-stream  ""  "F - test-dereference-of-var-on-stack: output should be empty")
     3784     (check-next-stream-line-equal _test-error-stream  "fn foo: cannot dereference var 'x' on stack"  "F - test-dereference-of-var-on-stack: error message")
     3785     # check that stop(1) was called
     3786     (check-ints-equal *(edx+4) 2 "F - test-dereference-of-var-on-stack: exit status")
     3787     # don't restore from ebp
     3788     81 0/subop/add %esp 8/imm32
     3789     # . epilogue
     3790     5d/pop-to-ebp
     3791     c3/return
     3792
     3793 test-convert-function-with-byte-operations:
     3794     # . prologue
     3795     55/push-ebp
     3796     89/<- %ebp 4/r32/esp
     3797     # setup
     3798     (clear-stream _test-input-stream)
     3799     (clear-stream $_test-input-buffered-file->buffer)
     3800     (clear-stream _test-output-stream)
     3801     (clear-stream $_test-output-buffered-file->buffer)
     3802     #
     3803     (write _test-input-stream "fn foo {\n")
     3804     (write _test-input-stream "  var x/eax: byte <- copy 0\n")
     3805     (write _test-input-stream "  var y/ecx: byte <- copy 0\n")
     3806     (write _test-input-stream "  y <- copy-byte x\n")
     3807     (write _test-input-stream "  var z/edx: (addr byte) <- copy 0\n")
     3808     (write _test-input-stream "  y <- copy-byte *z\n")
     3809     (write _test-input-stream "  copy-byte-to *z, x\n")
     3810     (write _test-input-stream "}\n")
     3811     # convert
     3812     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     3813     (flush _test-output-buffered-file)
     3814 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     3820     # check output
     3821     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-function-with-byte-operations/0")
     3822     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-function-with-byte-operations/1")
     3823     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-function-with-byte-operations/2")
     3824     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-function-with-byte-operations/3")
     3825     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-function-with-byte-operations/4")
     3826     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-function-with-byte-operations/5")
     3827     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-function-with-byte-operations/6")
     3828     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-function-with-byte-operations/7")
     3829     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-function-with-byte-operations/8")
     3830     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"                  "F - test-convert-function-with-byte-operations/9")
     3831     (check-next-stream-line-equal _test-output-stream "    8a/byte-> %eax 0x00000001/r32"           "F - test-convert-function-with-byte-operations/10")
     3832     (check-next-stream-line-equal _test-output-stream "    81 4/subop/and %ecx 0xff/imm32"          "F - test-convert-function-with-byte-operations/11")
     3833     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %edx"                    "F - test-convert-function-with-byte-operations/12")
     3834     (check-next-stream-line-equal _test-output-stream "    ba/copy-to-edx 0/imm32"                  "F - test-convert-function-with-byte-operations/13")
     3835     (check-next-stream-line-equal _test-output-stream "    8a/byte-> *edx 0x00000001/r32"           "F - test-convert-function-with-byte-operations/14")
     3836     (check-next-stream-line-equal _test-output-stream "    81 4/subop/and %ecx 0xff/imm32"          "F - test-convert-function-with-byte-operations/15")
     3837     (check-next-stream-line-equal _test-output-stream "    88/byte<- *edx 0x00000000/r32"           "F - test-convert-function-with-byte-operations/16")
     3838     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %edx"                     "F - test-convert-function-with-byte-operations/17")
     3839     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-function-with-byte-operations/18")
     3840     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-function-with-byte-operations/19")
     3841     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-function-with-byte-operations/20")
     3842     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-function-with-byte-operations/21")
     3843     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-function-with-byte-operations/22")
     3844     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-function-with-byte-operations/23")
     3845     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-function-with-byte-operations/24")
     3846     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-function-with-byte-operations/25")
     3847     # . epilogue
     3848     89/<- %esp 5/r32/ebp
     3849     5d/pop-to-ebp
     3850     c3/return
     3851
     3852 # variables of type 'byte' are not allowed on the stack
     3853 test-byte-values-on-stack:
     3854     # . prologue
     3855     55/push-ebp
     3856     89/<- %ebp 4/r32/esp
     3857     # setup
     3858     (clear-stream _test-input-stream)
     3859     (clear-stream $_test-input-buffered-file->buffer)
     3860     (clear-stream _test-output-stream)
     3861     (clear-stream $_test-output-buffered-file->buffer)
     3862     (clear-stream _test-error-stream)
     3863     (clear-stream $_test-error-buffered-file->buffer)
     3864     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     3865     68/push 0/imm32
     3866     68/push 0/imm32
     3867     89/<- %edx 4/r32/esp
     3868     (tailor-exit-descriptor %edx 0x10)
     3869     #
     3870     (write _test-input-stream "fn foo {\n")
     3871     (write _test-input-stream "  var x: byte\n")
     3872     (write _test-input-stream "}\n")
     3873     # convert
     3874     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     3875     # registers except esp clobbered at this point
     3876     # restore ed
     3877     89/<- %edx 4/r32/esp
     3878     (flush _test-output-buffered-file)
     3879     (flush _test-error-buffered-file)
     3880 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     3886     # check output
     3887     (check-stream-equal _test-output-stream  ""  "F - test-byte-values-on-stack: output should be empty")
     3888     (check-next-stream-line-equal _test-error-stream  "fn foo: var 'x' of type 'byte' cannot be on the stack"  "F - test-byte-values-on-stack: error message")
     3889     # check that stop(1) was called
     3890     (check-ints-equal *(edx+4) 2 "F - test-byte-values-on-stack: exit status")
     3891     # don't restore from ebp
     3892     81 0/subop/add %esp 8/imm32
     3893     # . epilogue
     3894     5d/pop-to-ebp
     3895     c3/return
     3896
     3897 # variables of type 'byte' are not allowed in esi or edi
     3898 test-byte-values-in-unsupported-registers:
     3899     # . prologue
     3900     55/push-ebp
     3901     89/<- %ebp 4/r32/esp
     3902     # setup
     3903     (clear-stream _test-input-stream)
     3904     (clear-stream $_test-input-buffered-file->buffer)
     3905     (clear-stream _test-output-stream)
     3906     (clear-stream $_test-output-buffered-file->buffer)
     3907     (clear-stream _test-error-stream)
     3908     (clear-stream $_test-error-buffered-file->buffer)
     3909     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     3910     68/push 0/imm32
     3911     68/push 0/imm32
     3912     89/<- %edx 4/r32/esp
     3913     (tailor-exit-descriptor %edx 0x10)
     3914     #
     3915     (write _test-input-stream "fn foo {\n")
     3916     (write _test-input-stream "  var x/esi: byte <- copy 0\n")
     3917     (write _test-input-stream "}\n")
     3918     # convert
     3919     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     3920     # registers except esp clobbered at this point
     3921     # restore ed
     3922     89/<- %edx 4/r32/esp
     3923     (flush _test-output-buffered-file)
     3924     (flush _test-error-buffered-file)
     3925 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     3931     # check output
     3932     (check-stream-equal _test-output-stream  ""  "F - test-byte-values-in-unsupported-registers: output should be empty")
     3933     (check-next-stream-line-equal _test-error-stream  "fn foo: var 'x' of type 'byte' cannot be in esi or edi"  "F - test-byte-values-in-unsupported-registers: error message")
     3934     # check that stop(1) was called
     3935     (check-ints-equal *(edx+4) 2 "F - test-byte-values-in-unsupported-registers: exit status")
     3936     # don't restore from ebp
     3937     81 0/subop/add %esp 8/imm32
     3938     # . epilogue
     3939     5d/pop-to-ebp
     3940     c3/return
     3941
     3942 # variables of type 'byte' _can_ be function args. They then occupy 4 bytes.
     3943 test-copy-byte-var-from-fn-arg:
     3944     # . prologue
     3945     55/push-ebp
     3946     89/<- %ebp 4/r32/esp
     3947     # setup
     3948     (clear-stream _test-input-stream)
     3949     (clear-stream $_test-input-buffered-file->buffer)
     3950     (clear-stream _test-output-stream)
     3951     (clear-stream $_test-output-buffered-file->buffer)
     3952     #
     3953     (write _test-input-stream "fn foo x: byte, y: int {\n")
     3954     (write _test-input-stream "  var a/eax: byte <- copy x\n")
     3955     (write _test-input-stream "  var b/eax: int <- copy y\n")
     3956     (write _test-input-stream "}\n")
     3957     # convert
     3958     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     3959     (flush _test-output-buffered-file)
     3960 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     3966     # check output
     3967     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-copy-byte-from-fn-arg/0")
     3968     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-copy-byte-from-fn-arg/1")
     3969     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-copy-byte-from-fn-arg/2")
     3970     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-copy-byte-from-fn-arg/3")
     3971     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-copy-byte-from-fn-arg/4")
     3972     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-copy-byte-from-fn-arg/5")
     3973     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-copy-byte-from-fn-arg/6")
     3974     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000000/r32"  "F - test-copy-byte-from-fn-arg/7")
     3975     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x0000000c) 0x00000000/r32"  "F - test-copy-byte-from-fn-arg/8")
     3976     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"   "F - test-copy-byte-from-fn-arg/9")
     3977     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-copy-byte-from-fn-arg/10")
     3978     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-copy-byte-from-fn-arg/11")
     3979     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-copy-byte-from-fn-arg/12")
     3980     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-copy-byte-from-fn-arg/13")
     3981     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-copy-byte-from-fn-arg/14")
     3982     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-copy-byte-from-fn-arg/15")
     3983     # . epilogue
     3984     89/<- %esp 5/r32/ebp
     3985     5d/pop-to-ebp
     3986     c3/return
     3987
     3988 test-convert-compare-register-with-literal:
     3989     # . prologue
     3990     55/push-ebp
     3991     89/<- %ebp 4/r32/esp
     3992     # setup
     3993     (clear-stream _test-input-stream)
     3994     (clear-stream $_test-input-buffered-file->buffer)
     3995     (clear-stream _test-output-stream)
     3996     (clear-stream $_test-output-buffered-file->buffer)
     3997     #
     3998     (write _test-input-stream "fn foo {\n")
     3999     (write _test-input-stream "  var x/ecx: int <- copy 0\n")
     4000     (write _test-input-stream "  compare x, 0\n")
     4001     (write _test-input-stream "}\n")
     4002     # convert
     4003     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     4004     (flush _test-output-buffered-file)
     4005 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     4011     # check output
     4012     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-compare-register-with-literal/0")
     4013     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-compare-register-with-literal/1")
     4014     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-compare-register-with-literal/2")
     4015     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-compare-register-with-literal/3")
     4016     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-compare-register-with-literal/4")
     4017     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-compare-register-with-literal/5")
     4018     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-compare-register-with-literal/6")
     4019     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"  "F - test-convert-compare-register-with-literal/7")
     4020     (check-next-stream-line-equal _test-output-stream "    81 7/subop/compare %ecx 0/imm32"  "F - test-convert-compare-register-with-literal/8")
     4021     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-compare-register-with-literal/9")
     4022     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-compare-register-with-literal/10")
     4023     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-compare-register-with-literal/11")
     4024     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-compare-register-with-literal/12")
     4025     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-compare-register-with-literal/13")
     4026     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-compare-register-with-literal/14")
     4027     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-compare-register-with-literal/15")
     4028     # . epilogue
     4029     89/<- %esp 5/r32/ebp
     4030     5d/pop-to-ebp
     4031     c3/return
     4032
     4033 test-convert-compare-byte-with-literal:
     4034     # . prologue
     4035     55/push-ebp
     4036     89/<- %ebp 4/r32/esp
     4037     # setup
     4038     (clear-stream _test-input-stream)
     4039     (clear-stream $_test-input-buffered-file->buffer)
     4040     (clear-stream _test-output-stream)
     4041     (clear-stream $_test-output-buffered-file->buffer)
     4042     #
     4043     (write _test-input-stream "fn foo {\n")
     4044     (write _test-input-stream "  var x/ecx: byte <- copy 0\n")
     4045     (write _test-input-stream "  compare x, 0\n")
     4046     (write _test-input-stream "}\n")
     4047     # convert
     4048     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     4049     (flush _test-output-buffered-file)
     4050 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     4056     # no errors; output is identical to test-convert-compare-register-with-literal
     4057     # . epilogue
     4058     89/<- %esp 5/r32/ebp
     4059     5d/pop-to-ebp
     4060     c3/return
     4061
     4062 test-unknown-variable:
     4063     # . prologue
     4064     55/push-ebp
     4065     89/<- %ebp 4/r32/esp
     4066     # setup
     4067     (clear-stream _test-input-stream)
     4068     (clear-stream $_test-input-buffered-file->buffer)
     4069     (clear-stream _test-output-stream)
     4070     (clear-stream $_test-output-buffered-file->buffer)
     4071     (clear-stream _test-error-stream)
     4072     (clear-stream $_test-error-buffered-file->buffer)
     4073     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     4074     68/push 0/imm32
     4075     68/push 0/imm32
     4076     89/<- %edx 4/r32/esp
     4077     (tailor-exit-descriptor %edx 0x10)
     4078     #
     4079     (write _test-input-stream "fn foo {\n")
     4080     (write _test-input-stream "  compare x, 0\n")
     4081     (write _test-input-stream "}\n")
     4082     # convert
     4083     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     4084     # registers except esp clobbered at this point
     4085     # restore ed
     4086     89/<- %edx 4/r32/esp
     4087     (flush _test-output-buffered-file)
     4088     (flush _test-error-buffered-file)
     4089 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     4095     # check output
     4096     (check-stream-equal _test-output-stream  ""  "F - test-unknown-variable: output should be empty")
     4097     (check-next-stream-line-equal _test-error-stream  "fn foo: unknown variable 'x'"  "F - test-unknown-variable: error message")
     4098     # check that stop(1) was called
     4099     (check-ints-equal *(edx+4) 2 "F - test-unknown-variable: exit status")
     4100     # don't restore from ebp
     4101     81 0/subop/add %esp 8/imm32
     4102     # . epilogue
     4103     5d/pop-to-ebp
     4104     c3/return
     4105
     4106 test-convert-function-with-local-var-in-block:
     4107     # . prologue
     4108     55/push-ebp
     4109     89/<- %ebp 4/r32/esp
     4110     # setup
     4111     (clear-stream _test-input-stream)
     4112     (clear-stream $_test-input-buffered-file->buffer)
     4113     (clear-stream _test-output-stream)
     4114     (clear-stream $_test-output-buffered-file->buffer)
     4115     #
     4116     (write _test-input-stream "fn foo {\n")
     4117     (write _test-input-stream "  {\n")
     4118     (write _test-input-stream "    var x: int\n")
     4119     (write _test-input-stream "    increment x\n")
     4120     (write _test-input-stream "  }\n")
     4121     (write _test-input-stream "}\n")
     4122     # convert
     4123     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     4124     (flush _test-output-buffered-file)
     4125 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     4131     # check output
     4132     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-in-block/0")
     4133     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-in-block/1")
     4134     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-in-block/2")
     4135     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-in-block/3")
     4136     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-in-block/4")
     4137     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-in-block/5")
     4138     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-local-var-in-block/6")
     4139     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-local-var-in-block/7")
     4140     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-local-var-in-block/8")
     4141     (check-next-stream-line-equal _test-output-stream "      ff 0/subop/increment *(ebp+0xfffffffc)"  "F - test-convert-function-with-local-var-in-block/9")
     4142     (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")
     4143     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-local-var-in-block/11")
     4144     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-local-var-in-block/12")
     4145     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-in-block/13")
     4146     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-in-block/14")
     4147     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-in-block/15")
     4148     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-in-block/16")
     4149     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-in-block/17")
     4150     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-in-block/18")
     4151     # . epilogue
     4152     89/<- %esp 5/r32/ebp
     4153     5d/pop-to-ebp
     4154     c3/return
     4155
     4156 test-convert-function-with-local-var-in-mem-after-block:
     4157     # . prologue
     4158     55/push-ebp
     4159     89/<- %ebp 4/r32/esp
     4160     # setup
     4161     (clear-stream _test-input-stream)
     4162     (clear-stream $_test-input-buffered-file->buffer)
     4163     (clear-stream _test-output-stream)
     4164     (clear-stream $_test-output-buffered-file->buffer)
     4165     #
     4166     (write _test-input-stream "fn foo {\n")
     4167     (write _test-input-stream "  {\n")
     4168     (write _test-input-stream "    var y: int\n")
     4169     (write _test-input-stream "  }\n")
     4170     (write _test-input-stream "  var x: int\n")
     4171     (write _test-input-stream "  increment x\n")
     4172     (write _test-input-stream "}\n")
     4173     # convert
     4174     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     4175     (flush _test-output-buffered-file)
     4176 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     4182     # check output
     4183     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-in-mem-after-block/0")
     4184     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-in-mem-after-block/1")
     4185     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-in-mem-after-block/2")
     4186     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-in-mem-after-block/3")
     4187     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-in-mem-after-block/4")
     4188     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-in-mem-after-block/5")
     4189     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-local-var-in-mem-after-block/6")
     4190     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-local-var-in-mem-after-block/7")
     4191     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-local-var-in-mem-after-block/8")
     4192     (check-next-stream-line-equal _test-output-stream "      81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-local-var-in-mem-after-block/9")
     4193     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-local-var-in-mem-after-block/10")
     4194     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-local-var-in-mem-after-block/11")
     4195     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-with-local-var-in-mem-after-block/12")
     4196     (check-next-stream-line-equal _test-output-stream "    ff 0/subop/increment *(ebp+0xfffffffc)"  "F - test-convert-function-with-local-var-in-mem-after-block/13")
     4197     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-local-var-in-mem-after-block/14")
     4198     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-in-mem-after-block/15")
     4199     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-in-mem-after-block/16")
     4200     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-in-mem-after-block/17")
     4201     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-in-mem-after-block/18")
     4202     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-in-mem-after-block/19")
     4203     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-in-mem-after-block/20")
     4204     # . epilogue
     4205     89/<- %esp 5/r32/ebp
     4206     5d/pop-to-ebp
     4207     c3/return
     4208
     4209 test-convert-function-with-local-var-in-named-block:
     4210     # . prologue
     4211     55/push-ebp
     4212     89/<- %ebp 4/r32/esp
     4213     # setup
     4214     (clear-stream _test-input-stream)
     4215     (clear-stream $_test-input-buffered-file->buffer)
     4216     (clear-stream _test-output-stream)
     4217     (clear-stream $_test-output-buffered-file->buffer)
     4218     #
     4219     (write _test-input-stream "fn foo {\n")
     4220     (write _test-input-stream "  $bar: {\n")
     4221     (write _test-input-stream "    var x: int\n")
     4222     (write _test-input-stream "    increment x\n")
     4223     (write _test-input-stream "  }\n")
     4224     (write _test-input-stream "}\n")
     4225     # convert
     4226     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     4227     (flush _test-output-buffered-file)
     4228 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     4234     # check output
     4235     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-in-named-block/0")
     4236     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-in-named-block/1")
     4237     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-in-named-block/2")
     4238     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-in-named-block/3")
     4239     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-in-named-block/4")
     4240     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-in-named-block/5")
     4241     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-local-var-in-named-block/6")
     4242     (check-next-stream-line-equal _test-output-stream "$bar:loop:"              "F - test-convert-function-with-local-var-in-named-block/7")
     4243     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-local-var-in-named-block/8")
     4244     (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")
     4245     (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")
     4246     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-local-var-in-named-block/11")
     4247     (check-next-stream-line-equal _test-output-stream "$bar:break:"             "F - test-convert-function-with-local-var-in-named-block/12")
     4248     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-in-named-block/13")
     4249     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-in-named-block/14")
     4250     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-in-named-block/15")
     4251     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-in-named-block/16")
     4252     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-in-named-block/17")
     4253     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-in-named-block/18")
     4254     # . epilogue
     4255     89/<- %esp 5/r32/ebp
     4256     5d/pop-to-ebp
     4257     c3/return
     4258
     4259 test-unknown-variable-in-named-block:
     4260     # . prologue
     4261     55/push-ebp
     4262     89/<- %ebp 4/r32/esp
     4263     # setup
     4264     (clear-stream _test-input-stream)
     4265     (clear-stream $_test-input-buffered-file->buffer)
     4266     (clear-stream _test-output-stream)
     4267     (clear-stream $_test-output-buffered-file->buffer)
     4268     (clear-stream _test-error-stream)
     4269     (clear-stream $_test-error-buffered-file->buffer)
     4270     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     4271     68/push 0/imm32
     4272     68/push 0/imm32
     4273     89/<- %edx 4/r32/esp
     4274     (tailor-exit-descriptor %edx 0x10)
     4275     #
     4276     (write _test-input-stream "fn foo {\n")
     4277     (write _test-input-stream "  $a: {\n")
     4278     (write _test-input-stream "    compare x, 0\n")
     4279     (write _test-input-stream "  }\n")
     4280     (write _test-input-stream "}\n")
     4281     # convert
     4282     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     4283     # registers except esp clobbered at this point
     4284     # restore ed
     4285     89/<- %edx 4/r32/esp
     4286     (flush _test-output-buffered-file)
     4287     (flush _test-error-buffered-file)
     4288 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     4294     # check output
     4295     (check-stream-equal _test-output-stream  ""  "F - test-unknown-variable-in-named-block: output should be empty")
     4296     (check-next-stream-line-equal _test-error-stream  "fn foo: unknown variable 'x'"  "F - test-unknown-variable-in-named-block: error message")
     4297     # check that stop(1) was called
     4298     (check-ints-equal *(edx+4) 2 "F - test-unknown-variable-in-named-block: exit status")
     4299     # don't restore from ebp
     4300     81 0/subop/add %esp 8/imm32
     4301     # . epilogue
     4302     5d/pop-to-ebp
     4303     c3/return
     4304
     4305 test-always-shadow-outermost-reg-vars-in-function:
     4306     # . prologue
     4307     55/push-ebp
     4308     89/<- %ebp 4/r32/esp
     4309     # setup
     4310     (clear-stream _test-input-stream)
     4311     (clear-stream $_test-input-buffered-file->buffer)
     4312     (clear-stream _test-output-stream)
     4313     (clear-stream $_test-output-buffered-file->buffer)
     4314     #
     4315     (write _test-input-stream "fn foo {\n")
     4316     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
     4317     (write _test-input-stream "}\n")
     4318     # convert
     4319     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     4320     (flush _test-output-buffered-file)
     4321 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     4327     # check output
     4328     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-always-shadow-outermost-reg-vars-in-function/0")
     4329     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-always-shadow-outermost-reg-vars-in-function/1")
     4330     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-always-shadow-outermost-reg-vars-in-function/2")
     4331     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-always-shadow-outermost-reg-vars-in-function/3")
     4332     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-always-shadow-outermost-reg-vars-in-function/4")
     4333     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-always-shadow-outermost-reg-vars-in-function/5")
     4334     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-compare-register-with-literal/6")
     4335     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-always-shadow-outermost-reg-vars-in-function/8")
     4336     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-compare-register-with-literal/9")
     4337     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-always-shadow-outermost-reg-vars-in-function/12")
     4338     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-always-shadow-outermost-reg-vars-in-function/13")
     4339     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-always-shadow-outermost-reg-vars-in-function/14")
     4340     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-always-shadow-outermost-reg-vars-in-function/15")
     4341     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-always-shadow-outermost-reg-vars-in-function/16")
     4342     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-always-shadow-outermost-reg-vars-in-function/17")
     4343     # . epilogue
     4344     89/<- %esp 5/r32/ebp
     4345     5d/pop-to-ebp
     4346     c3/return
     4347
     4348 test-shadow-local:
     4349     # . prologue
     4350     55/push-ebp
     4351     89/<- %ebp 4/r32/esp
     4352     # setup
     4353     (clear-stream _test-input-stream)
     4354     (clear-stream $_test-input-buffered-file->buffer)
     4355     (clear-stream _test-output-stream)
     4356     (clear-stream $_test-output-buffered-file->buffer)
     4357     #
     4358     (write _test-input-stream "fn foo {\n")
     4359     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
     4360     (write _test-input-stream "  {\n")
     4361     (write _test-input-stream "    var y/ecx: int <- copy 4\n")
     4362     (write _test-input-stream "  }\n")
     4363     (write _test-input-stream "  x <- increment\n")
     4364     (write _test-input-stream "}\n")
     4365     # convert
     4366     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     4367     (flush _test-output-buffered-file)
     4368 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     4374     # check output
     4375     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-shadow-local/0")
     4376     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-shadow-local/1")
     4377     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-shadow-local/2")
     4378     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-shadow-local/3")
     4379     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-shadow-local/4")
     4380     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-shadow-local/5")
     4381     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-shadow-local/6")
     4382     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-shadow-local/7")
     4383     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-shadow-local/8")
     4384     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-shadow-local/9")
     4385     (check-next-stream-line-equal _test-output-stream "      ff 6/subop/push %ecx"  "F - test-shadow-local/10")
     4386     (check-next-stream-line-equal _test-output-stream "      b9/copy-to-ecx 4/imm32"  "F - test-shadow-local/11")
     4387     (check-next-stream-line-equal _test-output-stream "      8f 0/subop/pop %ecx" "F - test-shadow-local/12")
     4388     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-shadow-local/13")
     4389     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-shadow-local/14")
     4390     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-shadow-local/15")
     4391     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-shadow-local/16")
     4392     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-shadow-local/17")
     4393     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-shadow-local/18")
     4394     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-shadow-local/19")
     4395     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-shadow-local/20")
     4396     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-shadow-local/21")
     4397     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-shadow-local/22")
     4398     # . epilogue
     4399     89/<- %esp 5/r32/ebp
     4400     5d/pop-to-ebp
     4401     c3/return
     4402
     4403 test-shadow-name:
     4404     # . prologue
     4405     55/push-ebp
     4406     89/<- %ebp 4/r32/esp
     4407     # setup
     4408     (clear-stream _test-input-stream)
     4409     (clear-stream $_test-input-buffered-file->buffer)
     4410     (clear-stream _test-output-stream)
     4411     (clear-stream $_test-output-buffered-file->buffer)
     4412     #
     4413     (write _test-input-stream "fn foo {\n")
     4414     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
     4415     (write _test-input-stream "  {\n")
     4416     (write _test-input-stream "    var x/edx: int <- copy 4\n")
     4417     (write _test-input-stream "  }\n")
     4418     (write _test-input-stream "  x <- increment\n")
     4419     (write _test-input-stream "}\n")
     4420     # convert
     4421     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     4422     (flush _test-output-buffered-file)
     4423 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     4429     # check output
     4430     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-shadow-name/0")
     4431     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-shadow-name/1")
     4432     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-shadow-name/2")
     4433     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-shadow-name/3")
     4434     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-shadow-name/4")
     4435     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-shadow-name/5")
     4436     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-shadow-name/6")
     4437     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-shadow-name/7")
     4438     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-shadow-name/8")
     4439     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-shadow-name/9")
     4440     (check-next-stream-line-equal _test-output-stream "      ff 6/subop/push %edx"  "F - test-shadow-name/10")
     4441     (check-next-stream-line-equal _test-output-stream "      ba/copy-to-edx 4/imm32"  "F - test-shadow-name/11")
     4442     (check-next-stream-line-equal _test-output-stream "      8f 0/subop/pop %edx" "F - test-shadow-name/12")
     4443     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-shadow-name/13")
     4444     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-shadow-name/14")
     4445     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-shadow-name/15")
     4446     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-shadow-name/16")
     4447     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-shadow-name/17")
     4448     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-shadow-name/18")
     4449     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-shadow-name/19")
     4450     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-shadow-name/20")
     4451     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-shadow-name/21")
     4452     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-shadow-name/22")
     4453     # . epilogue
     4454     89/<- %esp 5/r32/ebp
     4455     5d/pop-to-ebp
     4456     c3/return
     4457
     4458 test-shadow-name-2:
     4459     # . prologue
     4460     55/push-ebp
     4461     89/<- %ebp 4/r32/esp
     4462     # setup
     4463     (clear-stream _test-input-stream)
     4464     (clear-stream $_test-input-buffered-file->buffer)
     4465     (clear-stream _test-output-stream)
     4466     (clear-stream $_test-output-buffered-file->buffer)
     4467     #
     4468     (write _test-input-stream "fn foo {\n")
     4469     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
     4470     (write _test-input-stream "  {\n")
     4471     (write _test-input-stream "    var x/edx: int <- copy 4\n")
     4472     (write _test-input-stream "    var y/ecx: int <- copy 5\n")
     4473     (write _test-input-stream "  }\n")
     4474     (write _test-input-stream "  x <- increment\n")
     4475     (write _test-input-stream "}\n")
     4476     # convert
     4477     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     4478     (flush _test-output-buffered-file)
     4479 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     4485     # check output
     4486     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-shadow-name-2/0")
     4487     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-shadow-name-2/1")
     4488     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-shadow-name-2/2")
     4489     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-shadow-name-2/3")
     4490     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-shadow-name-2/4")
     4491     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-shadow-name-2/5")
     4492     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-shadow-name-2/6")
     4493     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-shadow-name-2/7")
     4494     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-shadow-name-2/8")
     4495     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-shadow-name-2/9")
     4496     (check-next-stream-line-equal _test-output-stream "      ff 6/subop/push %edx"  "F - test-shadow-name-2/10")
     4497     (check-next-stream-line-equal _test-output-stream "      ba/copy-to-edx 4/imm32"  "F - test-shadow-name-2/11")
     4498     (check-next-stream-line-equal _test-output-stream "      ff 6/subop/push %ecx"  "F - test-shadow-name-2/12")
     4499     (check-next-stream-line-equal _test-output-stream "      b9/copy-to-ecx 5/imm32"  "F - test-shadow-name-2/13")
     4500     (check-next-stream-line-equal _test-output-stream "      8f 0/subop/pop %ecx" "F - test-shadow-name-2/14")
     4501     (check-next-stream-line-equal _test-output-stream "      8f 0/subop/pop %edx" "F - test-shadow-name-2/15")
     4502     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-shadow-name-2/16")
     4503     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-shadow-name-2/17")
     4504     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-shadow-name-2/18")
     4505     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-shadow-name-2/19")
     4506     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-shadow-name-2/20")
     4507     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-shadow-name-2/21")
     4508     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-shadow-name-2/22")
     4509     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-shadow-name-2/23")
     4510     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-shadow-name-2/24")
     4511     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-shadow-name-2/25")
     4512     # . epilogue
     4513     89/<- %esp 5/r32/ebp
     4514     5d/pop-to-ebp
     4515     c3/return
     4516
     4517 test-do-not-spill-same-register-in-block:
     4518     # . prologue
     4519     55/push-ebp
     4520     89/<- %ebp 4/r32/esp
     4521     # setup
     4522     (clear-stream _test-input-stream)
     4523     (clear-stream $_test-input-buffered-file->buffer)
     4524     (clear-stream _test-output-stream)
     4525     (clear-stream $_test-output-buffered-file->buffer)
     4526     #
     4527     (write _test-input-stream "fn foo {\n")
     4528     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
     4529     (write _test-input-stream "  var y/ecx: int <- copy 4\n")
     4530     (write _test-input-stream "  y <- increment\n")
     4531     (write _test-input-stream "}\n")
     4532     # convert
     4533     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     4534     (flush _test-output-buffered-file)
     4535 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     4541     # check output
     4542     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-do-not-spill-same-register-in-block/0")
     4543     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-do-not-spill-same-register-in-block/1")
     4544     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-do-not-spill-same-register-in-block/2")
     4545     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-do-not-spill-same-register-in-block/3")
     4546     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-do-not-spill-same-register-in-block/4")
     4547     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-do-not-spill-same-register-in-block/5")
     4548     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-do-not-spill-same-register-in-block/6")
     4549     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-do-not-spill-same-register-in-block/7")
     4550     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 4/imm32"  "F - test-do-not-spill-same-register-in-block/8")
     4551     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-do-not-spill-same-register-in-block/9")
     4552     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-do-not-spill-same-register-in-block/10")
     4553     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-do-not-spill-same-register-in-block/11")
     4554     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-do-not-spill-same-register-in-block/12")
     4555     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-do-not-spill-same-register-in-block/13")
     4556     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-do-not-spill-same-register-in-block/14")
     4557     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-do-not-spill-same-register-in-block/15")
     4558     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-do-not-spill-same-register-in-block/16")
     4559     # . epilogue
     4560     89/<- %esp 5/r32/ebp
     4561     5d/pop-to-ebp
     4562     c3/return
     4563
     4564 test-spill-different-register-in-block:
     4565     # . prologue
     4566     55/push-ebp
     4567     89/<- %ebp 4/r32/esp
     4568     # setup
     4569     (clear-stream _test-input-stream)
     4570     (clear-stream $_test-input-buffered-file->buffer)
     4571     (clear-stream _test-output-stream)
     4572     (clear-stream $_test-output-buffered-file->buffer)
     4573     #
     4574     (write _test-input-stream "fn foo {\n")
     4575     (write _test-input-stream "  var x/eax: int <- copy 3\n")
     4576     (write _test-input-stream "  var y/ecx: int <- copy 4\n")
     4577     (write _test-input-stream "  y <- increment\n")
     4578     (write _test-input-stream "}\n")
     4579     # convert
     4580     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     4581     (flush _test-output-buffered-file)
     4582 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     4588     # check output
     4589     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-spill-different-register-in-block/0")
     4590     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-spill-different-register-in-block/1")
     4591     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-spill-different-register-in-block/2")
     4592     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-spill-different-register-in-block/3")
     4593     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-spill-different-register-in-block/4")
     4594     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-spill-different-register-in-block/5")
     4595     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-spill-different-register-in-block/6")
     4596     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 3/imm32"  "F - test-spill-different-register-in-block/7")
     4597     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-spill-different-register-in-block/8")
     4598     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 4/imm32"  "F - test-spill-different-register-in-block/9")
     4599     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-spill-different-register-in-block/10")
     4600     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-spill-different-register-in-block/11")
     4601     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax" "F - test-spill-different-register-in-block/12")
     4602     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-spill-different-register-in-block/13")
     4603     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-spill-different-register-in-block/14")
     4604     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-spill-different-register-in-block/15")
     4605     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-spill-different-register-in-block/16")
     4606     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-spill-different-register-in-block/17")
     4607     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-spill-different-register-in-block/18")
     4608     # . epilogue
     4609     89/<- %esp 5/r32/ebp
     4610     5d/pop-to-ebp
     4611     c3/return
     4612
     4613 test-convert-function-with-branches-in-block:
     4614     # . prologue
     4615     55/push-ebp
     4616     89/<- %ebp 4/r32/esp
     4617     # setup
     4618     (clear-stream _test-input-stream)
     4619     (clear-stream $_test-input-buffered-file->buffer)
     4620     (clear-stream _test-output-stream)
     4621     (clear-stream $_test-output-buffered-file->buffer)
     4622     #
     4623     (write _test-input-stream "fn foo x: int {\n")
     4624     (write _test-input-stream "  {\n")
     4625     (write _test-input-stream "    break-if->=\n")
     4626     (write _test-input-stream "    loop-if-addr<\n")
     4627     (write _test-input-stream "    increment x\n")
     4628     (write _test-input-stream "    loop\n")
     4629     (write _test-input-stream "  }\n")
     4630     (write _test-input-stream "}\n")
     4631     # convert
     4632     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     4633     (flush _test-output-buffered-file)
     4634 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     4640     # check output
     4641     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-branches-in-block/0")
     4642     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-branches-in-block/1")
     4643     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-branches-in-block/2")
     4644     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-branches-in-block/3")
     4645     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-branches-in-block/4")
     4646     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-branches-in-block/5")
     4647     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-branches-in-block/6")
     4648     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-branches-in-block/7")
     4649     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-in-block/8")
     4650     (check-next-stream-line-equal _test-output-stream "        0f 8c/jump-if-< break/disp32"  "F - test-convert-function-with-branches-in-block/9")
     4651     (check-next-stream-line-equal _test-output-stream "        e9/jump $foo:0x00000002:break/disp32"  "F - test-convert-function-with-branches-in-block/10")
     4652     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-in-block/11")
     4653     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-in-block/12")
     4654     (check-next-stream-line-equal _test-output-stream "        0f 83/jump-if-addr>= break/disp32"  "F - test-convert-function-with-branches-in-block/13")
     4655     (check-next-stream-line-equal _test-output-stream "        e9/jump $foo:0x00000002:loop/disp32"  "F - test-convert-function-with-branches-in-block/14")
     4656     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-in-block/15")
     4657     (check-next-stream-line-equal _test-output-stream "      ff 0/subop/increment *(ebp+0x00000008)"  "F - test-convert-function-with-branches-in-block/16")
     4658     (check-next-stream-line-equal _test-output-stream "      e9/jump loop/disp32"  "F - test-convert-function-with-branches-in-block/17")
     4659     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-branches-in-block/18")
     4660     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-branches-in-block/19")
     4661     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-branches-in-block/20")
     4662     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-branches-in-block/21")
     4663     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-branches-in-block/22")
     4664     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-branches-in-block/23")
     4665     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-branches-in-block/24")
     4666     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-branches-in-block/25")
     4667     # . epilogue
     4668     89/<- %esp 5/r32/ebp
     4669     5d/pop-to-ebp
     4670     c3/return
     4671
     4672 test-convert-function-with-branches-in-block-2:
     4673     # . prologue
     4674     55/push-ebp
     4675     89/<- %ebp 4/r32/esp
     4676     # setup
     4677     (clear-stream _test-input-stream)
     4678     (clear-stream $_test-input-buffered-file->buffer)
     4679     (clear-stream _test-output-stream)
     4680     (clear-stream $_test-output-buffered-file->buffer)
     4681     #
     4682     (write _test-input-stream "fn foo x: int {\n")
     4683     (write _test-input-stream "  {\n")
     4684     (write _test-input-stream "    break-if->=\n")
     4685     (write _test-input-stream "    loop-if-float<\n")
     4686     (write _test-input-stream "    increment x\n")
     4687     (write _test-input-stream "    loop\n")
     4688     (write _test-input-stream "  }\n")
     4689     (write _test-input-stream "}\n")
     4690     # convert
     4691     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     4692     (flush _test-output-buffered-file)
     4693 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     4699     # check output
     4700     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-branches-in-block/0")
     4701     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-branches-in-block/1")
     4702     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-branches-in-block/2")
     4703     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-branches-in-block/3")
     4704     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-branches-in-block/4")
     4705     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-branches-in-block/5")
     4706     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-branches-in-block/6")
     4707     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-branches-in-block/7")
     4708     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-in-block/8")
     4709     (check-next-stream-line-equal _test-output-stream "        0f 8c/jump-if-< break/disp32"  "F - test-convert-function-with-branches-in-block/9")
     4710     (check-next-stream-line-equal _test-output-stream "        e9/jump $foo:0x00000002:break/disp32"  "F - test-convert-function-with-branches-in-block/10")
     4711     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-in-block/11")
     4712     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-in-block/12")
     4713     (check-next-stream-line-equal _test-output-stream "        0f 83/jump-if-addr>= break/disp32"  "F - test-convert-function-with-branches-in-block/13")
     4714     (check-next-stream-line-equal _test-output-stream "        e9/jump $foo:0x00000002:loop/disp32"  "F - test-convert-function-with-branches-in-block/14")
     4715     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-in-block/15")
     4716     (check-next-stream-line-equal _test-output-stream "      ff 0/subop/increment *(ebp+0x00000008)"  "F - test-convert-function-with-branches-in-block/16")
     4717     (check-next-stream-line-equal _test-output-stream "      e9/jump loop/disp32"  "F - test-convert-function-with-branches-in-block/17")
     4718     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-branches-in-block/18")
     4719     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-branches-in-block/19")
     4720     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-branches-in-block/20")
     4721     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-branches-in-block/21")
     4722     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-branches-in-block/22")
     4723     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-branches-in-block/23")
     4724     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-branches-in-block/24")
     4725     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-branches-in-block/25")
     4726     # . epilogue
     4727     89/<- %esp 5/r32/ebp
     4728     5d/pop-to-ebp
     4729     c3/return
     4730
     4731 test-convert-function-with-branches-in-named-block:
     4732     # . prologue
     4733     55/push-ebp
     4734     89/<- %ebp 4/r32/esp
     4735     # setup
     4736     (clear-stream _test-input-stream)
     4737     (clear-stream $_test-input-buffered-file->buffer)
     4738     (clear-stream _test-output-stream)
     4739     (clear-stream $_test-output-buffered-file->buffer)
     4740     #
     4741     (write _test-input-stream "fn foo x: int {\n")
     4742     (write _test-input-stream "  $bar: {\n")
     4743     (write _test-input-stream "    break-if->= $bar\n")
     4744     (write _test-input-stream "    loop-if-addr< $bar\n")
     4745     (write _test-input-stream "    increment x\n")
     4746     (write _test-input-stream "    loop\n")
     4747     (write _test-input-stream "  }\n")
     4748     (write _test-input-stream "}\n")
     4749     # convert
     4750     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     4751     (flush _test-output-buffered-file)
     4752 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     4758     # check output
     4759     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-branches-in-named-block/0")
     4760     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-branches-in-named-block/1")
     4761     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-branches-in-named-block/2")
     4762     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-branches-in-named-block/3")
     4763     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-branches-in-named-block/4")
     4764     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-branches-in-named-block/5")
     4765     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-branches-in-named-block/6")
     4766     (check-next-stream-line-equal _test-output-stream "$bar:loop:"              "F - test-convert-function-with-branches-in-named-block/7")
     4767     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-in-named-block/8")
     4768     (check-next-stream-line-equal _test-output-stream "        0f 8c/jump-if-< break/disp32"  "F - test-convert-function-with-branches-in-named-block/9")
     4769     (check-next-stream-line-equal _test-output-stream "        e9/jump $bar:break/disp32"  "F - test-convert-function-with-branches-in-named-block/10")
     4770     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-in-named-block/11")
     4771     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-in-named-block/12")
     4772     (check-next-stream-line-equal _test-output-stream "        0f 83/jump-if-addr>= break/disp32"  "F - test-convert-function-with-branches-in-named-block/13")
     4773     (check-next-stream-line-equal _test-output-stream "        e9/jump $bar:loop/disp32"  "F - test-convert-function-with-branches-in-named-block/14")
     4774     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-in-named-block/15")
     4775     (check-next-stream-line-equal _test-output-stream "      ff 0/subop/increment *(ebp+0x00000008)"  "F - test-convert-function-with-branches-in-named-block/16")
     4776     (check-next-stream-line-equal _test-output-stream "      e9/jump loop/disp32"   "F - test-convert-function-with-branches-in-named-block/17")
     4777     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-branches-in-named-block/18")
     4778     (check-next-stream-line-equal _test-output-stream "$bar:break:"             "F - test-convert-function-with-branches-in-named-block/19")
     4779     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-branches-in-named-block/20")
     4780     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-branches-in-named-block/21")
     4781     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-branches-in-named-block/22")
     4782     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-branches-in-named-block/23")
     4783     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-branches-in-named-block/24")
     4784     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-branches-in-named-block/25")
     4785     # . epilogue
     4786     89/<- %esp 5/r32/ebp
     4787     5d/pop-to-ebp
     4788     c3/return
     4789
     4790 test-convert-function-with-var-in-nested-block:
     4791     # . prologue
     4792     55/push-ebp
     4793     89/<- %ebp 4/r32/esp
     4794     # setup
     4795     (clear-stream _test-input-stream)
     4796     (clear-stream $_test-input-buffered-file->buffer)
     4797     (clear-stream _test-output-stream)
     4798     (clear-stream $_test-output-buffered-file->buffer)
     4799     #
     4800     (write _test-input-stream "fn foo x: int {\n")
     4801     (write _test-input-stream "  {\n")
     4802     (write _test-input-stream "    {\n")
     4803     (write _test-input-stream "      var x: int\n")
     4804     (write _test-input-stream "      increment x\n")
     4805     (write _test-input-stream "    }\n")
     4806     (write _test-input-stream "  }\n")
     4807     (write _test-input-stream "}\n")
     4808     # convert
     4809     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     4810     (flush _test-output-buffered-file)
     4811 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     4817     # check output
     4818     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-var-in-nested-block/0")
     4819     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-var-in-nested-block/1")
     4820     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-var-in-nested-block/2")
     4821     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-var-in-nested-block/3")
     4822     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-var-in-nested-block/4")
     4823     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-var-in-nested-block/5")
     4824     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-var-in-nested-block/6")
     4825     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-var-in-nested-block/7")
     4826     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-var-in-nested-block/8")
     4827     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-var-in-nested-block/9")
     4828     (check-next-stream-line-equal _test-output-stream "        68/push 0/imm32" "F - test-convert-function-with-var-in-nested-block/10")
     4829     (check-next-stream-line-equal _test-output-stream "        ff 0/subop/increment *(ebp+0xfffffffc)"  "F - test-convert-function-with-var-in-nested-block/11")
     4830     (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")
     4831     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-var-in-nested-block/13")
     4832     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-var-in-nested-block/14")
     4833     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-var-in-nested-block/15")
     4834     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-var-in-nested-block/16")
     4835     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-var-in-nested-block/17")
     4836     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-var-in-nested-block/18")
     4837     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-var-in-nested-block/19")
     4838     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-var-in-nested-block/20")
     4839     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-var-in-nested-block/21")
     4840     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-var-in-nested-block/22")
     4841     # . epilogue
     4842     89/<- %esp 5/r32/ebp
     4843     5d/pop-to-ebp
     4844     c3/return
     4845
     4846 test-convert-function-with-multiple-vars-in-nested-blocks:
     4847     # . prologue
     4848     55/push-ebp
     4849     89/<- %ebp 4/r32/esp
     4850     # setup
     4851     (clear-stream _test-input-stream)
     4852     (clear-stream $_test-input-buffered-file->buffer)
     4853     (clear-stream _test-output-stream)
     4854     (clear-stream $_test-output-buffered-file->buffer)
     4855     #
     4856     (write _test-input-stream "fn foo x: int {\n")
     4857     (write _test-input-stream "  {\n")
     4858     (write _test-input-stream "    var x/eax: int <- copy 0\n")
     4859     (write _test-input-stream "    {\n")
     4860     (write _test-input-stream "      var y: int\n")
     4861     (write _test-input-stream "      x <- add y\n")
     4862     (write _test-input-stream "    }\n")
     4863     (write _test-input-stream "  }\n")
     4864     (write _test-input-stream "}\n")
     4865     # convert
     4866     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     4867     (flush _test-output-buffered-file)
     4868 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     4874     # check output
     4875     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-multiple-vars-in-nested-blocks/0")
     4876     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-multiple-vars-in-nested-blocks/1")
     4877     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-multiple-vars-in-nested-blocks/2")
     4878     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/3")
     4879     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-multiple-vars-in-nested-blocks/4")
     4880     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-multiple-vars-in-nested-blocks/5")
     4881     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-multiple-vars-in-nested-blocks/6")
     4882     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-multiple-vars-in-nested-blocks/7")
     4883     (check-next-stream-line-equal _test-output-stream "      ff 6/subop/push %eax"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/8")
     4884     (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")
     4885     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-multiple-vars-in-nested-blocks/10")
     4886     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-multiple-vars-in-nested-blocks/11")
     4887     (check-next-stream-line-equal _test-output-stream "        68/push 0/imm32" "F - test-convert-function-with-multiple-vars-in-nested-blocks/12")
     4888     (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")
     4889     (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")
     4890     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-multiple-vars-in-nested-blocks/15")
     4891     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/16")
     4892     (check-next-stream-line-equal _test-output-stream "      8f 0/subop/pop %eax"   "F - test-convert-function-with-multiple-vars-in-nested-blocks/17")
     4893     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-multiple-vars-in-nested-blocks/18")
     4894     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/19")
     4895     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-multiple-vars-in-nested-blocks/20")
     4896     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/21")
     4897     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-multiple-vars-in-nested-blocks/22")
     4898     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/23")
     4899     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-multiple-vars-in-nested-blocks/24")
     4900     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-multiple-vars-in-nested-blocks/25")
     4901     # . epilogue
     4902     89/<- %esp 5/r32/ebp
     4903     5d/pop-to-ebp
     4904     c3/return
     4905
     4906 test-convert-function-with-branches-and-local-vars:
     4907     # A conditional 'break' after a 'var' in a block is converted into a
     4908     # nested block that performs all necessary cleanup before jumping. This
     4909     # results in some ugly code duplication.
     4910     # . prologue
     4911     55/push-ebp
     4912     89/<- %ebp 4/r32/esp
     4913     # setup
     4914     (clear-stream _test-input-stream)
     4915     (clear-stream $_test-input-buffered-file->buffer)
     4916     (clear-stream _test-output-stream)
     4917     (clear-stream $_test-output-buffered-file->buffer)
     4918     #
     4919     (write _test-input-stream "fn foo {\n")
     4920     (write _test-input-stream "  {\n")
     4921     (write _test-input-stream "    var x: int\n")
     4922     (write _test-input-stream "    break-if->=\n")
     4923     (write _test-input-stream "    increment x\n")
     4924     (write _test-input-stream "  }\n")
     4925     (write _test-input-stream "}\n")
     4926     # convert
     4927     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     4928     (flush _test-output-buffered-file)
     4929 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     4935     # check output
     4936     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-branches-and-local-vars/0")
     4937     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-branches-and-local-vars/1")
     4938     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-branches-and-local-vars/2")
     4939     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-branches-and-local-vars/3")
     4940     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-branches-and-local-vars/4")
     4941     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-branches-and-local-vars/5")
     4942     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-branches-and-local-vars/6")
     4943     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-branches-and-local-vars/7")
     4944     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-branches-and-local-vars/8")
     4945     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-and-local-vars/9")
     4946     (check-next-stream-line-equal _test-output-stream "        0f 8c/jump-if-< break/disp32"  "F - test-convert-function-with-branches-and-local-vars/10")
     4947     (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")
     4948     (check-next-stream-line-equal _test-output-stream "        e9/jump $foo:0x00000002:break/disp32"  "F - test-convert-function-with-branches-and-local-vars/12")
     4949     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-and-local-vars/13")
     4950     (check-next-stream-line-equal _test-output-stream "      ff 0/subop/increment *(ebp+0xfffffffc)"  "F - test-convert-function-with-branches-and-local-vars/14")
     4951     (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")
     4952     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-branches-and-local-vars/16")
     4953     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-branches-and-local-vars/17")
     4954     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-branches-and-local-vars/18")
     4955     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-branches-and-local-vars/19")
     4956     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-branches-and-local-vars/20")
     4957     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-branches-and-local-vars/21")
     4958     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-branches-and-local-vars/22")
     4959     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-branches-and-local-vars/23")
     4960     # . epilogue
     4961     89/<- %esp 5/r32/ebp
     4962     5d/pop-to-ebp
     4963     c3/return
     4964
     4965 test-convert-function-with-conditional-loops-and-local-vars:
     4966     # A conditional 'loop' after a 'var' in a block is converted into a nested
     4967     # block that performs all necessary cleanup before jumping. This results
     4968     # in some ugly code duplication.
     4969     # . prologue
     4970     55/push-ebp
     4971     89/<- %ebp 4/r32/esp
     4972     # setup
     4973     (clear-stream _test-input-stream)
     4974     (clear-stream $_test-input-buffered-file->buffer)
     4975     (clear-stream _test-output-stream)
     4976     (clear-stream $_test-output-buffered-file->buffer)
     4977     #
     4978     (write _test-input-stream "fn foo {\n")
     4979     (write _test-input-stream "  {\n")
     4980     (write _test-input-stream "    var x: int\n")
     4981     (write _test-input-stream "    loop-if->=\n")
     4982     (write _test-input-stream "    increment x\n")
     4983     (write _test-input-stream "  }\n")
     4984     (write _test-input-stream "}\n")
     4985     # convert
     4986     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     4987     (flush _test-output-buffered-file)
     4988 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     4994     # check output
     4995     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-conditional-loops-and-local-vars/0")
     4996     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-conditional-loops-and-local-vars/1")
     4997     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-conditional-loops-and-local-vars/2")
     4998     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-conditional-loops-and-local-vars/3")
     4999     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-conditional-loops-and-local-vars/4")
     5000     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-conditional-loops-and-local-vars/5")
     5001     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-conditional-loops-and-local-vars/6")
     5002     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-conditional-loops-and-local-vars/7")
     5003     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-conditional-loops-and-local-vars/8")
     5004     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-conditional-loops-and-local-vars/9")
     5005     (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")
     5006     (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")
     5007     (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")
     5008     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-conditional-loops-and-local-vars/13")
     5009     (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")
     5010     (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")
     5011     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-conditional-loops-and-local-vars/16")
     5012     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-conditional-loops-and-local-vars/17")
     5013     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-conditional-loops-and-local-vars/18")
     5014     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-conditional-loops-and-local-vars/19")
     5015     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-conditional-loops-and-local-vars/20")
     5016     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-conditional-loops-and-local-vars/21")
     5017     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-conditional-loops-and-local-vars/22")
     5018     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-conditional-loops-and-local-vars/23")
     5019     # . epilogue
     5020     89/<- %esp 5/r32/ebp
     5021     5d/pop-to-ebp
     5022     c3/return
     5023
     5024 test-convert-function-with-unconditional-loops-and-local-vars:
     5025     # An unconditional 'loop' after a 'var' in a block is emitted _after_ the
     5026     # regular block cleanup. Any instructions after 'loop' are dead and
     5027     # therefore skipped.
     5028     # . prologue
     5029     55/push-ebp
     5030     89/<- %ebp 4/r32/esp
     5031     # setup
     5032     (clear-stream _test-input-stream)
     5033     (clear-stream $_test-input-buffered-file->buffer)
     5034     (clear-stream _test-output-stream)
     5035     (clear-stream $_test-output-buffered-file->buffer)
     5036     #
     5037     (write _test-input-stream "fn foo {\n")
     5038     (write _test-input-stream "  {\n")
     5039     (write _test-input-stream "    var x: int\n")
     5040     (write _test-input-stream "    loop\n")
     5041     (write _test-input-stream "    increment x\n")
     5042     (write _test-input-stream "  }\n")
     5043     (write _test-input-stream "}\n")
     5044     # convert
     5045     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     5046     (flush _test-output-buffered-file)
     5047 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     5053     # check output
     5054     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-unconditional-loops-and-local-vars/0")
     5055     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-unconditional-loops-and-local-vars/1")
     5056     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-unconditional-loops-and-local-vars/2")
     5057     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-unconditional-loops-and-local-vars/3")
     5058     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-unconditional-loops-and-local-vars/4")
     5059     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-unconditional-loops-and-local-vars/5")
     5060     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-unconditional-loops-and-local-vars/6")
     5061     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-unconditional-loops-and-local-vars/7")
     5062     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-unconditional-loops-and-local-vars/8")
     5063     (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")
     5064     (check-next-stream-line-equal _test-output-stream "      e9/jump loop/disp32"  "F - test-convert-function-with-unconditional-loops-and-local-vars/10")
     5065     # not emitted:                                           ff 0/subop/increment *(ebp+0xfffffffc)
     5066     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-unconditional-loops-and-local-vars/11")
     5067     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-unconditional-loops-and-local-vars/12")
     5068     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-unconditional-loops-and-local-vars/13")
     5069     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-unconditional-loops-and-local-vars/14")
     5070     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-unconditional-loops-and-local-vars/15")
     5071     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-unconditional-loops-and-local-vars/16")
     5072     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-unconditional-loops-and-local-vars/17")
     5073     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-unconditional-loops-and-local-vars/18")
     5074     # . epilogue
     5075     89/<- %esp 5/r32/ebp
     5076     5d/pop-to-ebp
     5077     c3/return
     5078
     5079 test-convert-function-with-branches-and-loops-and-local-vars:
     5080     # . prologue
     5081     55/push-ebp
     5082     89/<- %ebp 4/r32/esp
     5083     # setup
     5084     (clear-stream _test-input-stream)
     5085     (clear-stream $_test-input-buffered-file->buffer)
     5086     (clear-stream _test-output-stream)
     5087     (clear-stream $_test-output-buffered-file->buffer)
     5088     #
     5089     (write _test-input-stream "fn foo {\n")
     5090     (write _test-input-stream "  {\n")
     5091     (write _test-input-stream "    var x: int\n")
     5092     (write _test-input-stream "    break-if->=\n")
     5093     (write _test-input-stream "    increment x\n")
     5094     (write _test-input-stream "    loop\n")
     5095     (write _test-input-stream "  }\n")
     5096     (write _test-input-stream "}\n")
     5097     # convert
     5098     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     5099     (flush _test-output-buffered-file)
     5100 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     5106     # check output
     5107     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-branches-and-loops-and-local-vars/0")
     5108     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-branches-and-loops-and-local-vars/1")
     5109     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-branches-and-loops-and-local-vars/2")
     5110     (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")
     5111     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-branches-and-loops-and-local-vars/4")
     5112     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-branches-and-loops-and-local-vars/5")
     5113     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-branches-and-loops-and-local-vars/6")
     5114     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-branches-and-loops-and-local-vars/7")
     5115     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-branches-and-loops-and-local-vars/8")
     5116     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-and-loops-and-local-vars/9")
     5117     (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")
     5118     (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")
     5119     (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")
     5120     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-and-loops-and-local-vars/13")
     5121     (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")
     5122     (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")
     5123     (check-next-stream-line-equal _test-output-stream "      e9/jump loop/disp32"  "F - test-convert-function-with-branches-and-loops-and-local-vars/16")
     5124     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-branches-and-loops-and-local-vars/17")
     5125     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-branches-and-loops-and-local-vars/18")
     5126     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-branches-and-loops-and-local-vars/19")
     5127     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-branches-and-loops-and-local-vars/20")
     5128     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-branches-and-loops-and-local-vars/21")
     5129     (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")
     5130     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-branches-and-loops-and-local-vars/23")
     5131     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-branches-and-loops-and-local-vars/24")
     5132     # . epilogue
     5133     89/<- %esp 5/r32/ebp
     5134     5d/pop-to-ebp
     5135     c3/return
     5136
     5137 test-convert-function-with-nonlocal-branches-and-loops-and-local-vars:
     5138     # . prologue
     5139     55/push-ebp
     5140     89/<- %ebp 4/r32/esp
     5141     # setup
     5142     (clear-stream _test-input-stream)
     5143     (clear-stream $_test-input-buffered-file->buffer)
     5144     (clear-stream _test-output-stream)
     5145     (clear-stream $_test-output-buffered-file->buffer)
     5146     #
     5147     (write _test-input-stream "fn foo {\n")
     5148     (write _test-input-stream "  a: {\n")
     5149     (write _test-input-stream "    var x: int\n")
     5150     (write _test-input-stream "    {\n")
     5151     (write _test-input-stream "      var y: int\n")
     5152     (write _test-input-stream "      break-if->= a\n")
     5153     (write _test-input-stream "      increment x\n")
     5154     (write _test-input-stream "      loop\n")
     5155     (write _test-input-stream "    }\n")
     5156     (write _test-input-stream "  }\n")
     5157     (write _test-input-stream "}\n")
     5158     # convert
     5159     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     5160     (flush _test-output-buffered-file)
     5161 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     5167     # check output
     5168     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/0")
     5169     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/1")
     5170     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/2")
     5171     (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")
     5172     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/4")
     5173     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/5")
     5174     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/6")
     5175     (check-next-stream-line-equal _test-output-stream "a:loop:"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/7")
     5176     (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")
     5177     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/9")
     5178     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/10")
     5179     (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")
     5180     (check-next-stream-line-equal _test-output-stream "        {"               "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/12")
     5181     (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")
     5182     (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")
     5183     (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")
     5184     (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")
     5185     (check-next-stream-line-equal _test-output-stream "        }"               "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/17")
     5186     (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")
     5187     (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")
     5188     (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")
     5189     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/21")
     5190     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/22")
     5191     (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")
     5192     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/24")
     5193     (check-next-stream-line-equal _test-output-stream "a:break:"                "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/25")
     5194     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/26")
     5195     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/27")
     5196     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/28")
     5197     (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")
     5198     (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")
     5199     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/31")
     5200     # . epilogue
     5201     89/<- %esp 5/r32/ebp
     5202     5d/pop-to-ebp
     5203     c3/return
     5204
     5205 test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2:
     5206     # . prologue
     5207     55/push-ebp
     5208     89/<- %ebp 4/r32/esp
     5209     # setup
     5210     (clear-stream _test-input-stream)
     5211     (clear-stream $_test-input-buffered-file->buffer)
     5212     (clear-stream _test-output-stream)
     5213     (clear-stream $_test-output-buffered-file->buffer)
     5214     # non-local conditional branch from a block without a local variable,
     5215     # unwinding a local on the stack
     5216     (write _test-input-stream "fn foo {\n")
     5217     (write _test-input-stream "  a: {\n")
     5218     (write _test-input-stream "    var x: int\n")
     5219     (write _test-input-stream "    {\n")
     5220     (write _test-input-stream "      break-if->= a\n")
     5221     (write _test-input-stream "    }\n")
     5222     (write _test-input-stream "  }\n")
     5223     (write _test-input-stream "}\n")
     5224     # convert
     5225     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     5226     (flush _test-output-buffered-file)
     5227 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     5233     # check output
     5234     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/0")
     5235     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/1")
     5236     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/2")
     5237     (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-2/3")
     5238     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/4")
     5239     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/5")
     5240     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/6")
     5241     (check-next-stream-line-equal _test-output-stream "a:loop:"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/7")
     5242     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/8")
     5243     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/9")
     5244     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/10")
     5245     (check-next-stream-line-equal _test-output-stream "        {"               "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/11")
     5246     (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-2/12")
     5247     (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-2/13")
     5248     (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-2/14")
     5249     (check-next-stream-line-equal _test-output-stream "        }"               "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/15")
     5250     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/16")
     5251     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/17")
     5252     (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-2/18")
     5253     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/19")
     5254     (check-next-stream-line-equal _test-output-stream "a:break:"                "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/20")
     5255     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/21")
     5256     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/22")
     5257     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/23")
     5258     (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-2/24")
     5259     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/25")
     5260     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/26")
     5261     # . epilogue
     5262     89/<- %esp 5/r32/ebp
     5263     5d/pop-to-ebp
     5264     c3/return
     5265
     5266 test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3:
     5267     # . prologue
     5268     55/push-ebp
     5269     89/<- %ebp 4/r32/esp
     5270     # setup
     5271     (clear-stream _test-input-stream)
     5272     (clear-stream $_test-input-buffered-file->buffer)
     5273     (clear-stream _test-output-stream)
     5274     (clear-stream $_test-output-buffered-file->buffer)
     5275     # non-local unconditional branch from a block without a local variable,
     5276     # unwinding a local on the stack
     5277     (write _test-input-stream "fn foo {\n")
     5278     (write _test-input-stream "  a: {\n")
     5279     (write _test-input-stream "    var x: int\n")
     5280     (write _test-input-stream "    {\n")
     5281     (write _test-input-stream "      break a\n")
     5282     (write _test-input-stream "    }\n")
     5283     (write _test-input-stream "  }\n")
     5284     (write _test-input-stream "}\n")
     5285     # convert
     5286     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     5287     (flush _test-output-buffered-file)
     5288 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     5294     # check output
     5295     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/0")
     5296     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/1")
     5297     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/2")
     5298     (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/3")
     5299     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/4")
     5300     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/5")
     5301     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/6")
     5302     (check-next-stream-line-equal _test-output-stream "a:loop:"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/7")
     5303     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/8")
     5304     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/9")
     5305     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/10")
     5306     (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-3/11")
     5307     (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-3/12")
     5308     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/14")
     5309     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/15")
     5310     (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-3/16")
     5311     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/17")
     5312     (check-next-stream-line-equal _test-output-stream "a:break:"                "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/18")
     5313     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/19")
     5314     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/20")
     5315     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/21")
     5316     (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-3/22")
     5317     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/23")
     5318     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/24")
     5319     # . epilogue
     5320     89/<- %esp 5/r32/ebp
     5321     5d/pop-to-ebp
     5322     c3/return
     5323
     5324 test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4:
     5325     # . prologue
     5326     55/push-ebp
     5327     89/<- %ebp 4/r32/esp
     5328     # setup
     5329     (clear-stream _test-input-stream)
     5330     (clear-stream $_test-input-buffered-file->buffer)
     5331     (clear-stream _test-output-stream)
     5332     (clear-stream $_test-output-buffered-file->buffer)
     5333     #
     5334     (write _test-input-stream "fn foo {\n")
     5335     (write _test-input-stream "  a: {\n")
     5336     (write _test-input-stream "    var x/esi: int <- copy 0\n")
     5337     (write _test-input-stream "    {\n")
     5338     (write _test-input-stream "      break a\n")
     5339     (write _test-input-stream "    }\n")
     5340     (write _test-input-stream "  }\n")
     5341     (write _test-input-stream "}\n")
     5342     # convert
     5343     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     5344     (flush _test-output-buffered-file)
     5345 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     5351     # check output
     5352     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/0")
     5353     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/1")
     5354     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/2")
     5355     (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-4/3")
     5356     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/4")
     5357     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/5")
     5358     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/6")
     5359     (check-next-stream-line-equal _test-output-stream "a:loop:"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/7")
     5360     (check-next-stream-line-equal _test-output-stream "      ff 6/subop/push %esi"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/8")
     5361     (check-next-stream-line-equal _test-output-stream "      be/copy-to-esi 0/imm32"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/9")
     5362     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/10")
     5363     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/11")
     5364     (check-next-stream-line-equal _test-output-stream "        8f 0/subop/pop %esi"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/12")
     5365     (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-4/13")
     5366     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/14")
     5367     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/15")
     5368     (check-next-stream-line-equal _test-output-stream "      8f 0/subop/pop %esi"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/16")
     5369     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/17")
     5370     (check-next-stream-line-equal _test-output-stream "a:break:"                "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/18")
     5371     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/19")
     5372     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/20")
     5373     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/21")
     5374     (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-4/22")
     5375     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/23")
     5376     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/24")
     5377     # . epilogue
     5378     89/<- %esp 5/r32/ebp
     5379     5d/pop-to-ebp
     5380     c3/return
     5381
     5382 test-convert-function-with-nonlocal-unconditional-break-and-local-vars:
     5383     # . prologue
     5384     55/push-ebp
     5385     89/<- %ebp 4/r32/esp
     5386     # setup
     5387     (clear-stream _test-input-stream)
     5388     (clear-stream $_test-input-buffered-file->buffer)
     5389     (clear-stream _test-output-stream)
     5390     (clear-stream $_test-output-buffered-file->buffer)
     5391     #
     5392     (write _test-input-stream "fn foo {\n")
     5393     (write _test-input-stream "  a: {\n")
     5394     (write _test-input-stream "    var x: int\n")
     5395     (write _test-input-stream "    {\n")
     5396     (write _test-input-stream "      var y: int\n")
     5397     (write _test-input-stream "      break a\n")
     5398     (write _test-input-stream "      increment x\n")
     5399     (write _test-input-stream "    }\n")
     5400     (write _test-input-stream "  }\n")
     5401     (write _test-input-stream "}\n")
     5402     # convert
     5403     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     5404     (flush _test-output-buffered-file)
     5405 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     5411     # check output
     5412     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/0")
     5413     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/1")
     5414     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/2")
     5415     (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")
     5416     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/4")
     5417     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/5")
     5418     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/6")
     5419     (check-next-stream-line-equal _test-output-stream "a:loop:"                 "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/7")
     5420     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/8")
     5421     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/9")
     5422     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/10")
     5423     (check-next-stream-line-equal _test-output-stream "        68/push 0/imm32" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/11")
     5424     (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")
     5425     (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")
     5426     (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")
     5427     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/15")
     5428     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/16")
     5429     (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")
     5430     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/18")
     5431     (check-next-stream-line-equal _test-output-stream "a:break:"                "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/19")
     5432     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/20")
     5433     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/21")
     5434     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/22")
     5435     (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")
     5436     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/24")
     5437     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/25")
     5438     # . epilogue
     5439     89/<- %esp 5/r32/ebp
     5440     5d/pop-to-ebp
     5441     c3/return
     5442
     5443 test-convert-function-with-unconditional-break-and-local-vars:
     5444     # . prologue
     5445     55/push-ebp
     5446     89/<- %ebp 4/r32/esp
     5447     # setup
     5448     (clear-stream _test-input-stream)
     5449     (clear-stream $_test-input-buffered-file->buffer)
     5450     (clear-stream _test-output-stream)
     5451     (clear-stream $_test-output-buffered-file->buffer)
     5452     #
     5453     (write _test-input-stream "fn foo {\n")
     5454     (write _test-input-stream "  {\n")
     5455     (write _test-input-stream "    var x: int\n")
     5456     (write _test-input-stream "    {\n")
     5457     (write _test-input-stream "      var y: int\n")
     5458     (write _test-input-stream "      break\n")
     5459     (write _test-input-stream "      increment x\n")
     5460     (write _test-input-stream "    }\n")
     5461     (write _test-input-stream "  }\n")
     5462     (write _test-input-stream "}\n")
     5463     # convert
     5464     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     5465     (flush _test-output-buffered-file)
     5466 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     5472     # check output
     5473     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-unconditional-break-and-local-vars/0")
     5474     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-unconditional-break-and-local-vars/1")
     5475     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-unconditional-break-and-local-vars/2")
     5476     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-unconditional-break-and-local-vars/3")
     5477     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-unconditional-break-and-local-vars/4")
     5478     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-unconditional-break-and-local-vars/5")
     5479     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-unconditional-break-and-local-vars/6")
     5480     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-unconditional-break-and-local-vars/7")
     5481     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-unconditional-break-and-local-vars/8")
     5482     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-unconditional-break-and-local-vars/9")
     5483     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-unconditional-break-and-local-vars/10")
     5484     (check-next-stream-line-equal _test-output-stream "        68/push 0/imm32" "F - test-convert-function-with-unconditional-break-and-local-vars/11")
     5485     (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")
     5486     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-unconditional-break-and-local-vars/13")
     5487     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-unconditional-break-and-local-vars/14")
     5488     (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")
     5489     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-unconditional-break-and-local-vars/16")
     5490     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-unconditional-break-and-local-vars/17")
     5491     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-unconditional-break-and-local-vars/18")
     5492     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-unconditional-break-and-local-vars/19")
     5493     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-unconditional-break-and-local-vars/20")
     5494     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-unconditional-break-and-local-vars/21")
     5495     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-unconditional-break-and-local-vars/22")
     5496     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-unconditional-break-and-local-vars/23")
     5497     # . epilogue
     5498     89/<- %esp 5/r32/ebp
     5499     5d/pop-to-ebp
     5500     c3/return
     5501
     5502 test-convert-function-with-nonlocal-unconditional-loop-and-local-vars:
     5503     # . prologue
     5504     55/push-ebp
     5505     89/<- %ebp 4/r32/esp
     5506     # setup
     5507     (clear-stream _test-input-stream)
     5508     (clear-stream $_test-input-buffered-file->buffer)
     5509     (clear-stream _test-output-stream)
     5510     (clear-stream $_test-output-buffered-file->buffer)
     5511     #
     5512     (write _test-input-stream "fn foo {\n")
     5513     (write _test-input-stream "  a: {\n")
     5514     (write _test-input-stream "    var x: int\n")
     5515     (write _test-input-stream "    {\n")
     5516     (write _test-input-stream "      var y: int\n")
     5517     (write _test-input-stream "      loop a\n")
     5518     (write _test-input-stream "      increment x\n")
     5519     (write _test-input-stream "    }\n")
     5520     (write _test-input-stream "  }\n")
     5521     (write _test-input-stream "}\n")
     5522     # convert
     5523     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     5524     (flush _test-output-buffered-file)
     5525 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     5531     # check output
     5532     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/0")
     5533     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/1")
     5534     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/2")
     5535     (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")
     5536     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/4")
     5537     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/5")
     5538     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/6")
     5539     (check-next-stream-line-equal _test-output-stream "a:loop:"                 "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/7")
     5540     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/8")
     5541     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/9")
     5542     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/10")
     5543     (check-next-stream-line-equal _test-output-stream "        68/push 0/imm32" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/11")
     5544     (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")
     5545     (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")
     5546     (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")
     5547     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/15")
     5548     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/16")
     5549     (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")
     5550     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/18")
     5551     (check-next-stream-line-equal _test-output-stream "a:break:"                "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/19")
     5552     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/20")
     5553     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/21")
     5554     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/22")
     5555     (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")
     5556     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/24")
     5557     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/25")
     5558     # . epilogue
     5559     89/<- %esp 5/r32/ebp
     5560     5d/pop-to-ebp
     5561     c3/return
     5562
     5563 test-convert-function-with-local-array-var-in-mem:
     5564     # . prologue
     5565     55/push-ebp
     5566     89/<- %ebp 4/r32/esp
     5567     # setup
     5568     (clear-stream _test-input-stream)
     5569     (clear-stream $_test-input-buffered-file->buffer)
     5570     (clear-stream _test-output-stream)
     5571     (clear-stream $_test-output-buffered-file->buffer)
     5572     #
     5573     (write _test-input-stream "fn foo {\n")
     5574     (write _test-input-stream "  var x: (array int 3)\n")
     5575     (write _test-input-stream "}\n")
     5576     # convert
     5577     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     5578     (flush _test-output-buffered-file)
     5579 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     5585     # check output
     5586     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-array-var-in-mem/0")
     5587     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-array-var-in-mem/1")
     5588     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-array-var-in-mem/2")
     5589     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-array-var-in-mem/3")
     5590     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-array-var-in-mem/4")
     5591     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-array-var-in-mem/5")
     5592     # define x
     5593     (check-next-stream-line-equal _test-output-stream "    (push-n-zero-bytes 0x0000000c)"  "F - test-convert-function-with-local-array-var-in-mem/7")
     5594     (check-next-stream-line-equal _test-output-stream "    68/push 0x0000000c/imm32"  "F - test-convert-function-with-local-array-var-in-mem/8")
     5595     # reclaim x
     5596     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000010/imm32"  "F - test-convert-function-with-local-array-var-in-mem/9")
     5597     #
     5598     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-array-var-in-mem/10")
     5599     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-array-var-in-mem/11")
     5600     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-array-var-in-mem/12")
     5601     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-array-var-in-mem/13")
     5602     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-array-var-in-mem/14")
     5603     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-array-var-in-mem/15")
     5604     # . epilogue
     5605     89/<- %esp 5/r32/ebp
     5606     5d/pop-to-ebp
     5607     c3/return
     5608
     5609 test-array-size-in-hex:
     5610     # . prologue
     5611     55/push-ebp
     5612     89/<- %ebp 4/r32/esp
     5613     # setup
     5614     (clear-stream _test-input-stream)
     5615     (clear-stream $_test-input-buffered-file->buffer)
     5616     (clear-stream _test-output-stream)
     5617     (clear-stream $_test-output-buffered-file->buffer)
     5618     (clear-stream _test-error-stream)
     5619     (clear-stream $_test-error-buffered-file->buffer)
     5620     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     5621     68/push 0/imm32
     5622     68/push 0/imm32
     5623     89/<- %edx 4/r32/esp
     5624     (tailor-exit-descriptor %edx 0x10)
     5625     #
     5626     (write _test-input-stream "fn foo {\n")
     5627     (write _test-input-stream "  var x: (array int 10)\n")
     5628     (write _test-input-stream "}\n")
     5629     # convert
     5630     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     5631     # registers except esp clobbered at this point
     5632     # restore ed
     5633     89/<- %edx 4/r32/esp
     5634     (flush _test-output-buffered-file)
     5635     (flush _test-error-buffered-file)
     5636 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     5642     # check output
     5643     (check-stream-equal _test-output-stream  ""  "F - test-array-size-in-hex: output should be empty")
     5644     (check-next-stream-line-equal _test-error-stream  "literal integers are always hex in Mu; start '10' with a '0x' to be unambiguous, converting it to hexadecimal as necessary."  "F - test-array-size-in-hex: error message")
     5645     # check that stop(1) was called
     5646     (check-ints-equal *(edx+4) 2 "F - test-array-size-in-hex: exit status")
     5647     # don't restore from ebp
     5648     81 0/subop/add %esp 8/imm32
     5649     # . epilogue
     5650     5d/pop-to-ebp
     5651     c3/return
     5652
     5653 test-array-size-with-metadata:
     5654     # . prologue
     5655     55/push-ebp
     5656     89/<- %ebp 4/r32/esp
     5657     # setup
     5658     (clear-stream _test-input-stream)
     5659     (clear-stream $_test-input-buffered-file->buffer)
     5660     (clear-stream _test-output-stream)
     5661     (clear-stream $_test-output-buffered-file->buffer)
     5662     #
     5663     (write _test-input-stream "fn foo {\n")
     5664     (write _test-input-stream "  var x: (array int 3/bar)\n")
     5665     (write _test-input-stream "}\n")
     5666     # convert
     5667     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     5668     (flush _test-output-buffered-file)
     5669 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     5675     # no errors
     5676     # . epilogue
     5677     89/<- %esp 5/r32/ebp
     5678     5d/pop-to-ebp
     5679     c3/return
     5680
     5681 test-convert-function-with-populate:
     5682     # . prologue
     5683     55/push-ebp
     5684     89/<- %ebp 4/r32/esp
     5685     # setup
     5686     (clear-stream _test-input-stream)
     5687     (clear-stream $_test-input-buffered-file->buffer)
     5688     (clear-stream _test-output-stream)
     5689     (clear-stream $_test-output-buffered-file->buffer)
     5690     #
     5691     (write _test-input-stream "fn foo {\n")
     5692     (write _test-input-stream "  var x/ecx: (addr handle array int) <- copy 0\n")
     5693     (write _test-input-stream "  populate x, 7\n")
     5694     (write _test-input-stream "}\n")
     5695     # convert
     5696     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     5697     (flush _test-output-buffered-file)
     5698 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     5704     # check output
     5705     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-populate/0")
     5706     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-populate/1")
     5707     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-populate/2")
     5708     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-populate/3")
     5709     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-populate/4")
     5710     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-populate/5")
     5711     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-populate/6")
     5712     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"  "F - test-convert-function-with-populate/7")
     5713     (check-next-stream-line-equal _test-output-stream "    (allocate-array2 Heap 0x00000004 7 %ecx)"  "F - test-convert-function-with-populate/8")  # 4 = size-of(int)
     5714     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-function-with-populate/9")
     5715     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-populate/10")
     5716     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-populate/11")
     5717     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-populate/12")
     5718     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-populate/13")
     5719     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-populate/14")
     5720     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-populate/15")
     5721     # . epilogue
     5722     89/<- %esp 5/r32/ebp
     5723     5d/pop-to-ebp
     5724     c3/return
     5725
     5726 # special-case for size(byte) when allocating array
     5727 test-convert-function-with-local-array-of-bytes-in-mem:
     5728     # . prologue
     5729     55/push-ebp
     5730     89/<- %ebp 4/r32/esp
     5731     # setup
     5732     (clear-stream _test-input-stream)
     5733     (clear-stream $_test-input-buffered-file->buffer)
     5734     (clear-stream _test-output-stream)
     5735     (clear-stream $_test-output-buffered-file->buffer)
     5736     #
     5737     (write _test-input-stream "fn foo {\n")
     5738     (write _test-input-stream "  var x: (array byte 3)\n")
     5739     (write _test-input-stream "}\n")
     5740     # convert
     5741     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     5742     (flush _test-output-buffered-file)
     5743 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     5749     # check output
     5750     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-array-of-bytes-in-mem/0")
     5751     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-array-of-bytes-in-mem/1")
     5752     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-array-of-bytes-in-mem/2")
     5753     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-array-of-bytes-in-mem/3")
     5754     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-array-of-bytes-in-mem/4")
     5755     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-array-of-bytes-in-mem/5")
     5756     # define x
     5757     (check-next-stream-line-equal _test-output-stream "    (push-n-zero-bytes 0x00000003)"  "F - test-convert-function-with-local-array-of-bytes-in-mem/7")
     5758     (check-next-stream-line-equal _test-output-stream "    68/push 0x00000003/imm32"  "F - test-convert-function-with-local-array-of-bytes-in-mem/8")
     5759     # reclaim x
     5760     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000007/imm32"  "F - test-convert-function-with-local-array-of-bytes-in-mem/9")
     5761     #
     5762     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-array-of-bytes-in-mem/10")
     5763     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-array-of-bytes-in-mem/11")
     5764     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-array-of-bytes-in-mem/12")
     5765     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-array-of-bytes-in-mem/13")
     5766     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-array-of-bytes-in-mem/14")
     5767     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-array-of-bytes-in-mem/15")
     5768     # . epilogue
     5769     89/<- %esp 5/r32/ebp
     5770     5d/pop-to-ebp
     5771     c3/return
     5772
     5773 test-convert-address:
     5774     # . prologue
     5775     55/push-ebp
     5776     89/<- %ebp 4/r32/esp
     5777     # setup
     5778     (clear-stream _test-input-stream)
     5779     (clear-stream $_test-input-buffered-file->buffer)
     5780     (clear-stream _test-output-stream)
     5781     (clear-stream $_test-output-buffered-file->buffer)
     5782     #
     5783     (write _test-input-stream "fn foo {\n")
     5784     (write _test-input-stream "  var a: int\n")
     5785     (write _test-input-stream "  var b/eax: (addr int) <- address a\n")
     5786     (write _test-input-stream "}\n")
     5787     # convert
     5788     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     5789     (flush _test-output-buffered-file)
     5790 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     5796     # check output
     5797     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-address/0")
     5798     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-address/1")
     5799     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-address/2")
     5800     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-address/3")
     5801     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-address/4")
     5802     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-address/5")
     5803     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-address/6")
     5804     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-address/7")
     5805     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(ebp+0xfffffffc) 0x00000000/r32"  "F - test-convert-address/8")
     5806     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"  "F - test-convert-address/9")
     5807     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-address/10")
     5808     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-address/11")
     5809     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-address/12")
     5810     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-address/13")
     5811     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-address/14")
     5812     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-address/15")
     5813     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-address/16")
     5814     # . epilogue
     5815     89/<- %esp 5/r32/ebp
     5816     5d/pop-to-ebp
     5817     c3/return
     5818
     5819 test-convert-floating-point-convert:
     5820     # . prologue
     5821     55/push-ebp
     5822     89/<- %ebp 4/r32/esp
     5823     # setup
     5824     (clear-stream _test-input-stream)
     5825     (clear-stream $_test-input-buffered-file->buffer)
     5826     (clear-stream _test-output-stream)
     5827     (clear-stream $_test-output-buffered-file->buffer)
     5828     #
     5829     (write _test-input-stream "fn foo {\n")
     5830     (write _test-input-stream "  var a/eax: int <- copy 0\n")
     5831     (write _test-input-stream "  var b/xmm1: float <- convert a\n")
     5832     (write _test-input-stream "}\n")
     5833     # convert
     5834     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     5835     (flush _test-output-buffered-file)
     5836 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     5842     # check output
     5843     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-floating-point-convert/0")
     5844     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-floating-point-convert/1")
     5845     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-floating-point-convert/2")
     5846     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-floating-point-convert/3")
     5847     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-floating-point-convert/4")
     5848     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-floating-point-convert/5")
     5849     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-floating-point-convert/6")
     5850     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"  "F - test-convert-floating-point-convert/7")
     5851     (check-next-stream-line-equal _test-output-stream "    81 5/subop/subtract %esp 4/imm32"  "F - test-convert-floating-point-convert/8")
     5852     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/<- *esp 1/x32"  "F - test-convert-floating-point-convert/9")
     5853     (check-next-stream-line-equal _test-output-stream "    f3 0f 2a/convert-to-float %eax 0x00000001/x32"  "F - test-convert-floating-point-convert/10")
     5854     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/-> *esp 1/x32"  "F - test-convert-floating-point-convert/11")
     5855     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-floating-point-convert/12")
     5856     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax" "F - test-convert-floating-point-convert/13")
     5857     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-floating-point-convert/14")
     5858     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-floating-point-convert/15")
     5859     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-floating-point-convert/16")
     5860     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-floating-point-convert/17")
     5861     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-floating-point-convert/18")
     5862     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-floating-point-convert/19")
     5863     # . epilogue
     5864     89/<- %esp 5/r32/ebp
     5865     5d/pop-to-ebp
     5866     c3/return
     5867
     5868 test-convert-floating-point-convert-2:
     5869     # . prologue
     5870     55/push-ebp
     5871     89/<- %ebp 4/r32/esp
     5872     # setup
     5873     (clear-stream _test-input-stream)
     5874     (clear-stream $_test-input-buffered-file->buffer)
     5875     (clear-stream _test-output-stream)
     5876     (clear-stream $_test-output-buffered-file->buffer)
     5877     #
     5878     (write _test-input-stream "fn foo {\n")
     5879     (write _test-input-stream "  var a/eax: int <- copy 0\n")
     5880     (write _test-input-stream "  var b/xmm1: float <- convert a\n")
     5881     (write _test-input-stream "  a <- convert b\n")
     5882     (write _test-input-stream "}\n")
     5883     # convert
     5884     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     5885     (flush _test-output-buffered-file)
     5886 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     5892     # check output
     5893     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-floating-point-convert-2/0")
     5894     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-floating-point-convert-2/1")
     5895     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-floating-point-convert-2/2")
     5896     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-floating-point-convert-2/3")
     5897     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-floating-point-convert-2/4")
     5898     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-floating-point-convert-2/5")
     5899     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-floating-point-convert-2/6")
     5900     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"  "F - test-convert-floating-point-convert-2/7")
     5901     (check-next-stream-line-equal _test-output-stream "    81 5/subop/subtract %esp 4/imm32"  "F - test-convert-floating-point-convert-2/8")
     5902     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/<- *esp 1/x32"  "F - test-convert-floating-point-convert-2/9")
     5903     (check-next-stream-line-equal _test-output-stream "    f3 0f 2a/convert-to-float %eax 0x00000001/x32"  "F - test-convert-floating-point-convert-2/10")
     5904     (check-next-stream-line-equal _test-output-stream "    f3 0f 2d/convert-to-int %xmm1 0x00000000/r32"  "F - test-convert-floating-point-convert-2/11")
     5905     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/-> *esp 1/x32"  "F - test-convert-floating-point-convert-2/12")
     5906     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-floating-point-convert-2/13")
     5907     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax" "F - test-convert-floating-point-convert-2/14")
     5908     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-floating-point-convert-2/15")
     5909     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-floating-point-convert-2/16")
     5910     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-floating-point-convert-2/17")
     5911     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-floating-point-convert-2/18")
     5912     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-floating-point-convert-2/19")
     5913     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-floating-point-convert-2/20")
     5914     # . epilogue
     5915     89/<- %esp 5/r32/ebp
     5916     5d/pop-to-ebp
     5917     c3/return
     5918
     5919 test-convert-floating-point-operation:
     5920     # . prologue
     5921     55/push-ebp
     5922     89/<- %ebp 4/r32/esp
     5923     # setup
     5924     (clear-stream _test-input-stream)
     5925     (clear-stream $_test-input-buffered-file->buffer)
     5926     (clear-stream _test-output-stream)
     5927     (clear-stream $_test-output-buffered-file->buffer)
     5928     #
     5929     (write _test-input-stream "fn f {\n")
     5930     (write _test-input-stream "  var m: float\n")
     5931     (write _test-input-stream "  var x/xmm1: float <- copy m\n")
     5932     (write _test-input-stream "  var y/xmm5: float <- copy m\n")
     5933     (write _test-input-stream "  x <- copy y\n")
     5934     (write _test-input-stream "  copy-to m, y\n")
     5935     (write _test-input-stream "  x <- add y\n")
     5936     (write _test-input-stream "  x <- add m\n")
     5937     (write _test-input-stream "  x <- subtract y\n")
     5938     (write _test-input-stream "  x <- subtract m\n")
     5939     (write _test-input-stream "  x <- multiply y\n")
     5940     (write _test-input-stream "  x <- multiply m\n")
     5941     (write _test-input-stream "  x <- divide y\n")
     5942     (write _test-input-stream "  x <- divide m\n")
     5943     (write _test-input-stream "  x <- reciprocal y\n")
     5944     (write _test-input-stream "  x <- reciprocal m\n")
     5945     (write _test-input-stream "  x <- square-root y\n")
     5946     (write _test-input-stream "  x <- square-root m\n")
     5947     (write _test-input-stream "  x <- inverse-square-root y\n")
     5948     (write _test-input-stream "  x <- inverse-square-root m\n")
     5949     (write _test-input-stream "  x <- max y\n")
     5950     (write _test-input-stream "  x <- max m\n")
     5951     (write _test-input-stream "  x <- min y\n")
     5952     (write _test-input-stream "  x <- min m\n")
     5953     (write _test-input-stream "  compare x, y\n")
     5954     (write _test-input-stream "  compare x, m\n")
     5955     (write _test-input-stream "}\n")
     5956     # convert
     5957     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     5958     (flush _test-output-buffered-file)
     5959 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     5965     # check output
     5966     (check-next-stream-line-equal _test-output-stream "f:"                                                                     "F - test-convert-floating-point-operation/0")
     5967     (check-next-stream-line-equal _test-output-stream "  # . prologue"                                                         "F - test-convert-floating-point-operation/1")
     5968     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                                                          "F - test-convert-floating-point-operation/2")
     5969     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                                                 "F - test-convert-floating-point-operation/3")
     5970     (check-next-stream-line-equal _test-output-stream "  {"                                                                    "F - test-convert-floating-point-operation/4")
     5971     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:loop:"                                                    "F - test-convert-floating-point-operation/5")
     5972     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"                                                    "F - test-convert-floating-point-operation/6")
     5973     (check-next-stream-line-equal _test-output-stream "    81 5/subop/subtract %esp 4/imm32"                                   "F - test-convert-floating-point-operation/7")
     5974     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/<- *esp 1/x32"                                             "F - test-convert-floating-point-operation/8")
     5975     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/copy *(ebp+0xfffffffc) 0x00000001/x32"                     "F - test-convert-floating-point-operation/9")
     5976     (check-next-stream-line-equal _test-output-stream "    81 5/subop/subtract %esp 4/imm32"                                   "F - test-convert-floating-point-operation/10")
     5977     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/<- *esp 5/x32"                                             "F - test-convert-floating-point-operation/11")
     5978     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/copy *(ebp+0xfffffffc) 0x00000005/x32"                     "F - test-convert-floating-point-operation/12")
     5979     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/copy %xmm1 0x00000005/x32"                                 "F - test-convert-floating-point-operation/13")
     5980     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/copy *(ebp+0xfffffffc) 0x00000005/x32"                     "F - test-convert-floating-point-operation/14")
     5981     (check-next-stream-line-equal _test-output-stream "    f3 0f 58/add %xmm5 0x00000001/x32"                                  "F - test-convert-floating-point-operation/15")
     5982     (check-next-stream-line-equal _test-output-stream "    f3 0f 58/add *(ebp+0xfffffffc) 0x00000001/x32"                      "F - test-convert-floating-point-operation/16")
     5983     (check-next-stream-line-equal _test-output-stream "    f3 0f 5c/subtract %xmm5 0x00000001/x32"                             "F - test-convert-floating-point-operation/17")
     5984     (check-next-stream-line-equal _test-output-stream "    f3 0f 5c/subtract *(ebp+0xfffffffc) 0x00000001/x32"                 "F - test-convert-floating-point-operation/18")
     5985     (check-next-stream-line-equal _test-output-stream "    f3 0f 59/multiply %xmm5 0x00000001/x32"                             "F - test-convert-floating-point-operation/19")
     5986     (check-next-stream-line-equal _test-output-stream "    f3 0f 59/multiply *(ebp+0xfffffffc) 0x00000001/x32"                 "F - test-convert-floating-point-operation/20")
     5987     (check-next-stream-line-equal _test-output-stream "    f3 0f 5e/divide %xmm5 0x00000001/x32"                               "F - test-convert-floating-point-operation/21")
     5988     (check-next-stream-line-equal _test-output-stream "    f3 0f 5e/divide *(ebp+0xfffffffc) 0x00000001/x32"                   "F - test-convert-floating-point-operation/22")
     5989     (check-next-stream-line-equal _test-output-stream "    f3 0f 53/reciprocal %xmm5 0x00000001/x32"                           "F - test-convert-floating-point-operation/23")
     5990     (check-next-stream-line-equal _test-output-stream "    f3 0f 53/reciprocal *(ebp+0xfffffffc) 0x00000001/x32"               "F - test-convert-floating-point-operation/24")
     5991     (check-next-stream-line-equal _test-output-stream "    f3 0f 51/square-root %xmm5 0x00000001/x32"                          "F - test-convert-floating-point-operation/25")
     5992     (check-next-stream-line-equal _test-output-stream "    f3 0f 51/square-root *(ebp+0xfffffffc) 0x00000001/x32"              "F - test-convert-floating-point-operation/26")
     5993     (check-next-stream-line-equal _test-output-stream "    f3 0f 52/inverse-square-root %xmm5 0x00000001/x32"                  "F - test-convert-floating-point-operation/27")
     5994     (check-next-stream-line-equal _test-output-stream "    f3 0f 52/inverse-square-root *(ebp+0xfffffffc) 0x00000001/x32"      "F - test-convert-floating-point-operation/28")
     5995     (check-next-stream-line-equal _test-output-stream "    f3 0f 5f/max %xmm5 0x00000001/x32"                                  "F - test-convert-floating-point-operation/29")
     5996     (check-next-stream-line-equal _test-output-stream "    f3 0f 5f/max *(ebp+0xfffffffc) 0x00000001/x32"                      "F - test-convert-floating-point-operation/30")
     5997     (check-next-stream-line-equal _test-output-stream "    f3 0f 5d/min %xmm5 0x00000001/x32"                                  "F - test-convert-floating-point-operation/31")
     5998     (check-next-stream-line-equal _test-output-stream "    f3 0f 5d/min *(ebp+0xfffffffc) 0x00000001/x32"                      "F - test-convert-floating-point-operation/32")
     5999     (check-next-stream-line-equal _test-output-stream "    0f 2f/compare %xmm5 0x00000001/x32"                                 "F - test-convert-floating-point-operation/33")
     6000     (check-next-stream-line-equal _test-output-stream "    0f 2f/compare *(ebp+0xfffffffc) 0x00000001/x32"                     "F - test-convert-floating-point-operation/34")
     6001     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/-> *esp 5/x32"                                             "F - test-convert-floating-point-operation/35")
     6002     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"                                        "F - test-convert-floating-point-operation/36")
     6003     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/-> *esp 1/x32"                                             "F - test-convert-floating-point-operation/37")
     6004     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"                                        "F - test-convert-floating-point-operation/38")
     6005     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"                               "F - test-convert-floating-point-operation/39")
     6006     (check-next-stream-line-equal _test-output-stream "  }"                                                                    "F - test-convert-floating-point-operation/40")
     6007     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:break:"                                                   "F - test-convert-floating-point-operation/41")
     6008     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                                                         "F - test-convert-floating-point-operation/42")
     6009     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                                                 "F - test-convert-floating-point-operation/43")
     6010     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                                                        "F - test-convert-floating-point-operation/44")
     6011     (check-next-stream-line-equal _test-output-stream "  c3/return"                                                            "F - test-convert-floating-point-operation/45")
     6012     # . epilogue
     6013     89/<- %esp 5/r32/ebp
     6014     5d/pop-to-ebp
     6015     c3/return
     6016
     6017 test-convert-floating-point-dereferenced:
     6018     # . prologue
     6019     55/push-ebp
     6020     89/<- %ebp 4/r32/esp
     6021     # setup
     6022     (clear-stream _test-input-stream)
     6023     (clear-stream $_test-input-buffered-file->buffer)
     6024     (clear-stream _test-output-stream)
     6025     (clear-stream $_test-output-buffered-file->buffer)
     6026     #
     6027     (write _test-input-stream "fn f {\n")
     6028     (write _test-input-stream "  var m: float\n")
     6029     (write _test-input-stream "  var x/xmm1: float <- copy m\n")
     6030     (write _test-input-stream "  var y/eax: (addr float) <- copy 0\n")
     6031     (write _test-input-stream "  x <- multiply *y\n")
     6032     (write _test-input-stream "}\n")
     6033     # convert
     6034     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     6035     (flush _test-output-buffered-file)
     6036 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     6042     # check output
     6043     (check-next-stream-line-equal _test-output-stream "f:"                                                                     "F - test-convert-floating-point-dereferenced/0")
     6044     (check-next-stream-line-equal _test-output-stream "  # . prologue"                                                         "F - test-convert-floating-point-dereferenced/1")
     6045     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                                                          "F - test-convert-floating-point-dereferenced/2")
     6046     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                                                 "F - test-convert-floating-point-dereferenced/3")
     6047     (check-next-stream-line-equal _test-output-stream "  {"                                                                    "F - test-convert-floating-point-dereferenced/4")
     6048     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:loop:"                                                    "F - test-convert-floating-point-dereferenced/5")
     6049     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"                                                    "F - test-convert-floating-point-dereferenced/6")
     6050     (check-next-stream-line-equal _test-output-stream "    81 5/subop/subtract %esp 4/imm32"                                   "F - test-convert-floating-point-dereferenced/7")
     6051     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/<- *esp 1/x32"                                             "F - test-convert-floating-point-dereferenced/8")
     6052     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/copy *(ebp+0xfffffffc) 0x00000001/x32"                     "F - test-convert-floating-point-dereferenced/9")
     6053     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                                               "F - test-convert-floating-point-dereferenced/10")
     6054     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                                             "F - test-convert-floating-point-dereferenced/11")
     6055     (check-next-stream-line-equal _test-output-stream "    f3 0f 59/multiply *eax 0x00000001/x32"                              "F - test-convert-floating-point-dereferenced/12")
     6056     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                                                "F - test-convert-floating-point-dereferenced/13")
     6057     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/-> *esp 1/x32"                                             "F - test-convert-floating-point-dereferenced/14")
     6058     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"                                        "F - test-convert-floating-point-dereferenced/15")
     6059     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"                               "F - test-convert-floating-point-dereferenced/16")
     6060     (check-next-stream-line-equal _test-output-stream "  }"                                                                    "F - test-convert-floating-point-dereferenced/17")
     6061     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:break:"                                                   "F - test-convert-floating-point-dereferenced/18")
     6062     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                                                         "F - test-convert-floating-point-dereferenced/19")
     6063     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                                                 "F - test-convert-floating-point-dereferenced/20")
     6064     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                                                        "F - test-convert-floating-point-dereferenced/21")
     6065     (check-next-stream-line-equal _test-output-stream "  c3/return"                                                            "F - test-convert-floating-point-dereferenced/22")
     6066     # . epilogue
     6067     89/<- %esp 5/r32/ebp
     6068     5d/pop-to-ebp
     6069     c3/return
     6070
     6071 test-convert-length-of-array:
     6072     # . prologue
     6073     55/push-ebp
     6074     89/<- %ebp 4/r32/esp
     6075     # setup
     6076     (clear-stream _test-input-stream)
     6077     (clear-stream $_test-input-buffered-file->buffer)
     6078     (clear-stream _test-output-stream)
     6079     (clear-stream $_test-output-buffered-file->buffer)
     6080     #
     6081     (write _test-input-stream "fn foo a: (addr array int) {\n")
     6082     (write _test-input-stream "  var b/eax: (addr array int) <- copy a\n")
     6083     (write _test-input-stream "  var c/eax: int <- length b\n")
     6084     (write _test-input-stream "}\n")
     6085     # convert
     6086     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     6087     (flush _test-output-buffered-file)
     6088 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     6094     # check output
     6095     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array/0")
     6096     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array/1")
     6097     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array/2")
     6098     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-length-of-array/3")
     6099     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array/4")
     6100     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array/5")
     6101     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-length-of-array/6")
     6102     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000000/r32"  "F - test-convert-length-of-array/7")
     6103     (check-next-stream-line-equal _test-output-stream "    8b/-> *eax 0x00000000/r32"  "F - test-convert-length-of-array/8")
     6104     (check-next-stream-line-equal _test-output-stream "    c1/shift 5/subop/>> %eax 0x00000002/imm8"  "F - test-convert-length-of-array/9")
     6105     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"  "F - test-convert-length-of-array/10")
     6106     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array/11")
     6107     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array/12")
     6108     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array/13")
     6109     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-length-of-array/14")
     6110     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-length-of-array/15")
     6111     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array/16")
     6112     # . epilogue
     6113     89/<- %esp 5/r32/ebp
     6114     5d/pop-to-ebp
     6115     c3/return
     6116
     6117 # special-case for size(byte) when computing array length
     6118 test-convert-length-of-array-of-bytes:
     6119     # . prologue
     6120     55/push-ebp
     6121     89/<- %ebp 4/r32/esp
     6122     # setup
     6123     (clear-stream _test-input-stream)
     6124     (clear-stream $_test-input-buffered-file->buffer)
     6125     (clear-stream _test-output-stream)
     6126     (clear-stream $_test-output-buffered-file->buffer)
     6127     #
     6128     (write _test-input-stream "fn foo a: (addr array byte) {\n")
     6129     (write _test-input-stream "  var b/eax: (addr array byte) <- copy a\n")
     6130     (write _test-input-stream "  var c/eax: int <- length b\n")
     6131     (write _test-input-stream "}\n")
     6132     # convert
     6133     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     6134     (flush _test-output-buffered-file)
     6135 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     6141     # check output
     6142     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array-of-bytes/0")
     6143     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array-of-bytes/1")
     6144     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array-of-bytes/2")
     6145     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-length-of-array-of-bytes/3")
     6146     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array-of-bytes/4")
     6147     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array-of-bytes/5")
     6148     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-length-of-array-of-bytes/6")
     6149     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000000/r32"  "F - test-convert-length-of-array-of-bytes/7")
     6150     (check-next-stream-line-equal _test-output-stream "    8b/-> *eax 0x00000000/r32"  "F - test-convert-length-of-array-of-bytes/8")
     6151     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"  "F - test-convert-length-of-array-of-bytes/9")
     6152     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array-of-bytes/10")
     6153     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array-of-bytes/11")
     6154     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array-of-bytes/12")
     6155     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-length-of-array-of-bytes/13")
     6156     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-length-of-array-of-bytes/14")
     6157     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array-of-bytes/15")
     6158     # . epilogue
     6159     89/<- %esp 5/r32/ebp
     6160     5d/pop-to-ebp
     6161     c3/return
     6162
     6163 test-convert-length-of-array-on-stack:
     6164     # . prologue
     6165     55/push-ebp
     6166     89/<- %ebp 4/r32/esp
     6167     # setup
     6168     (clear-stream _test-input-stream)
     6169     (clear-stream $_test-input-buffered-file->buffer)
     6170     (clear-stream _test-output-stream)
     6171     (clear-stream $_test-output-buffered-file->buffer)
     6172     #
     6173     (write _test-input-stream "fn foo {\n")
     6174     (write _test-input-stream "  var a: (array int 3)\n")
     6175     (write _test-input-stream "  var b/eax: int <- length a\n")
     6176     (write _test-input-stream "}\n")
     6177     # convert
     6178     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     6179     (flush _test-output-buffered-file)
     6180 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     6186     # check output
     6187     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array-on-stack/0")
     6188     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array-on-stack/1")
     6189     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array-on-stack/2")
     6190     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-length-of-array-on-stack/3")
     6191     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array-on-stack/4")
     6192     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array-on-stack/5")
     6193     # define x
     6194     (check-next-stream-line-equal _test-output-stream "    (push-n-zero-bytes 0x0000000c)"  "F - test-convert-length-of-array-on-stack/6")
     6195     (check-next-stream-line-equal _test-output-stream "    68/push 0x0000000c/imm32"  "F - test-convert-length-of-array-on-stack/7")
     6196     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-length-of-array-on-stack/8")
     6197     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0xfffffff0) 0x00000000/r32"  "F - test-convert-length-of-array-on-stack/9")
     6198     (check-next-stream-line-equal _test-output-stream "    c1/shift 5/subop/>> %eax 0x00000002/imm8"  "F - test-convert-length-of-array-on-stack/10")
     6199     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"  "F - test-convert-length-of-array-on-stack/11")
     6200     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000010/imm32"  "F - test-convert-length-of-array-on-stack/12")
     6201     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array-on-stack/13")
     6202     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array-on-stack/14")
     6203     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array-on-stack/15")
     6204     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-length-of-array-on-stack/16")
     6205     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-length-of-array-on-stack/17")
     6206     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array-on-stack/18")
     6207     # . epilogue
     6208     89/<- %esp 5/r32/ebp
     6209     5d/pop-to-ebp
     6210     c3/return
     6211
     6212 test-reg-var-def-with-read-of-same-register:
     6213     # . prologue
     6214     55/push-ebp
     6215     89/<- %ebp 4/r32/esp
     6216     # setup
     6217     (clear-stream _test-input-stream)
     6218     (clear-stream $_test-input-buffered-file->buffer)
     6219     (clear-stream _test-output-stream)
     6220     (clear-stream $_test-output-buffered-file->buffer)
     6221     (clear-stream _test-error-stream)
     6222     (clear-stream $_test-error-buffered-file->buffer)
     6223     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)  # bytes of args in call to convert-mu
     6224     68/push 0/imm32
     6225     68/push 0/imm32
     6226     89/<- %edx 4/r32/esp
     6227     (tailor-exit-descriptor %edx 0x10)
     6228     #
     6229     (write _test-input-stream "fn foo {\n")
     6230     (write _test-input-stream "  var x/eax: int <- copy 3\n")
     6231     (write _test-input-stream "  var y/eax: int <- add x\n")
     6232     (write _test-input-stream "}\n")
     6233     # convert
     6234     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     6235     # registers except esp could be clobbered at this point (though they shouldn't be)
     6236     # restore ed
     6237     89/<- %edx 4/r32/esp
     6238     (flush _test-output-buffered-file)
     6239     (flush _test-error-buffered-file)
     6240 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     6246 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     6252     (check-stream-equal _test-error-stream  ""  "F - test-reg-var-def-with-read-of-same-register: error stream should be empty")
     6253     # check output
     6254     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-reg-var-def-with-read-of-same-register/0")
     6255     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-reg-var-def-with-read-of-same-register/1")
     6256     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-reg-var-def-with-read-of-same-register/2")
     6257     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-reg-var-def-with-read-of-same-register/3")
     6258     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-reg-var-def-with-read-of-same-register/4")
     6259     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-reg-var-def-with-read-of-same-register/5")
     6260     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-reg-var-def-with-read-of-same-register/6")
     6261     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 3/imm32"                  "F - test-reg-var-def-with-read-of-same-register/7")
     6262     (check-next-stream-line-equal _test-output-stream "    01/add-to %eax 0x00000000/r32"           "F - test-reg-var-def-with-read-of-same-register/8")
     6263     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-reg-var-def-with-read-of-same-register/9")
     6264     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-reg-var-def-with-read-of-same-register/10")
     6265     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-reg-var-def-with-read-of-same-register/11")
     6266     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-reg-var-def-with-read-of-same-register/12")
     6267     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-reg-var-def-with-read-of-same-register/13")
     6268     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-reg-var-def-with-read-of-same-register/14")
     6269     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-reg-var-def-with-read-of-same-register/15")
     6270     # don't restore from ebp
     6271     81 0/subop/add %esp 8/imm32
     6272     # . epilogue
     6273     5d/pop-to-ebp
     6274     c3/return
     6275
     6276 test-convert-index-into-array:
     6277     # . prologue
     6278     55/push-ebp
     6279     89/<- %ebp 4/r32/esp
     6280     # setup
     6281     (clear-stream _test-input-stream)
     6282     (clear-stream $_test-input-buffered-file->buffer)
     6283     (clear-stream _test-output-stream)
     6284     (clear-stream $_test-output-buffered-file->buffer)
     6285     #
     6286     (write _test-input-stream "fn foo {\n")
     6287     (write _test-input-stream "  var arr/eax: (addr array int) <- copy 0\n")
     6288     (write _test-input-stream "  var idx/ecx: int <- copy 3\n")
     6289     (write _test-input-stream "  var x/eax: (addr int) <- index arr, idx\n")
     6290     (write _test-input-stream "}\n")
     6291     # convert
     6292     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     6293     (flush _test-output-buffered-file)
     6294 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     6300     # check output
     6301     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array/0")
     6302     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array/1")
     6303     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array/2")
     6304     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array/3")
     6305     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array/4")
     6306     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array/5")
     6307     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array/6")
     6308     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-index-into-array/7")
     6309     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-index-into-array/8")
     6310     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"                  "F - test-convert-index-into-array/9")
     6311     (check-next-stream-line-equal _test-output-stream "    (__check-mu-array-bounds %ecx 0x00000004 *eax \"foo\" \"arr\")"  "F - test-convert-index-into-array/10")
     6312     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + ecx<<0x00000002 + 4) 0x00000000/r32"  "F - test-convert-index-into-array/11")
     6313     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-index-into-array/12")
     6314     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array/13")
     6315     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array/14")
     6316     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array/15")
     6317     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array/16")
     6318     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array/17")
     6319     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array/18")
     6320     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array/19")
     6321     # . epilogue
     6322     89/<- %esp 5/r32/ebp
     6323     5d/pop-to-ebp
     6324     c3/return
     6325
     6326 test-convert-index-into-array-of-bytes:
     6327     # . prologue
     6328     55/push-ebp
     6329     89/<- %ebp 4/r32/esp
     6330     # setup
     6331     (clear-stream _test-input-stream)
     6332     (clear-stream $_test-input-buffered-file->buffer)
     6333     (clear-stream _test-output-stream)
     6334     (clear-stream $_test-output-buffered-file->buffer)
     6335     #
     6336     (write _test-input-stream "fn foo {\n")
     6337     (write _test-input-stream "  var arr/eax: (addr array byte) <- copy 0\n")
     6338     (write _test-input-stream "  var idx/ecx: int <- copy 3\n")
     6339     (write _test-input-stream "  var x/eax: (addr byte) <- index arr, idx\n")
     6340     (write _test-input-stream "}\n")
     6341     # convert
     6342     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     6343     (flush _test-output-buffered-file)
     6344 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     6350     # check output
     6351     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-of-bytes/0")
     6352     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-of-bytes/1")
     6353     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-of-bytes/2")
     6354     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-of-bytes/3")
     6355     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-of-bytes/4")
     6356     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-of-bytes/5")
     6357     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-of-bytes/6")
     6358     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-index-into-array-of-bytes/7")
     6359     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-index-into-array-of-bytes/8")
     6360     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"                  "F - test-convert-index-into-array-of-bytes/9")
     6361     (check-next-stream-line-equal _test-output-stream "    (__check-mu-array-bounds %ecx 0x00000001 *eax \"foo\" \"arr\")"  "F - test-convert-index-into-array-of-bytes/10")
     6362     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + ecx<<0x00000000 + 4) 0x00000000/r32"  "F - test-convert-index-into-array-of-bytes/11")
     6363     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-index-into-array-of-bytes/12")
     6364     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-of-bytes/13")
     6365     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-of-bytes/14")
     6366     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-of-bytes/15")
     6367     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-of-bytes/16")
     6368     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-of-bytes/17")
     6369     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-of-bytes/18")
     6370     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-of-bytes/19")
     6371     # . epilogue
     6372     89/<- %esp 5/r32/ebp
     6373     5d/pop-to-ebp
     6374     c3/return
     6375
     6376 test-convert-index-into-array-with-literal:
     6377     # . prologue
     6378     55/push-ebp
     6379     89/<- %ebp 4/r32/esp
     6380     # setup
     6381     (clear-stream _test-input-stream)
     6382     (clear-stream $_test-input-buffered-file->buffer)
     6383     (clear-stream _test-output-stream)
     6384     (clear-stream $_test-output-buffered-file->buffer)
     6385     #
     6386     (write _test-input-stream "fn foo {\n")
     6387     (write _test-input-stream "  var arr/eax: (addr array int) <- copy 0\n")
     6388     (write _test-input-stream "  var x/eax: (addr int) <- index arr, 2\n")
     6389     (write _test-input-stream "}\n")
     6390     # convert
     6391     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     6392     (flush _test-output-buffered-file)
     6393 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     6399     # check output
     6400     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-with-literal/0")
     6401     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-with-literal/1")
     6402     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-with-literal/2")
     6403     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-with-literal/3")
     6404     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-with-literal/4")
     6405     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-with-literal/5")
     6406     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-with-literal/6")
     6407     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-index-into-array-with-literal/7")
     6408     (check-next-stream-line-equal _test-output-stream "    (__check-mu-array-bounds 2 0x00000004 *eax \"foo\" \"arr\")"  "F - test-convert-index-into-array-with-literal/8")
     6409                                                                                  # 2 * 4 bytes/elem + 4 bytes for size = offset 12
     6410     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + 0x0000000c) 0x00000000/r32"  "F - test-convert-index-into-array-with-literal/9")
     6411     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-with-literal/10")
     6412     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-with-literal/11")
     6413     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-with-literal/12")
     6414     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-with-literal/13")
     6415     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-with-literal/14")
     6416     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-with-literal/15")
     6417     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-with-literal/16")
     6418     # . epilogue
     6419     89/<- %esp 5/r32/ebp
     6420     5d/pop-to-ebp
     6421     c3/return
     6422
     6423 test-convert-index-into-array-of-bytes-with-literal:
     6424     # . prologue
     6425     55/push-ebp
     6426     89/<- %ebp 4/r32/esp
     6427     # setup
     6428     (clear-stream _test-input-stream)
     6429     (clear-stream $_test-input-buffered-file->buffer)
     6430     (clear-stream _test-output-stream)
     6431     (clear-stream $_test-output-buffered-file->buffer)
     6432     #
     6433     (write _test-input-stream "fn foo {\n")
     6434     (write _test-input-stream "  var arr/eax: (addr array byte) <- copy 0\n")
     6435     (write _test-input-stream "  var x/eax: (addr byte) <- index arr, 2\n")
     6436     (write _test-input-stream "}\n")
     6437     # convert
     6438     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     6439     (flush _test-output-buffered-file)
     6440 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     6446     # check output
     6447     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-of-bytes-with-literal/0")
     6448     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-of-bytes-with-literal/1")
     6449     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-of-bytes-with-literal/2")
     6450     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-of-bytes-with-literal/3")
     6451     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-of-bytes-with-literal/4")
     6452     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-of-bytes-with-literal/5")
     6453     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-of-bytes-with-literal/6")
     6454     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-index-into-array-of-bytes-with-literal/7")
     6455     (check-next-stream-line-equal _test-output-stream "    (__check-mu-array-bounds 2 0x00000001 *eax \"foo\" \"arr\")"  "F - test-convert-index-into-array-of-bytes-with-literal/8")
     6456                                                                                  # 2 * 1 byte/elem + 4 bytes for size = offset 6
     6457     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + 0x00000006) 0x00000000/r32"  "F - test-convert-index-into-array-of-bytes-with-literal/8")
     6458     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-of-bytes-with-literal/9")
     6459     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-of-bytes-with-literal/10")
     6460     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-of-bytes-with-literal/11")
     6461     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-of-bytes-with-literal/12")
     6462     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-of-bytes-with-literal/13")
     6463     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-of-bytes-with-literal/14")
     6464     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-of-bytes-with-literal/15")
     6465     # . epilogue
     6466     89/<- %esp 5/r32/ebp
     6467     5d/pop-to-ebp
     6468     c3/return
     6469
     6470 test-convert-index-into-array-on-stack:
     6471     # . prologue
     6472     55/push-ebp
     6473     89/<- %ebp 4/r32/esp
     6474     # setup
     6475     (clear-stream _test-input-stream)
     6476     (clear-stream $_test-input-buffered-file->buffer)
     6477     (clear-stream _test-output-stream)
     6478     (clear-stream $_test-output-buffered-file->buffer)
     6479     #
     6480     (write _test-input-stream "fn foo {\n")
     6481     (write _test-input-stream "  var arr: (array int 3)\n")
     6482     (write _test-input-stream "  var idx/eax: int <- copy 2\n")
     6483     (write _test-input-stream "  var x/eax: (addr int) <- index arr, idx\n")
     6484     (write _test-input-stream "}\n")
     6485     # convert
     6486     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     6487     (flush _test-output-buffered-file)
     6488 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     6494     # check output
     6495     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-on-stack/0")
     6496     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-on-stack/1")
     6497     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-on-stack/2")
     6498     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-on-stack/3")
     6499     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-on-stack/4")
     6500     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-on-stack/5")
     6501     # var arr
     6502     (check-next-stream-line-equal _test-output-stream "    (push-n-zero-bytes 0x0000000c)"          "F - test-convert-index-into-array-on-stack/6")
     6503     (check-next-stream-line-equal _test-output-stream "    68/push 0x0000000c/imm32"                "F - test-convert-index-into-array-on-stack/7")
     6504     # var idx
     6505     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-on-stack/8")
     6506     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 2/imm32"                  "F - test-convert-index-into-array-on-stack/9")
     6507     (check-next-stream-line-equal _test-output-stream "    (__check-mu-array-bounds %eax 0x00000004 *(ebp+0xfffffff0) \"foo\" \"arr\")"  "F - test-convert-index-into-array-on-stack/10")
     6508     # var x is at (ebp-0x10) + idx<<2 + 4 = ebp + idx<<2 - 0xc
     6509     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(ebp + eax<<0x00000002 + 0xfffffff4) 0x00000000/r32"  "F - test-convert-index-into-array-on-stack/11")
     6510     # reclaim idx
     6511     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-on-stack/12")
     6512     # reclaim arr
     6513     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000010/imm32"    "F - test-convert-index-into-array-on-stack/13")
     6514     #
     6515     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-on-stack/14")
     6516     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-on-stack/15")
     6517     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-on-stack/16")
     6518     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-on-stack/17")
     6519     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-on-stack/18")
     6520     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-on-stack/19")
     6521     # . epilogue
     6522     89/<- %esp 5/r32/ebp
     6523     5d/pop-to-ebp
     6524     c3/return
     6525
     6526 test-convert-index-into-array-on-stack-with-literal:
     6527     # . prologue
     6528     55/push-ebp
     6529     89/<- %ebp 4/r32/esp
     6530     # setup
     6531     (clear-stream _test-input-stream)
     6532     (clear-stream $_test-input-buffered-file->buffer)
     6533     (clear-stream _test-output-stream)
     6534     (clear-stream $_test-output-buffered-file->buffer)
     6535     #
     6536     (write _test-input-stream "fn foo {\n")
     6537     (write _test-input-stream "  var arr: (array int 3)\n")
     6538     (write _test-input-stream "  var x/eax: (addr int) <- index arr, 2\n")
     6539     (write _test-input-stream "}\n")
     6540     # convert
     6541     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     6542     (flush _test-output-buffered-file)
     6543 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     6549     # check output
     6550     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-on-stack-with-literal/0")
     6551     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-on-stack-with-literal/1")
     6552     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-on-stack-with-literal/2")
     6553     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-on-stack-with-literal/3")
     6554     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-on-stack-with-literal/4")
     6555     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-on-stack-with-literal/5")
     6556     # var arr
     6557     (check-next-stream-line-equal _test-output-stream "    (push-n-zero-bytes 0x0000000c)"          "F - test-convert-index-into-array-on-stack-with-literal/6")
     6558     (check-next-stream-line-equal _test-output-stream "    68/push 0x0000000c/imm32"                "F - test-convert-index-into-array-on-stack-with-literal/7")
     6559     # var x
     6560     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-on-stack-with-literal/8")
     6561     (check-next-stream-line-equal _test-output-stream "    (__check-mu-array-bounds 2 0x00000004 *(ebp+0xfffffff0) \"foo\" \"arr\")"  "F - test-convert-index-into-array-on-stack-with-literal/9")
     6562     # x is at (ebp-0x10) + 4 + 2*4 = ebp-4
     6563     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(ebp + 0xfffffffc) 0x00000000/r32"  "F - test-convert-index-into-array-on-stack-with-literal/10")
     6564     # reclaim x
     6565     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-on-stack-with-literal/11")
     6566     # reclaim arr
     6567     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000010/imm32"    "F - test-convert-index-into-array-on-stack-with-literal/12")
     6568     #
     6569     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-on-stack-with-literal/13")
     6570     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-on-stack-with-literal/14")
     6571     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-on-stack-with-literal/15")
     6572     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-on-stack-with-literal/16")
     6573     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-on-stack-with-literal/17")
     6574     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-on-stack-with-literal/18")
     6575     # . epilogue
     6576     89/<- %esp 5/r32/ebp
     6577     5d/pop-to-ebp
     6578     c3/return
     6579
     6580 test-convert-index-into-array-of-bytes-on-stack-with-literal:
     6581     # . prologue
     6582     55/push-ebp
     6583     89/<- %ebp 4/r32/esp
     6584     # setup
     6585     (clear-stream _test-input-stream)
     6586     (clear-stream $_test-input-buffered-file->buffer)
     6587     (clear-stream _test-output-stream)
     6588     (clear-stream $_test-output-buffered-file->buffer)
     6589     #
     6590     (write _test-input-stream "fn foo {\n")
     6591     (write _test-input-stream "  var arr: (array byte 3)\n")
     6592     (write _test-input-stream "  var x/eax: (addr byte) <- index arr, 2\n")
     6593     (write _test-input-stream "}\n")
     6594     # convert
     6595     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     6596     (flush _test-output-buffered-file)
     6597 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     6603     # check output
     6604     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/0")
     6605     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/1")
     6606     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/2")
     6607     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/3")
     6608     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/4")
     6609     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/5")
     6610     # var arr
     6611     (check-next-stream-line-equal _test-output-stream "    (push-n-zero-bytes 0x00000003)"          "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/6")
     6612     (check-next-stream-line-equal _test-output-stream "    68/push 0x00000003/imm32"                "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/7")
     6613     # var x
     6614     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/8")
     6615     (check-next-stream-line-equal _test-output-stream "    (__check-mu-array-bounds 2 0x00000001 *(ebp+0xfffffff9) \"foo\" \"arr\")"  "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/9")
     6616     # x is at (ebp-7) + 4 + 2 = ebp-1
     6617     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(ebp + 0xffffffff) 0x00000000/r32"  "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/10")
     6618     # reclaim x
     6619     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/11")
     6620     # reclaim arr
     6621     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000007/imm32"    "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/12")
     6622     #
     6623     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/13")
     6624     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/14")
     6625     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/15")
     6626     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/16")
     6627     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/17")
     6628     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/18")
     6629     # . epilogue
     6630     89/<- %esp 5/r32/ebp
     6631     5d/pop-to-ebp
     6632     c3/return
     6633
     6634 test-convert-index-into-array-using-offset:
     6635     # . prologue
     6636     55/push-ebp
     6637     89/<- %ebp 4/r32/esp
     6638     # setup
     6639     (clear-stream _test-input-stream)
     6640     (clear-stream $_test-input-buffered-file->buffer)
     6641     (clear-stream _test-output-stream)
     6642     (clear-stream $_test-output-buffered-file->buffer)
     6643     #
     6644     (write _test-input-stream "fn foo {\n")
     6645     (write _test-input-stream "  var arr/eax: (addr array int) <- copy 0\n")
     6646     (write _test-input-stream "  var idx/ecx: int <- copy 3\n")
     6647     (write _test-input-stream "  var off/ecx: (offset int) <- compute-offset arr, idx\n")
     6648     (write _test-input-stream "  var x/eax: (addr int) <- index arr, off\n")
     6649     (write _test-input-stream "}\n")
     6650     # convert
     6651     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     6652     (flush _test-output-buffered-file)
     6653 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     6659     # check output
     6660     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-using-offset/0")
     6661     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-using-offset/1")
     6662     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-using-offset/2")
     6663     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-using-offset/3")
     6664     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-using-offset/4")
     6665     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-using-offset/5")
     6666     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-using-offset/6")
     6667     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-index-into-array-using-offset/7")
     6668     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-index-into-array-using-offset/8")
     6669     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"                  "F - test-convert-index-into-array-using-offset/9")
     6670     (check-next-stream-line-equal _test-output-stream "    69/multiply %ecx 0x00000004/imm32 0x00000001/r32"  "F - test-convert-index-into-array-using-offset/10")
     6671     (check-next-stream-line-equal _test-output-stream "    (__check-mu-array-bounds %ecx 1 *eax \"foo\" \"arr\")"  "F - test-convert-index-into-array-using-offset/11")
     6672     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + ecx + 4) 0x00000000/r32"  "F - test-convert-index-into-array-using-offset/12")
     6673     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-index-into-array-using-offset/13")
     6674     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-using-offset/14")
     6675     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-using-offset/15")
     6676     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-using-offset/16")
     6677     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-using-offset/17")
     6678     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-using-offset/18")
     6679     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-using-offset/19")
     6680     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-using-offset/20")
     6681     # . epilogue
     6682     89/<- %esp 5/r32/ebp
     6683     5d/pop-to-ebp
     6684     c3/return
     6685
     6686 test-convert-index-into-array-of-bytes-using-offset:
     6687     # . prologue
     6688     55/push-ebp
     6689     89/<- %ebp 4/r32/esp
     6690     # setup
     6691     (clear-stream _test-input-stream)
     6692     (clear-stream $_test-input-buffered-file->buffer)
     6693     (clear-stream _test-output-stream)
     6694     (clear-stream $_test-output-buffered-file->buffer)
     6695     #
     6696     (write _test-input-stream "fn foo {\n")
     6697     (write _test-input-stream "  var arr/eax: (addr array byte) <- copy 0\n")
     6698     (write _test-input-stream "  var idx/ecx: int <- copy 3\n")
     6699     (write _test-input-stream "  var off/ecx: (offset byte) <- compute-offset arr, idx\n")
     6700     (write _test-input-stream "  var x/eax: (addr byte) <- index arr, off\n")
     6701     (write _test-input-stream "}\n")
     6702     # convert
     6703     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     6704     (flush _test-output-buffered-file)
     6705 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     6711     # check output
     6712     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-of-bytes-using-offset/0")
     6713     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-of-bytes-using-offset/1")
     6714     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-of-bytes-using-offset/2")
     6715     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-of-bytes-using-offset/3")
     6716     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-of-bytes-using-offset/4")
     6717     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-of-bytes-using-offset/5")
     6718     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-of-bytes-using-offset/6")
     6719     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-index-into-array-of-bytes-using-offset/7")
     6720     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-index-into-array-of-bytes-using-offset/8")
     6721     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"                  "F - test-convert-index-into-array-of-bytes-using-offset/9")
     6722     (check-next-stream-line-equal _test-output-stream "    69/multiply %ecx 0x00000001/imm32 0x00000001/r32"  "F - test-convert-index-into-array-of-bytes-using-offset/10")
     6723     (check-next-stream-line-equal _test-output-stream "    (__check-mu-array-bounds %ecx 1 *eax \"foo\" \"arr\")"  "F - test-convert-index-into-array-of-bytes-using-offset/11")
     6724     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + ecx + 4) 0x00000000/r32"  "F - test-convert-index-into-array-of-bytes-using-offset/12")
     6725     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-index-into-array-of-bytes-using-offset/13")
     6726     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-of-bytes-using-offset/14")
     6727     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-of-bytes-using-offset/15")
     6728     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-of-bytes-using-offset/16")
     6729     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-of-bytes-using-offset/17")
     6730     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-of-bytes-using-offset/18")
     6731     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-of-bytes-using-offset/19")
     6732     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-of-bytes-using-offset/20")
     6733     # . epilogue
     6734     89/<- %esp 5/r32/ebp
     6735     5d/pop-to-ebp
     6736     c3/return
     6737
     6738 test-convert-index-into-array-using-offset-on-stack:
     6739     # . prologue
     6740     55/push-ebp
     6741     89/<- %ebp 4/r32/esp
     6742     # setup
     6743     (clear-stream _test-input-stream)
     6744     (clear-stream $_test-input-buffered-file->buffer)
     6745     (clear-stream _test-output-stream)
     6746     (clear-stream $_test-output-buffered-file->buffer)
     6747     #
     6748     (write _test-input-stream "fn foo {\n")
     6749     (write _test-input-stream "  var arr/eax: (addr array int) <- copy 0\n")
     6750     (write _test-input-stream "  var idx: int\n")
     6751     (write _test-input-stream "  var off/ecx: (offset int) <- compute-offset arr, idx\n")
     6752     (write _test-input-stream "  var x/eax: (addr int) <- index arr, off\n")
     6753     (write _test-input-stream "}\n")
     6754     # convert
     6755     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     6756     (flush _test-output-buffered-file)
     6757 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     6763     # check output
     6764     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-using-offset-on-stack/0")
     6765     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-using-offset-on-stack/1")
     6766     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-using-offset-on-stack/2")
     6767     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-using-offset-on-stack/3")
     6768     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-using-offset-on-stack/4")
     6769     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-using-offset-on-stack/5")
     6770     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-using-offset-on-stack/6")
     6771     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-index-into-array-using-offset-on-stack/7")
     6772     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"                         "F - test-convert-index-into-array-using-offset-on-stack/8")
     6773     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-index-into-array-using-offset-on-stack/9")
     6774     (check-next-stream-line-equal _test-output-stream "    69/multiply *(ebp+0xfffffff8) 0x00000004/imm32 0x00000001/r32"  "F - test-convert-index-into-array-using-offset-on-stack/10")
     6775     (check-next-stream-line-equal _test-output-stream "    (__check-mu-array-bounds %ecx 1 *eax \"foo\" \"arr\")"  "F - test-convert-index-into-array-using-offset-on-stack/11")
     6776     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + ecx + 4) 0x00000000/r32"  "F - test-convert-index-into-array-using-offset-on-stack/12")
     6777     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-index-into-array-using-offset-on-stack/13")
     6778     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"    "F - test-convert-index-into-array-using-offset-on-stack/14")
     6779     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-using-offset-on-stack/15")
     6780     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-using-offset-on-stack/16")
     6781     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-using-offset-on-stack/17")
     6782     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-using-offset-on-stack/18")
     6783     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-using-offset-on-stack/19")
     6784     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-using-offset-on-stack/20")
     6785     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-using-offset-on-stack/21")
     6786     # . epilogue
     6787     89/<- %esp 5/r32/ebp
     6788     5d/pop-to-ebp
     6789     c3/return
     6790
     6791 test-convert-index-into-array-of-bytes-using-offset-on-stack:
     6792     # . prologue
     6793     55/push-ebp
     6794     89/<- %ebp 4/r32/esp
     6795     # setup
     6796     (clear-stream _test-input-stream)
     6797     (clear-stream $_test-input-buffered-file->buffer)
     6798     (clear-stream _test-output-stream)
     6799     (clear-stream $_test-output-buffered-file->buffer)
     6800     #
     6801     (write _test-input-stream "fn foo {\n")
     6802     (write _test-input-stream "  var arr/eax: (addr array byte) <- copy 0\n")
     6803     (write _test-input-stream "  var idx: int\n")
     6804     (write _test-input-stream "  var off/ecx: (offset byte) <- compute-offset arr, idx\n")
     6805     (write _test-input-stream "  var x/eax: (addr byte) <- index arr, off\n")
     6806     (write _test-input-stream "}\n")
     6807     # convert
     6808     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     6809     (flush _test-output-buffered-file)
     6810 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     6816     # check output
     6817     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/0")
     6818     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/1")
     6819     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/2")
     6820     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/3")
     6821     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/4")
     6822     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/5")
     6823     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/6")
     6824     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/7")
     6825     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"                         "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/8")
     6826     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/9")
     6827     (check-next-stream-line-equal _test-output-stream "    69/multiply *(ebp+0xfffffff8) 0x00000001/imm32 0x00000001/r32"  "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/10")
     6828     (check-next-stream-line-equal _test-output-stream "    (__check-mu-array-bounds %ecx 1 *eax \"foo\" \"arr\")"  "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/11")
     6829     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + ecx + 4) 0x00000000/r32"  "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/12")
     6830     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/13")
     6831     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"    "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/14")
     6832     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/15")
     6833     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/16")
     6834     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/17")
     6835     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/18")
     6836     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/19")
     6837     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/20")
     6838     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/21")
     6839     # . epilogue
     6840     89/<- %esp 5/r32/ebp
     6841     5d/pop-to-ebp
     6842     c3/return
     6843
     6844 test-convert-function-and-type-definition:
     6845     # . prologue
     6846     55/push-ebp
     6847     89/<- %ebp 4/r32/esp
     6848     # setup
     6849     (clear-stream _test-input-stream)
     6850     (clear-stream $_test-input-buffered-file->buffer)
     6851     (clear-stream _test-output-stream)
     6852     (clear-stream $_test-output-buffered-file->buffer)
     6853     #
     6854     (write _test-input-stream "fn foo a: (addr t) {\n")
     6855     (write _test-input-stream "  var _a/eax: (addr t) <- copy a\n")
     6856     (write _test-input-stream "  var b/ecx: (addr int) <- get _a, x\n")
     6857     (write _test-input-stream "  var c/ecx: (addr int) <- get _a, y\n")
     6858     (write _test-input-stream "}\n")
     6859     (write _test-input-stream "type t {\n")
     6860     (write _test-input-stream "  x: int\n")
     6861     (write _test-input-stream "  y: int\n")
     6862     (write _test-input-stream "}\n")
     6863     # convert
     6864     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     6865     (flush _test-output-buffered-file)
     6866 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     6872     # check output
     6873     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-and-type-definition/0")
     6874     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-and-type-definition/1")
     6875     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-and-type-definition/2")
     6876     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-and-type-definition/3")
     6877     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-and-type-definition/4")
     6878     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-and-type-definition/5")
     6879     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-and-type-definition/6")
     6880     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000000/r32"  "F - test-convert-function-and-type-definition/7")
     6881     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-and-type-definition/8")
     6882     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + 0x00000000) 0x00000001/r32"  "F - test-convert-function-and-type-definition/9")
     6883     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + 0x00000004) 0x00000001/r32"  "F - test-convert-function-and-type-definition/11")
     6884     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-function-and-type-definition/13")
     6885     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax" "F - test-convert-function-and-type-definition/14")
     6886     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-and-type-definition/15")
     6887     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-and-type-definition/16")
     6888     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-and-type-definition/17")
     6889     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-and-type-definition/18")
     6890     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-and-type-definition/19")
     6891     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-and-type-definition/20")
     6892     # . epilogue
     6893     89/<- %esp 5/r32/ebp
     6894     5d/pop-to-ebp
     6895     c3/return
     6896
     6897 test-type-definition-with-array:
     6898     # . prologue
     6899     55/push-ebp
     6900     89/<- %ebp 4/r32/esp
     6901     # setup
     6902     (clear-stream _test-input-stream)
     6903     (clear-stream $_test-input-buffered-file->buffer)
     6904     (clear-stream _test-output-stream)
     6905     (clear-stream $_test-output-buffered-file->buffer)
     6906     (clear-stream _test-error-stream)
     6907     (clear-stream $_test-error-buffered-file->buffer)
     6908     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     6909     68/push 0/imm32
     6910     68/push 0/imm32
     6911     89/<- %edx 4/r32/esp
     6912     (tailor-exit-descriptor %edx 0x10)
     6913     #
     6914     (write _test-input-stream "type t {\n")
     6915     (write _test-input-stream "  a: (array int 3)\n")
     6916     (write _test-input-stream "}\n")
     6917     # convert
     6918     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     6919     # registers except esp clobbered at this point
     6920     # restore ed
     6921     89/<- %edx 4/r32/esp
     6922     (flush _test-output-buffered-file)
     6923     (flush _test-error-buffered-file)
     6924 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     6930     # check output
     6931     (check-stream-equal _test-output-stream  ""  "F - test-type-definition-with-array: output should be empty")
     6932     (check-next-stream-line-equal _test-error-stream  "type t: 'array' elements not allowed for now"  "F - test-type-definition-with-array: error message")
     6933     # check that stop(1) was called
     6934     (check-ints-equal *(edx+4) 2 "F - test-type-definition-with-array: exit status")
     6935     # don't restore from ebp
     6936     81 0/subop/add %esp 8/imm32
     6937     # . epilogue
     6938     5d/pop-to-ebp
     6939     c3/return
     6940
     6941 test-type-definition-with-addr:
     6942     # . prologue
     6943     55/push-ebp
     6944     89/<- %ebp 4/r32/esp
     6945     # setup
     6946     (clear-stream _test-input-stream)
     6947     (clear-stream $_test-input-buffered-file->buffer)
     6948     (clear-stream _test-output-stream)
     6949     (clear-stream $_test-output-buffered-file->buffer)
     6950     (clear-stream _test-error-stream)
     6951     (clear-stream $_test-error-buffered-file->buffer)
     6952     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     6953     68/push 0/imm32
     6954     68/push 0/imm32
     6955     89/<- %edx 4/r32/esp
     6956     (tailor-exit-descriptor %edx 0x10)
     6957     #
     6958     (write _test-input-stream "type t {\n")
     6959     (write _test-input-stream "  a: (addr int)\n")
     6960     (write _test-input-stream "}\n")
     6961     # convert
     6962     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     6963     # registers except esp clobbered at this point
     6964     # restore ed
     6965     89/<- %edx 4/r32/esp
     6966     (flush _test-output-buffered-file)
     6967     (flush _test-error-buffered-file)
     6968 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     6974     # check output
     6975     (check-stream-equal _test-output-stream  ""  "F - test-type-definition-with-addr: output should be empty")
     6976     (check-next-stream-line-equal _test-error-stream  "type t: 'addr' elements not allowed"  "F - test-type-definition-with-addr: error message")
     6977     # check that stop(1) was called
     6978     (check-ints-equal *(edx+4) 2 "F - test-type-definition-with-addr: exit status")
     6979     # don't restore from ebp
     6980     81 0/subop/add %esp 8/imm32
     6981     # . epilogue
     6982     5d/pop-to-ebp
     6983     c3/return
     6984
     6985 test-convert-function-with-local-var-with-user-defined-type:
     6986     # . prologue
     6987     55/push-ebp
     6988     89/<- %ebp 4/r32/esp
     6989     # setup
     6990     (clear-stream _test-input-stream)
     6991     (clear-stream $_test-input-buffered-file->buffer)
     6992     (clear-stream _test-output-stream)
     6993     (clear-stream $_test-output-buffered-file->buffer)
     6994     #
     6995     (write _test-input-stream "fn foo {\n")
     6996     (write _test-input-stream "  var a: t\n")
     6997     (write _test-input-stream "}\n")
     6998     (write _test-input-stream "type t {\n")
     6999     (write _test-input-stream "  x: int\n")
     7000     (write _test-input-stream "  y: int\n")
     7001     (write _test-input-stream "}\n")
     7002     # convert
     7003     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     7004     (flush _test-output-buffered-file)
     7005 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     7011     # check output
     7012     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-with-user-defined-type/0")
     7013     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-with-user-defined-type/1")
     7014     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-with-user-defined-type/2")
     7015     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-with-user-defined-type/3")
     7016     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-with-user-defined-type/4")
     7017     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-with-user-defined-type/5")
     7018     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-with-local-var-with-user-defined-type/6")
     7019     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-with-local-var-with-user-defined-type/7")
     7020     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000008/imm32"  "F - test-convert-function-with-local-var-with-user-defined-type/8")
     7021     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-with-user-defined-type/9")
     7022     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-with-user-defined-type/10")
     7023     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-with-user-defined-type/11")
     7024     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-with-user-defined-type/12")
     7025     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-with-user-defined-type/13")
     7026     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-with-user-defined-type/14")
     7027     # . epilogue
     7028     89/<- %esp 5/r32/ebp
     7029     5d/pop-to-ebp
     7030     c3/return
     7031
     7032 test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type:
     7033     # . prologue
     7034     55/push-ebp
     7035     89/<- %ebp 4/r32/esp
     7036     # setup
     7037     (clear-stream _test-input-stream)
     7038     (clear-stream $_test-input-buffered-file->buffer)
     7039     (clear-stream _test-output-stream)
     7040     (clear-stream $_test-output-buffered-file->buffer)
     7041     #
     7042     (write _test-input-stream "fn foo {\n")
     7043     (write _test-input-stream "  var a: t\n")
     7044     (write _test-input-stream "}\n")
     7045     (write _test-input-stream "type t {\n")
     7046     (write _test-input-stream "  x: s\n")
     7047     (write _test-input-stream "}\n")
     7048     (write _test-input-stream "type s {\n")
     7049     (write _test-input-stream "  z: int\n")
     7050     (write _test-input-stream "}\n")
     7051     # convert
     7052     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     7053     (flush _test-output-buffered-file)
     7054 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     7060     # check output
     7061     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type/0")
     7062     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type/1")
     7063     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type/2")
     7064     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type/3")
     7065     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type/4")
     7066     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type/5")
     7067     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type/7")
     7068     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type/8")
     7069     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type/9")
     7070     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type/10")
     7071     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type/11")
     7072     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type/12")
     7073     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type/13")
     7074     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type/14")
     7075     # . epilogue
     7076     89/<- %esp 5/r32/ebp
     7077     5d/pop-to-ebp
     7078     c3/return
     7079
     7080 test-convert-function-call-with-arg-of-user-defined-type:
     7081     # . prologue
     7082     55/push-ebp
     7083     89/<- %ebp 4/r32/esp
     7084     # setup
     7085     (clear-stream _test-input-stream)
     7086     (clear-stream $_test-input-buffered-file->buffer)
     7087     (clear-stream _test-output-stream)
     7088     (clear-stream $_test-output-buffered-file->buffer)
     7089     #
     7090     (write _test-input-stream "fn f {\n")
     7091     (write _test-input-stream "  var a: t\n")
     7092     (write _test-input-stream "  foo a\n")
     7093     (write _test-input-stream "}\n")
     7094     (write _test-input-stream "fn foo x: t {\n")
     7095     (write _test-input-stream "}\n")
     7096     (write _test-input-stream "type t {\n")
     7097     (write _test-input-stream "  x: int\n")
     7098     (write _test-input-stream "  y: int\n")
     7099     (write _test-input-stream "}\n")
     7100     # convert
     7101     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     7102     (flush _test-output-buffered-file)
     7103 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     7109     # check output
     7110     (check-next-stream-line-equal _test-output-stream "f:"                      "F - test-convert-function-call-with-arg-of-user-defined-type/0")
     7111     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-arg-of-user-defined-type/1")
     7112     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-arg-of-user-defined-type/2")
     7113     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call-with-arg-of-user-defined-type/3")
     7114     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-arg-of-user-defined-type/4")
     7115     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:loop:"     "F - test-convert-function-call-with-arg-of-user-defined-type/5")
     7116     # var a: t
     7117     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-call-with-arg-of-user-defined-type/6")
     7118     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-call-with-arg-of-user-defined-type/7")
     7119     # foo a
     7120     (check-next-stream-line-equal _test-output-stream "    (foo *(ebp+0xfffffff8) *(ebp+0xfffffffc))"  "F - test-convert-function-call-with-arg-of-user-defined-type/8")
     7121     #
     7122     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000008/imm32"  "F - test-convert-function-call-with-arg-of-user-defined-type/9")
     7123     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-arg-of-user-defined-type/10")
     7124     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:break:"    "F - test-convert-function-call-with-arg-of-user-defined-type/11")
     7125     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-arg-of-user-defined-type/12")
     7126     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call-with-arg-of-user-defined-type/13")
     7127     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-arg-of-user-defined-type/14")
     7128     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-arg-of-user-defined-type/15")
     7129     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-call-with-arg-of-user-defined-type/16")
     7130     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-arg-of-user-defined-type/17")
     7131     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-arg-of-user-defined-type/18")
     7132     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call-with-arg-of-user-defined-type/19")
     7133     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-arg-of-user-defined-type/20")
     7134     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call-with-arg-of-user-defined-type/21")
     7135     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-arg-of-user-defined-type/22")
     7136     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-arg-of-user-defined-type/23")
     7137     # . epilogue
     7138     89/<- %esp 5/r32/ebp
     7139     5d/pop-to-ebp
     7140     c3/return
     7141
     7142 test-convert-function-call-with-arg-of-user-defined-type-register-indirect:
     7143     # . prologue
     7144     55/push-ebp
     7145     89/<- %ebp 4/r32/esp
     7146     # setup
     7147     (clear-stream _test-input-stream)
     7148     (clear-stream $_test-input-buffered-file->buffer)
     7149     (clear-stream _test-output-stream)
     7150     (clear-stream $_test-output-buffered-file->buffer)
     7151     #
     7152     (write _test-input-stream "fn f {\n")
     7153     (write _test-input-stream "  var a/eax: (addr t) <- copy 0\n")
     7154     (write _test-input-stream "  foo *a\n")
     7155     (write _test-input-stream "}\n")
     7156     (write _test-input-stream "fn foo x: t {\n")
     7157     (write _test-input-stream "}\n")
     7158     (write _test-input-stream "type t {\n")
     7159     (write _test-input-stream "  x: int\n")
     7160     (write _test-input-stream "  y: int\n")
     7161     (write _test-input-stream "}\n")
     7162     # convert
     7163     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     7164     (flush _test-output-buffered-file)
     7165 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     7171     # check output
     7172     (check-next-stream-line-equal _test-output-stream "f:"                      "F - test-convert-function-call-with-arg-of-user-defined-type/0")
     7173     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-arg-of-user-defined-type/1")
     7174     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-arg-of-user-defined-type/2")
     7175     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call-with-arg-of-user-defined-type/3")
     7176     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-arg-of-user-defined-type/4")
     7177     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:loop:"     "F - test-convert-function-call-with-arg-of-user-defined-type/5")
     7178     # var a
     7179     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-call-with-arg-of-user-defined-type/6")
     7180     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"  "F - test-convert-function-call-with-arg-of-user-defined-type/7")
     7181     # foo a
     7182     (check-next-stream-line-equal _test-output-stream "    (foo *(eax+0x00000000) *(eax+0x00000004))"  "F - test-convert-function-call-with-arg-of-user-defined-type/8")
     7183     #
     7184     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax" "F - test-convert-function-call-with-arg-of-user-defined-type/9")
     7185     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-arg-of-user-defined-type/10")
     7186     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:break:"    "F - test-convert-function-call-with-arg-of-user-defined-type/11")
     7187     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-arg-of-user-defined-type/12")
     7188     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call-with-arg-of-user-defined-type/13")
     7189     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-arg-of-user-defined-type/14")
     7190     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-arg-of-user-defined-type/15")
     7191     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-call-with-arg-of-user-defined-type/16")
     7192     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-arg-of-user-defined-type/17")
     7193     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-arg-of-user-defined-type/18")
     7194     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call-with-arg-of-user-defined-type/19")
     7195     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-arg-of-user-defined-type/20")
     7196     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call-with-arg-of-user-defined-type/21")
     7197     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-arg-of-user-defined-type/22")
     7198     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-arg-of-user-defined-type/23")
     7199     # . epilogue
     7200     89/<- %esp 5/r32/ebp
     7201     5d/pop-to-ebp
     7202     c3/return
     7203
     7204 # we don't have special support for call-by-reference; just explicitly create
     7205 # a new variable with the address of the arg
     7206 test-convert-function-call-with-arg-of-user-defined-type-by-reference:
     7207     # . prologue
     7208     55/push-ebp
     7209     89/<- %ebp 4/r32/esp
     7210     # setup
     7211     (clear-stream _test-input-stream)
     7212     (clear-stream $_test-input-buffered-file->buffer)
     7213     (clear-stream _test-output-stream)
     7214     (clear-stream $_test-output-buffered-file->buffer)
     7215     #
     7216     (write _test-input-stream "fn f {\n")
     7217     (write _test-input-stream "  var a: t\n")
     7218     (write _test-input-stream "  var b/eax: (addr t) <- address a\n")
     7219     (write _test-input-stream "  foo b\n")
     7220     (write _test-input-stream "}\n")
     7221     (write _test-input-stream "fn foo x: (addr t) {\n")
     7222     (write _test-input-stream "  var x/ecx: (addr t) <- copy x\n")
     7223     (write _test-input-stream "}\n")
     7224     (write _test-input-stream "type t {\n")
     7225     (write _test-input-stream "  x: int\n")
     7226     (write _test-input-stream "  y: int\n")
     7227     (write _test-input-stream "}\n")
     7228     # convert
     7229     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     7230     (flush _test-output-buffered-file)
     7231 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     7237     # check output
     7238     (check-next-stream-line-equal _test-output-stream "f:"                      "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/0")
     7239     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/1")
     7240     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/2")
     7241     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/3")
     7242     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/4")
     7243     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:loop:"     "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/5")
     7244     # var a: t
     7245     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/6")
     7246     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/7")
     7247     # var b/eax: (addr t)
     7248     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/8")
     7249     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(ebp+0xfffffff8) 0x00000000/r32"  "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/9")
     7250     # foo a
     7251     (check-next-stream-line-equal _test-output-stream "    (foo %eax)"          "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/10")
     7252     #
     7253     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/11")
     7254     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000008/imm32"  "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/12")
     7255     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/13")
     7256     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:break:"    "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/14")
     7257     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/15")
     7258     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/16")
     7259     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/17")
     7260     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/18")
     7261     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/19")
     7262     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/20")
     7263     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/21")
     7264     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/22")
     7265     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/23")
     7266     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/24")
     7267     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/25")
     7268     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000001/r32"  "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/26")
     7269     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/27")
     7270     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/28")
     7271     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/29")
     7272     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/30")
     7273     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/31")
     7274     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/32")
     7275     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/33")
     7276     # . epilogue
     7277     89/<- %esp 5/r32/ebp
     7278     5d/pop-to-ebp
     7279     c3/return
     7280
     7281 test-convert-get-on-local-variable:
     7282     # . prologue
     7283     55/push-ebp
     7284     89/<- %ebp 4/r32/esp
     7285     # setup
     7286     (clear-stream _test-input-stream)
     7287     (clear-stream $_test-input-buffered-file->buffer)
     7288     (clear-stream _test-output-stream)
     7289     (clear-stream $_test-output-buffered-file->buffer)
     7290     #
     7291     (write _test-input-stream "fn foo {\n")
     7292     (write _test-input-stream "  var a: t\n")
     7293     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
     7294     (write _test-input-stream "}\n")
     7295     (write _test-input-stream "type t {\n")
     7296     (write _test-input-stream "  x: int\n")
     7297     (write _test-input-stream "  y: int\n")
     7298     (write _test-input-stream "}\n")
     7299     # convert
     7300     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     7301     (flush _test-output-buffered-file)
     7302 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     7308     # check output
     7309     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-get-on-local-variable/0")
     7310     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-get-on-local-variable/1")
     7311     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-get-on-local-variable/2")
     7312     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-get-on-local-variable/3")
     7313     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-get-on-local-variable/4")
     7314     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-get-on-local-variable/5")
     7315     # var a
     7316     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-get-on-local-variable/6")
     7317     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-get-on-local-variable/7")
     7318     # var c
     7319     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-get-on-local-variable/8")
     7320     # get
     7321     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(ebp+0xfffffffc) 0x00000001/r32"  "F - test-convert-get-on-local-variable/9")
     7322     # reclaim c
     7323     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-get-on-local-variable/10")
     7324     # reclaim a
     7325     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000008/imm32"  "F - test-convert-get-on-local-variable/11")
     7326     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-get-on-local-variable/12")
     7327     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-get-on-local-variable/13")
     7328     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-get-on-local-variable/14")
     7329     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-get-on-local-variable/15")
     7330     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-get-on-local-variable/16")
     7331     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-get-on-local-variable/17")
     7332     # . epilogue
     7333     89/<- %esp 5/r32/ebp
     7334     5d/pop-to-ebp
     7335     c3/return
     7336
     7337 test-convert-get-on-function-argument:
     7338     # . prologue
     7339     55/push-ebp
     7340     89/<- %ebp 4/r32/esp
     7341     # setup
     7342     (clear-stream _test-input-stream)
     7343     (clear-stream $_test-input-buffered-file->buffer)
     7344     (clear-stream _test-output-stream)
     7345     (clear-stream $_test-output-buffered-file->buffer)
     7346     #
     7347     (write _test-input-stream "fn foo a: t {\n")
     7348     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
     7349     (write _test-input-stream "}\n")
     7350     (write _test-input-stream "type t {\n")
     7351     (write _test-input-stream "  x: int\n")
     7352     (write _test-input-stream "  y: int\n")
     7353     (write _test-input-stream "}\n")
     7354     # convert
     7355     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     7356     (flush _test-output-buffered-file)
     7357 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     7363     # check output
     7364     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-get-on-function-argument/0")
     7365     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-get-on-function-argument/1")
     7366     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-get-on-function-argument/2")
     7367     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-get-on-function-argument/3")
     7368     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-get-on-function-argument/4")
     7369     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-get-on-function-argument/5")
     7370     # var c
     7371     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-get-on-function-argument/6")
     7372     # get
     7373     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(ebp+0x0000000c) 0x00000001/r32"  "F - test-convert-get-on-function-argument/7")
     7374     # reclaim c
     7375     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-get-on-function-argument/8")
     7376     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-get-on-function-argument/9")
     7377     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-get-on-function-argument/10")
     7378     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-get-on-function-argument/11")
     7379     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-get-on-function-argument/12")
     7380     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-get-on-function-argument/13")
     7381     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-get-on-function-argument/14")
     7382     # . epilogue
     7383     89/<- %esp 5/r32/ebp
     7384     5d/pop-to-ebp
     7385     c3/return
     7386
     7387 test-convert-get-on-function-argument-with-known-type:
     7388     # . prologue
     7389     55/push-ebp
     7390     89/<- %ebp 4/r32/esp
     7391     # setup
     7392     (clear-stream _test-input-stream)
     7393     (clear-stream $_test-input-buffered-file->buffer)
     7394     (clear-stream _test-output-stream)
     7395     (clear-stream $_test-output-buffered-file->buffer)
     7396     #
     7397     (write _test-input-stream "type t {\n")
     7398     (write _test-input-stream "  x: int\n")
     7399     (write _test-input-stream "  y: int\n")
     7400     (write _test-input-stream "}\n")
     7401     (write _test-input-stream "fn foo a: t {\n")
     7402     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
     7403     (write _test-input-stream "}\n")
     7404     # convert
     7405     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     7406     (flush _test-output-buffered-file)
     7407 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     7413     # check output
     7414     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-get-on-function-argument-with-known-type/0")
     7415     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-get-on-function-argument-with-known-type/1")
     7416     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-get-on-function-argument-with-known-type/2")
     7417     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-get-on-function-argument-with-known-type/3")
     7418     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-get-on-function-argument-with-known-type/4")
     7419     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-get-on-function-argument-with-known-type/5")
     7420     # var c
     7421     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-get-on-function-argument-with-known-type/6")
     7422     # get
     7423     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(ebp+0x0000000c) 0x00000001/r32"  "F - test-convert-get-on-function-argument-with-known-type/7")
     7424     # reclaim c
     7425     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-get-on-function-argument-with-known-type/8")
     7426     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-get-on-function-argument-with-known-type/9")
     7427     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-get-on-function-argument-with-known-type/10")
     7428     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-get-on-function-argument-with-known-type/11")
     7429     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-get-on-function-argument-with-known-type/12")
     7430     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-get-on-function-argument-with-known-type/13")
     7431     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-get-on-function-argument-with-known-type/14")
     7432     # . epilogue
     7433     89/<- %esp 5/r32/ebp
     7434     5d/pop-to-ebp
     7435     c3/return
     7436
     7437 test-add-with-too-many-inouts:
     7438     # . prologue
     7439     55/push-ebp
     7440     89/<- %ebp 4/r32/esp
     7441     # setup
     7442     (clear-stream _test-input-stream)
     7443     (clear-stream $_test-input-buffered-file->buffer)
     7444     (clear-stream _test-output-stream)
     7445     (clear-stream $_test-output-buffered-file->buffer)
     7446     (clear-stream _test-error-stream)
     7447     (clear-stream $_test-error-buffered-file->buffer)
     7448     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     7449     68/push 0/imm32
     7450     68/push 0/imm32
     7451     89/<- %edx 4/r32/esp
     7452     (tailor-exit-descriptor %edx 0x10)
     7453     #
     7454     (write _test-input-stream "fn foo {\n")
     7455     (write _test-input-stream "  var a: int\n")
     7456     (write _test-input-stream "  var b/ecx: int <- add a, 0\n")
     7457     (write _test-input-stream "}\n")
     7458     # convert
     7459     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     7460     # registers except esp clobbered at this point
     7461     # restore ed
     7462     89/<- %edx 4/r32/esp
     7463     (flush _test-output-buffered-file)
     7464     (flush _test-error-buffered-file)
     7465 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     7471     # check output
     7472     (check-stream-equal _test-output-stream  ""  "F - test-add-with-too-many-inouts: output should be empty")
     7473     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt add: too many inouts; most primitives support at most two arguments, across inouts and outputs"  "F - test-add-with-too-many-inouts: error message")
     7474     # check that stop(1) was called
     7475     (check-ints-equal *(edx+4) 2 "F - test-add-with-too-many-inouts: exit status")
     7476     # don't restore from ebp
     7477     81 0/subop/add %esp 8/imm32
     7478     # . epilogue
     7479     5d/pop-to-ebp
     7480     c3/return
     7481
     7482 test-add-with-too-many-inouts-2:
     7483     # . prologue
     7484     55/push-ebp
     7485     89/<- %ebp 4/r32/esp
     7486     # setup
     7487     (clear-stream _test-input-stream)
     7488     (clear-stream $_test-input-buffered-file->buffer)
     7489     (clear-stream _test-output-stream)
     7490     (clear-stream $_test-output-buffered-file->buffer)
     7491     (clear-stream _test-error-stream)
     7492     (clear-stream $_test-error-buffered-file->buffer)
     7493     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     7494     68/push 0/imm32
     7495     68/push 0/imm32
     7496     89/<- %edx 4/r32/esp
     7497     (tailor-exit-descriptor %edx 0x10)
     7498     #
     7499     (write _test-input-stream "fn foo {\n")
     7500     (write _test-input-stream "  var a: int\n")
     7501     (write _test-input-stream "  add-to a, 0, 1\n")
     7502     (write _test-input-stream "}\n")
     7503     # convert
     7504     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     7505     # registers except esp clobbered at this point
     7506     # restore ed
     7507     89/<- %edx 4/r32/esp
     7508     (flush _test-output-buffered-file)
     7509     (flush _test-error-buffered-file)
     7510 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     7516     # check output
     7517     (check-stream-equal _test-output-stream  ""  "F - test-add-with-too-many-inouts-2: output should be empty")
     7518     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt add-to: too many inouts; most primitives support at most two arguments, across inouts and outputs"  "F - test-add-with-too-many-inouts-2: error message")
     7519     # check that stop(1) was called
     7520     (check-ints-equal *(edx+4) 2 "F - test-add-with-too-many-inouts-2: exit status")
     7521     # don't restore from ebp
     7522     81 0/subop/add %esp 8/imm32
     7523     # . epilogue
     7524     5d/pop-to-ebp
     7525     c3/return
     7526
     7527 test-add-with-too-many-outputs:
     7528     # . prologue
     7529     55/push-ebp
     7530     89/<- %ebp 4/r32/esp
     7531     # setup
     7532     (clear-stream _test-input-stream)
     7533     (clear-stream $_test-input-buffered-file->buffer)
     7534     (clear-stream _test-output-stream)
     7535     (clear-stream $_test-output-buffered-file->buffer)
     7536     (clear-stream _test-error-stream)
     7537     (clear-stream $_test-error-buffered-file->buffer)
     7538     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     7539     68/push 0/imm32
     7540     68/push 0/imm32
     7541     89/<- %edx 4/r32/esp
     7542     (tailor-exit-descriptor %edx 0x10)
     7543     #
     7544     (write _test-input-stream "fn foo {\n")
     7545     (write _test-input-stream "  var a/eax: int <- copy 0\n")
     7546     (write _test-input-stream "  var b/ebx: int <- copy 0\n")
     7547     (write _test-input-stream "  var c/ecx: int <- copy 0\n")
     7548     (write _test-input-stream "  c, b <- add a\n")
     7549     (write _test-input-stream "}\n")
     7550     # convert
     7551     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     7552     # registers except esp clobbered at this point
     7553     # restore ed
     7554     89/<- %edx 4/r32/esp
     7555     (flush _test-output-buffered-file)
     7556     (flush _test-error-buffered-file)
     7557 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     7563     # check output
     7564     (check-stream-equal _test-output-stream  ""  "F - test-add-with-too-many-outputs: output should be empty")
     7565     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt add: too many outputs; most primitives support at most one output"  "F - test-add-with-too-many-outputs: error message")
     7566     # check that stop(1) was called
     7567     (check-ints-equal *(edx+4) 2 "F - test-add-with-too-many-outputs: exit status")
     7568     # don't restore from ebp
     7569     81 0/subop/add %esp 8/imm32
     7570     # . epilogue
     7571     5d/pop-to-ebp
     7572     c3/return
     7573
     7574 test-add-with-non-number:
     7575     # . prologue
     7576     55/push-ebp
     7577     89/<- %ebp 4/r32/esp
     7578     # setup
     7579     (clear-stream _test-input-stream)
     7580     (clear-stream $_test-input-buffered-file->buffer)
     7581     (clear-stream _test-output-stream)
     7582     (clear-stream $_test-output-buffered-file->buffer)
     7583     (clear-stream _test-error-stream)
     7584     (clear-stream $_test-error-buffered-file->buffer)
     7585     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     7586     68/push 0/imm32
     7587     68/push 0/imm32
     7588     89/<- %edx 4/r32/esp
     7589     (tailor-exit-descriptor %edx 0x10)
     7590     #
     7591     (write _test-input-stream "fn foo {\n")
     7592     (write _test-input-stream "  var a: int\n")
     7593     (write _test-input-stream "  var b/ecx: (addr int) <- add a\n")
     7594     (write _test-input-stream "}\n")
     7595     # convert
     7596     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     7597     # registers except esp clobbered at this point
     7598     # restore ed
     7599     89/<- %edx 4/r32/esp
     7600     (flush _test-output-buffered-file)
     7601     (flush _test-error-buffered-file)
     7602 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     7608     # check output
     7609     (check-stream-equal _test-output-stream  ""  "F - test-add-with-non-number: output should be empty")
     7610     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt add: 'b' must be a non-addr non-offset scalar"  "F - test-add-with-non-number: error message")
     7611     # check that stop(1) was called
     7612     (check-ints-equal *(edx+4) 2 "F - test-add-with-non-number: exit status")
     7613     # don't restore from ebp
     7614     81 0/subop/add %esp 8/imm32
     7615     # . epilogue
     7616     5d/pop-to-ebp
     7617     c3/return
     7618
     7619 test-add-with-addr-dereferenced:
     7620     # . prologue
     7621     55/push-ebp
     7622     89/<- %ebp 4/r32/esp
     7623     # setup
     7624     (clear-stream _test-input-stream)
     7625     (clear-stream $_test-input-buffered-file->buffer)
     7626     (clear-stream _test-output-stream)
     7627     (clear-stream $_test-output-buffered-file->buffer)
     7628     #
     7629     (write _test-input-stream "fn foo {\n")
     7630     (write _test-input-stream "  var a/eax: (addr int) <- copy 0\n")
     7631     (write _test-input-stream "  add-to *a, 1\n")
     7632     (write _test-input-stream "}\n")
     7633     # convert
     7634     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     7635     (flush _test-output-buffered-file)
     7636     # no error
     7637     # . epilogue
     7638     89/<- %esp 5/r32/ebp
     7639     5d/pop-to-ebp
     7640     c3/return
     7641
     7642 test-copy-with-no-inout:
     7643     # . prologue
     7644     55/push-ebp
     7645     89/<- %ebp 4/r32/esp
     7646     # setup
     7647     (clear-stream _test-input-stream)
     7648     (clear-stream $_test-input-buffered-file->buffer)
     7649     (clear-stream _test-output-stream)
     7650     (clear-stream $_test-output-buffered-file->buffer)
     7651     (clear-stream _test-error-stream)
     7652     (clear-stream $_test-error-buffered-file->buffer)
     7653     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     7654     68/push 0/imm32
     7655     68/push 0/imm32
     7656     89/<- %edx 4/r32/esp
     7657     (tailor-exit-descriptor %edx 0x10)
     7658     #
     7659     (write _test-input-stream "fn foo {\n")
     7660     (write _test-input-stream "  var x/eax: boolean <- copy\n")
     7661     (write _test-input-stream "}\n")
     7662     # convert
     7663     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     7664     # registers except esp clobbered at this point
     7665     # restore ed
     7666     89/<- %edx 4/r32/esp
     7667     (flush _test-output-buffered-file)
     7668     (flush _test-error-buffered-file)
     7669 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     7675     # check output
     7676     (check-stream-equal _test-output-stream  ""  "F - test-copy-with-no-inout: output should be empty")
     7677     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy' expects an inout"  "F - test-copy-with-no-inout: error message")
     7678     # check that stop(1) was called
     7679     (check-ints-equal *(edx+4) 2 "F - test-copy-with-no-inout: exit status")
     7680     # don't restore from ebp
     7681     81 0/subop/add %esp 8/imm32
     7682     # . epilogue
     7683     5d/pop-to-ebp
     7684     c3/return
     7685
     7686 test-copy-with-multiple-inouts:
     7687     # . prologue
     7688     55/push-ebp
     7689     89/<- %ebp 4/r32/esp
     7690     # setup
     7691     (clear-stream _test-input-stream)
     7692     (clear-stream $_test-input-buffered-file->buffer)
     7693     (clear-stream _test-output-stream)
     7694     (clear-stream $_test-output-buffered-file->buffer)
     7695     (clear-stream _test-error-stream)
     7696     (clear-stream $_test-error-buffered-file->buffer)
     7697     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     7698     68/push 0/imm32
     7699     68/push 0/imm32
     7700     89/<- %edx 4/r32/esp
     7701     (tailor-exit-descriptor %edx 0x10)
     7702     #
     7703     (write _test-input-stream "fn foo {\n")
     7704     (write _test-input-stream "  var x/eax: boolean <- copy 0, 0\n")
     7705     (write _test-input-stream "}\n")
     7706     # convert
     7707     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     7708     # registers except esp clobbered at this point
     7709     # restore ed
     7710     89/<- %edx 4/r32/esp
     7711     (flush _test-output-buffered-file)
     7712     (flush _test-error-buffered-file)
     7713 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     7719     # check output
     7720     (check-stream-equal _test-output-stream  ""  "F - test-copy-with-multiple-inouts: output should be empty")
     7721     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy' must have just one inout"  "F - test-copy-with-multiple-inouts: error message")
     7722     # check that stop(1) was called
     7723     (check-ints-equal *(edx+4) 2 "F - test-copy-with-multiple-inouts: exit status")
     7724     # don't restore from ebp
     7725     81 0/subop/add %esp 8/imm32
     7726     # . epilogue
     7727     5d/pop-to-ebp
     7728     c3/return
     7729
     7730 test-copy-with-no-output:
     7731     # . prologue
     7732     55/push-ebp
     7733     89/<- %ebp 4/r32/esp
     7734     # setup
     7735     (clear-stream _test-input-stream)
     7736     (clear-stream $_test-input-buffered-file->buffer)
     7737     (clear-stream _test-output-stream)
     7738     (clear-stream $_test-output-buffered-file->buffer)
     7739     (clear-stream _test-error-stream)
     7740     (clear-stream $_test-error-buffered-file->buffer)
     7741     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     7742     68/push 0/imm32
     7743     68/push 0/imm32
     7744     89/<- %edx 4/r32/esp
     7745     (tailor-exit-descriptor %edx 0x10)
     7746     #
     7747     (write _test-input-stream "fn foo {\n")
     7748     (write _test-input-stream "  copy 0\n")
     7749     (write _test-input-stream "}\n")
     7750     # convert
     7751     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     7752     # registers except esp clobbered at this point
     7753     # restore ed
     7754     89/<- %edx 4/r32/esp
     7755     (flush _test-output-buffered-file)
     7756     (flush _test-error-buffered-file)
     7757 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     7763     # check output
     7764     (check-stream-equal _test-output-stream  ""  "F - test-copy-with-no-output: output should be empty")
     7765     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy' expects an output"  "F - test-copy-with-no-output: error message")
     7766     # check that stop(1) was called
     7767     (check-ints-equal *(edx+4) 2 "F - test-copy-with-no-output: exit status")
     7768     # don't restore from ebp
     7769     81 0/subop/add %esp 8/imm32
     7770     # . epilogue
     7771     5d/pop-to-ebp
     7772     c3/return
     7773
     7774 test-copy-with-multiple-outputs:
     7775     # . prologue
     7776     55/push-ebp
     7777     89/<- %ebp 4/r32/esp
     7778     # setup
     7779     (clear-stream _test-input-stream)
     7780     (clear-stream $_test-input-buffered-file->buffer)
     7781     (clear-stream _test-output-stream)
     7782     (clear-stream $_test-output-buffered-file->buffer)
     7783     (clear-stream _test-error-stream)
     7784     (clear-stream $_test-error-buffered-file->buffer)
     7785     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     7786     68/push 0/imm32
     7787     68/push 0/imm32
     7788     89/<- %edx 4/r32/esp
     7789     (tailor-exit-descriptor %edx 0x10)
     7790     #
     7791     (write _test-input-stream "fn foo {\n")
     7792     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
     7793     (write _test-input-stream "  var y/ecx: boolean <- copy 0\n")
     7794     (write _test-input-stream "  x, y <- copy 0\n")
     7795     (write _test-input-stream "}\n")
     7796     # convert
     7797     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     7798     # registers except esp clobbered at this point
     7799     # restore ed
     7800     89/<- %edx 4/r32/esp
     7801     (flush _test-output-buffered-file)
     7802     (flush _test-error-buffered-file)
     7803 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     7809     # check output
     7810     (check-stream-equal _test-output-stream  ""  "F - test-copy-with-multiple-outputs: output should be empty")
     7811     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy' must have just one output"  "F - test-copy-with-multiple-outputs: error message")
     7812     # check that stop(1) was called
     7813     (check-ints-equal *(edx+4) 2 "F - test-copy-with-multiple-outputs: exit status")
     7814     # don't restore from ebp
     7815     81 0/subop/add %esp 8/imm32
     7816     # . epilogue
     7817     5d/pop-to-ebp
     7818     c3/return
     7819
     7820 test-copy-invalid-value-to-address:
     7821     # . prologue
     7822     55/push-ebp
     7823     89/<- %ebp 4/r32/esp
     7824     # setup
     7825     (clear-stream _test-input-stream)
     7826     (clear-stream $_test-input-buffered-file->buffer)
     7827     (clear-stream _test-output-stream)
     7828     (clear-stream $_test-output-buffered-file->buffer)
     7829     (clear-stream _test-error-stream)
     7830     (clear-stream $_test-error-buffered-file->buffer)
     7831     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     7832     68/push 0/imm32
     7833     68/push 0/imm32
     7834     89/<- %edx 4/r32/esp
     7835     (tailor-exit-descriptor %edx 0x10)
     7836     #
     7837     (write _test-input-stream "fn foo {\n")
     7838     (write _test-input-stream "  var x/eax: int <- copy 0\n")
     7839     (write _test-input-stream "  var y/ecx: (addr int) <- copy x\n")
     7840     (write _test-input-stream "}\n")
     7841     # convert
     7842     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     7843     # registers except esp clobbered at this point
     7844     # restore ed
     7845     89/<- %edx 4/r32/esp
     7846     (flush _test-output-buffered-file)
     7847     (flush _test-error-buffered-file)
     7848 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     7854     # check output
     7855     (check-stream-equal _test-output-stream  ""  "F - test-copy-invalid-value-to-address: output should be empty")
     7856     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt copy: 'y' must be a non-addr non-offset scalar"  "F - test-copy-invalid-value-to-address: error message")
     7857     # check that stop(1) was called
     7858     (check-ints-equal *(edx+4) 2 "F - test-copy-invalid-value-to-address: exit status")
     7859     # don't restore from ebp
     7860     81 0/subop/add %esp 8/imm32
     7861     # . epilogue
     7862     5d/pop-to-ebp
     7863     c3/return
     7864
     7865 test-copy-null-value-to-address:
     7866     # . prologue
     7867     55/push-ebp
     7868     89/<- %ebp 4/r32/esp
     7869     # setup
     7870     (clear-stream _test-input-stream)
     7871     (clear-stream $_test-input-buffered-file->buffer)
     7872     (clear-stream _test-output-stream)
     7873     (clear-stream $_test-output-buffered-file->buffer)
     7874     #
     7875     (write _test-input-stream "fn foo {\n")
     7876     (write _test-input-stream "  var y/ecx: (addr int) <- copy 0\n")
     7877     (write _test-input-stream "}\n")
     7878     # convert
     7879     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     7880     (flush _test-output-buffered-file)
     7881     # no errors
     7882     # . epilogue
     7883     89/<- %esp 5/r32/ebp
     7884     5d/pop-to-ebp
     7885     c3/return
     7886
     7887 test-copy-invalid-value-to-offset:
     7888     # . prologue
     7889     55/push-ebp
     7890     89/<- %ebp 4/r32/esp
     7891     # setup
     7892     (clear-stream _test-input-stream)
     7893     (clear-stream $_test-input-buffered-file->buffer)
     7894     (clear-stream _test-output-stream)
     7895     (clear-stream $_test-output-buffered-file->buffer)
     7896     (clear-stream _test-error-stream)
     7897     (clear-stream $_test-error-buffered-file->buffer)
     7898     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     7899     68/push 0/imm32
     7900     68/push 0/imm32
     7901     89/<- %edx 4/r32/esp
     7902     (tailor-exit-descriptor %edx 0x10)
     7903     #
     7904     (write _test-input-stream "fn foo {\n")
     7905     (write _test-input-stream "  var x/eax: int <- copy 0\n")
     7906     (write _test-input-stream "  var y/ecx: (offset int) <- copy x\n")
     7907     (write _test-input-stream "}\n")
     7908     # convert
     7909     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     7910     # registers except esp clobbered at this point
     7911     # restore ed
     7912     89/<- %edx 4/r32/esp
     7913     (flush _test-output-buffered-file)
     7914     (flush _test-error-buffered-file)
     7915 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     7921     # check output
     7922     (check-stream-equal _test-output-stream  ""  "F - test-copy-invalid-value-to-address: output should be empty")
     7923     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt copy: 'y' must be a non-addr non-offset scalar"  "F - test-copy-invalid-value-to-address: error message")
     7924     # check that stop(1) was called
     7925     (check-ints-equal *(edx+4) 2 "F - test-copy-invalid-value-to-offset: exit status")
     7926     # don't restore from ebp
     7927     81 0/subop/add %esp 8/imm32
     7928     # . epilogue
     7929     5d/pop-to-ebp
     7930     c3/return
     7931
     7932 test-copy-null-value-to-offset:
     7933     # . prologue
     7934     55/push-ebp
     7935     89/<- %ebp 4/r32/esp
     7936     # setup
     7937     (clear-stream _test-input-stream)
     7938     (clear-stream $_test-input-buffered-file->buffer)
     7939     (clear-stream _test-output-stream)
     7940     (clear-stream $_test-output-buffered-file->buffer)
     7941     #
     7942     (write _test-input-stream "fn foo {\n")
     7943     (write _test-input-stream "  var y/ecx: (offset int) <- copy 0\n")
     7944     (write _test-input-stream "}\n")
     7945     # convert
     7946     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     7947     (flush _test-output-buffered-file)
     7948 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     7954     # no errors
     7955     # . epilogue
     7956     89/<- %esp 5/r32/ebp
     7957     5d/pop-to-ebp
     7958     c3/return
     7959
     7960 test-copy-non-literal-to-byte:
     7961     # . prologue
     7962     55/push-ebp
     7963     89/<- %ebp 4/r32/esp
     7964     # setup
     7965     (clear-stream _test-input-stream)
     7966     (clear-stream $_test-input-buffered-file->buffer)
     7967     (clear-stream _test-output-stream)
     7968     (clear-stream $_test-output-buffered-file->buffer)
     7969     (clear-stream _test-error-stream)
     7970     (clear-stream $_test-error-buffered-file->buffer)
     7971     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     7972     68/push 0/imm32
     7973     68/push 0/imm32
     7974     89/<- %edx 4/r32/esp
     7975     (tailor-exit-descriptor %edx 0x10)
     7976     #
     7977     (write _test-input-stream "fn foo {\n")
     7978     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
     7979     (write _test-input-stream "  var y/ecx: byte <- copy x\n")
     7980     (write _test-input-stream "}\n")
     7981     # convert
     7982     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     7983     # registers except esp clobbered at this point
     7984     # restore ed
     7985     89/<- %edx 4/r32/esp
     7986     (flush _test-output-buffered-file)
     7987     (flush _test-error-buffered-file)
     7988 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     7994     # check output
     7995     (check-stream-equal _test-output-stream  ""  "F - test-copy-non-literal-to-byte: output should be empty")
     7996     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt copy: cannot copy non-literal to 'y' of type byte; use copy-byte"  "F - test-copy-non-literal-to-byte: error message")
     7997     # check that stop(1) was called
     7998     (check-ints-equal *(edx+4) 2 "F - test-copy-non-literal-to-byte: exit status")
     7999     # don't restore from ebp
     8000     81 0/subop/add %esp 8/imm32
     8001     # . epilogue
     8002     5d/pop-to-ebp
     8003     c3/return
     8004
     8005 test-copy-deref-address:
     8006     # . prologue
     8007     55/push-ebp
     8008     89/<- %ebp 4/r32/esp
     8009     # setup
     8010     (clear-stream _test-input-stream)
     8011     (clear-stream $_test-input-buffered-file->buffer)
     8012     (clear-stream _test-output-stream)
     8013     (clear-stream $_test-output-buffered-file->buffer)
     8014     #
     8015     (write _test-input-stream "fn foo {\n")
     8016     (write _test-input-stream "  var x/eax: (addr addr int) <- copy 0\n")
     8017     (write _test-input-stream "  var y/ecx: (addr int) <- copy *x\n")
     8018     (write _test-input-stream "}\n")
     8019     # convert
     8020     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     8021     (flush _test-output-buffered-file)
     8022     # no errors
     8023     # . epilogue
     8024     5d/pop-to-ebp
     8025     c3/return
     8026
     8027 test-copy-to-non-register:
     8028     # . prologue
     8029     55/push-ebp
     8030     89/<- %ebp 4/r32/esp
     8031     # setup
     8032     (clear-stream _test-input-stream)
     8033     (clear-stream $_test-input-buffered-file->buffer)
     8034     (clear-stream _test-output-stream)
     8035     (clear-stream $_test-output-buffered-file->buffer)
     8036     (clear-stream _test-error-stream)
     8037     (clear-stream $_test-error-buffered-file->buffer)
     8038     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     8039     68/push 0/imm32
     8040     68/push 0/imm32
     8041     89/<- %edx 4/r32/esp
     8042     (tailor-exit-descriptor %edx 0x10)
     8043     #
     8044     (write _test-input-stream "fn foo {\n")
     8045     (write _test-input-stream "  var x: int\n")
     8046     (write _test-input-stream "  x <- copy 0\n")
     8047     (write _test-input-stream "}\n")
     8048     # convert
     8049     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     8050     # registers except esp clobbered at this point
     8051     # restore ed
     8052     89/<- %edx 4/r32/esp
     8053     (flush _test-output-buffered-file)
     8054     (flush _test-error-buffered-file)
     8055 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     8061     # check output
     8062     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-non-register: output should be empty")
     8063     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt copy: output 'x' not in a register"  "F - test-copy-to-non-register: error message")
     8064     # check that stop(1) was called
     8065     (check-ints-equal *(edx+4) 2 "F - test-copy-to-non-register: exit status")
     8066     # don't restore from ebp
     8067     81 0/subop/add %esp 8/imm32
     8068     # . epilogue
     8069     5d/pop-to-ebp
     8070     c3/return
     8071
     8072 test-copy-from-non-scalar-inout:
     8073     # . prologue
     8074     55/push-ebp
     8075     89/<- %ebp 4/r32/esp
     8076     # setup
     8077     (clear-stream _test-input-stream)
     8078     (clear-stream $_test-input-buffered-file->buffer)
     8079     (clear-stream _test-output-stream)
     8080     (clear-stream $_test-output-buffered-file->buffer)
     8081     (clear-stream _test-error-stream)
     8082     (clear-stream $_test-error-buffered-file->buffer)
     8083     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     8084     68/push 0/imm32
     8085     68/push 0/imm32
     8086     89/<- %edx 4/r32/esp
     8087     (tailor-exit-descriptor %edx 0x10)
     8088     #
     8089     (write _test-input-stream "fn foo {\n")
     8090     (write _test-input-stream "  var x: (handle int)\n")
     8091     (write _test-input-stream "  var y/eax: int <- copy x\n")
     8092     (write _test-input-stream "}\n")
     8093     # convert
     8094     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     8095     # registers except esp clobbered at this point
     8096     # restore ed
     8097     89/<- %edx 4/r32/esp
     8098     (flush _test-output-buffered-file)
     8099     (flush _test-error-buffered-file)
     8100 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     8106     # check output
     8107     (check-stream-equal _test-output-stream  ""  "F - test-copy-from-non-scalar-inout: output should be empty")
     8108     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt copy: 'x' is too large to fit in a register"  "F - test-copy-from-non-scalar-inout: error message")
     8109     # check that stop(1) was called
     8110     (check-ints-equal *(edx+4) 2 "F - test-copy-from-non-scalar-inout: exit status")
     8111     # don't restore from ebp
     8112     81 0/subop/add %esp 8/imm32
     8113     # . epilogue
     8114     5d/pop-to-ebp
     8115     c3/return
     8116
     8117 test-copy-to-with-no-inout:
     8118     # . prologue
     8119     55/push-ebp
     8120     89/<- %ebp 4/r32/esp
     8121     # setup
     8122     (clear-stream _test-input-stream)
     8123     (clear-stream $_test-input-buffered-file->buffer)
     8124     (clear-stream _test-output-stream)
     8125     (clear-stream $_test-output-buffered-file->buffer)
     8126     (clear-stream _test-error-stream)
     8127     (clear-stream $_test-error-buffered-file->buffer)
     8128     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     8129     68/push 0/imm32
     8130     68/push 0/imm32
     8131     89/<- %edx 4/r32/esp
     8132     (tailor-exit-descriptor %edx 0x10)
     8133     #
     8134     (write _test-input-stream "fn foo {\n")
     8135     (write _test-input-stream "  copy-to\n")
     8136     (write _test-input-stream "}\n")
     8137     # convert
     8138     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     8139     # registers except esp clobbered at this point
     8140     # restore ed
     8141     89/<- %edx 4/r32/esp
     8142     (flush _test-output-buffered-file)
     8143     (flush _test-error-buffered-file)
     8144 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     8150     # check output
     8151     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-with-no-inout: output should be empty")
     8152     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy-to' must have two inouts"  "F - test-copy-to-with-no-inout: error message")
     8153     # check that stop(1) was called
     8154     (check-ints-equal *(edx+4) 2 "F - test-copy-to-with-no-inout: exit status")
     8155     # don't restore from ebp
     8156     81 0/subop/add %esp 8/imm32
     8157     # . epilogue
     8158     5d/pop-to-ebp
     8159     c3/return
     8160
     8161 test-copy-to-with-no-source:
     8162     # . prologue
     8163     55/push-ebp
     8164     89/<- %ebp 4/r32/esp
     8165     # setup
     8166     (clear-stream _test-input-stream)
     8167     (clear-stream $_test-input-buffered-file->buffer)
     8168     (clear-stream _test-output-stream)
     8169     (clear-stream $_test-output-buffered-file->buffer)
     8170     (clear-stream _test-error-stream)
     8171     (clear-stream $_test-error-buffered-file->buffer)
     8172     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     8173     68/push 0/imm32
     8174     68/push 0/imm32
     8175     89/<- %edx 4/r32/esp
     8176     (tailor-exit-descriptor %edx 0x10)
     8177     #
     8178     (write _test-input-stream "fn foo {\n")
     8179     (write _test-input-stream "  var x: boolean\n")
     8180     (write _test-input-stream "  copy-to x\n")
     8181     (write _test-input-stream "}\n")
     8182     # convert
     8183     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     8184     # registers except esp clobbered at this point
     8185     # restore ed
     8186     89/<- %edx 4/r32/esp
     8187     (flush _test-output-buffered-file)
     8188     (flush _test-error-buffered-file)
     8189 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     8195     # check output
     8196     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-with-no-source: output should be empty")
     8197     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy-to' must have two inouts"  "F - test-copy-to-with-no-source: error message")
     8198     # check that stop(1) was called
     8199     (check-ints-equal *(edx+4) 2 "F - test-copy-to-with-no-source: exit status")
     8200     # don't restore from ebp
     8201     81 0/subop/add %esp 8/imm32
     8202     # . epilogue
     8203     5d/pop-to-ebp
     8204     c3/return
     8205
     8206 test-copy-to-with-no-register:
     8207     # . prologue
     8208     55/push-ebp
     8209     89/<- %ebp 4/r32/esp
     8210     # setup
     8211     (clear-stream _test-input-stream)
     8212     (clear-stream $_test-input-buffered-file->buffer)
     8213     (clear-stream _test-output-stream)
     8214     (clear-stream $_test-output-buffered-file->buffer)
     8215     (clear-stream _test-error-stream)
     8216     (clear-stream $_test-error-buffered-file->buffer)
     8217     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     8218     68/push 0/imm32
     8219     68/push 0/imm32
     8220     89/<- %edx 4/r32/esp
     8221     (tailor-exit-descriptor %edx 0x10)
     8222     #
     8223     (write _test-input-stream "fn foo {\n")
     8224     (write _test-input-stream "  var x: boolean\n")
     8225     (write _test-input-stream "  copy-to x, x\n")
     8226     (write _test-input-stream "}\n")
     8227     # convert
     8228     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     8229     # registers except esp clobbered at this point
     8230     # restore ed
     8231     89/<- %edx 4/r32/esp
     8232     (flush _test-output-buffered-file)
     8233     (flush _test-error-buffered-file)
     8234 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     8240     # check output
     8241     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-with-no-register: output should be empty")
     8242     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt copy-to: source (second inout) is in memory"  "F - test-copy-to-with-no-register: error message")
     8243     # check that stop(1) was called
     8244     (check-ints-equal *(edx+4) 2 "F - test-copy-to-with-no-register: exit status")
     8245     # don't restore from ebp
     8246     81 0/subop/add %esp 8/imm32
     8247     # . epilogue
     8248     5d/pop-to-ebp
     8249     c3/return
     8250
     8251 test-copy-to-with-too-many-inouts:
     8252     # . prologue
     8253     55/push-ebp
     8254     89/<- %ebp 4/r32/esp
     8255     # setup
     8256     (clear-stream _test-input-stream)
     8257     (clear-stream $_test-input-buffered-file->buffer)
     8258     (clear-stream _test-output-stream)
     8259     (clear-stream $_test-output-buffered-file->buffer)
     8260     (clear-stream _test-error-stream)
     8261     (clear-stream $_test-error-buffered-file->buffer)
     8262     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     8263     68/push 0/imm32
     8264     68/push 0/imm32
     8265     89/<- %edx 4/r32/esp
     8266     (tailor-exit-descriptor %edx 0x10)
     8267     #
     8268     (write _test-input-stream "fn foo {\n")
     8269     (write _test-input-stream "  var x: boolean\n")
     8270     (write _test-input-stream "  copy-to x, 0, 0\n")
     8271     (write _test-input-stream "}\n")
     8272     # convert
     8273     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     8274     # registers except esp clobbered at this point
     8275     # restore ed
     8276     89/<- %edx 4/r32/esp
     8277     (flush _test-output-buffered-file)
     8278     (flush _test-error-buffered-file)
     8279 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     8285     # check output
     8286     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-with-too-many-inouts: output should be empty")
     8287     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy-to' must have two inouts"  "F - test-copy-to-with-too-many-inouts: error message")
     8288     # check that stop(1) was called
     8289     (check-ints-equal *(edx+4) 2 "F - test-copy-to-with-too-many-inouts: exit status")
     8290     # don't restore from ebp
     8291     81 0/subop/add %esp 8/imm32
     8292     # . epilogue
     8293     5d/pop-to-ebp
     8294     c3/return
     8295
     8296 test-copy-to-with-output:
     8297     # . prologue
     8298     55/push-ebp
     8299     89/<- %ebp 4/r32/esp
     8300     # setup
     8301     (clear-stream _test-input-stream)
     8302     (clear-stream $_test-input-buffered-file->buffer)
     8303     (clear-stream _test-output-stream)
     8304     (clear-stream $_test-output-buffered-file->buffer)
     8305     (clear-stream _test-error-stream)
     8306     (clear-stream $_test-error-buffered-file->buffer)
     8307     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     8308     68/push 0/imm32
     8309     68/push 0/imm32
     8310     89/<- %edx 4/r32/esp
     8311     (tailor-exit-descriptor %edx 0x10)
     8312     #
     8313     (write _test-input-stream "fn foo {\n")
     8314     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
     8315     (write _test-input-stream "  var y/ecx: boolean <- copy 0\n")
     8316     (write _test-input-stream "  x <- copy-to y, 0\n")
     8317     (write _test-input-stream "}\n")
     8318     # convert
     8319     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     8320     # registers except esp clobbered at this point
     8321     # restore ed
     8322     89/<- %edx 4/r32/esp
     8323     (flush _test-output-buffered-file)
     8324     (flush _test-error-buffered-file)
     8325 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     8331     # check output
     8332     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-with-output: output should be empty")
     8333     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy-to' must not have any outputs"  "F - test-copy-to-with-output: error message")
     8334     # check that stop(1) was called
     8335     (check-ints-equal *(edx+4) 2 "F - test-copy-to-with-output: exit status")
     8336     # don't restore from ebp
     8337     81 0/subop/add %esp 8/imm32
     8338     # . epilogue
     8339     5d/pop-to-ebp
     8340     c3/return
     8341
     8342 test-copy-to-invalid-value-to-address:
     8343     # . prologue
     8344     55/push-ebp
     8345     89/<- %ebp 4/r32/esp
     8346     # setup
     8347     (clear-stream _test-input-stream)
     8348     (clear-stream $_test-input-buffered-file->buffer)
     8349     (clear-stream _test-output-stream)
     8350     (clear-stream $_test-output-buffered-file->buffer)
     8351     (clear-stream _test-error-stream)
     8352     (clear-stream $_test-error-buffered-file->buffer)
     8353     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     8354     68/push 0/imm32
     8355     68/push 0/imm32
     8356     89/<- %edx 4/r32/esp
     8357     (tailor-exit-descriptor %edx 0x10)
     8358     #
     8359     (write _test-input-stream "fn foo {\n")
     8360     (write _test-input-stream "  var x/eax: int <- copy 0\n")
     8361     (write _test-input-stream "  var y: (addr int)\n")
     8362     (write _test-input-stream "  copy-to y, x\n")
     8363     (write _test-input-stream "}\n")
     8364     # convert
     8365     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     8366     # registers except esp clobbered at this point
     8367     # restore ed
     8368     89/<- %edx 4/r32/esp
     8369     (flush _test-output-buffered-file)
     8370     (flush _test-error-buffered-file)
     8371 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     8377     # check output
     8378     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-invalid-value-to-address: output should be empty")
     8379     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt copy-to: 'y' must be a non-addr non-offset scalar"  "F - test-copy-to-invalid-value-to-address: error message")
     8380     # check that stop(1) was called
     8381     (check-ints-equal *(edx+4) 2 "F - test-copy-to-invalid-value-to-address: exit status")
     8382     # don't restore from ebp
     8383     81 0/subop/add %esp 8/imm32
     8384     # . epilogue
     8385     5d/pop-to-ebp
     8386     c3/return
     8387
     8388 test-copy-to-null-value-to-address:
     8389     # . prologue
     8390     55/push-ebp
     8391     89/<- %ebp 4/r32/esp
     8392     # setup
     8393     (clear-stream _test-input-stream)
     8394     (clear-stream $_test-input-buffered-file->buffer)
     8395     (clear-stream _test-output-stream)
     8396     (clear-stream $_test-output-buffered-file->buffer)
     8397     #
     8398     (write _test-input-stream "fn foo {\n")
     8399     (write _test-input-stream "  var y: (addr int)\n")
     8400     (write _test-input-stream "  copy-to y, 0\n")
     8401     (write _test-input-stream "}\n")
     8402     # convert
     8403     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     8404     (flush _test-output-buffered-file)
     8405     # no errors
     8406     # . epilogue
     8407     89/<- %esp 5/r32/ebp
     8408     5d/pop-to-ebp
     8409     c3/return
     8410
     8411 test-copy-to-invalid-value-to-offset:
     8412     # . prologue
     8413     55/push-ebp
     8414     89/<- %ebp 4/r32/esp
     8415     # setup
     8416     (clear-stream _test-input-stream)
     8417     (clear-stream $_test-input-buffered-file->buffer)
     8418     (clear-stream _test-output-stream)
     8419     (clear-stream $_test-output-buffered-file->buffer)
     8420     (clear-stream _test-error-stream)
     8421     (clear-stream $_test-error-buffered-file->buffer)
     8422     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     8423     68/push 0/imm32
     8424     68/push 0/imm32
     8425     89/<- %edx 4/r32/esp
     8426     (tailor-exit-descriptor %edx 0x10)
     8427     #
     8428     (write _test-input-stream "fn foo {\n")
     8429     (write _test-input-stream "  var x/eax: int <- copy 0\n")
     8430     (write _test-input-stream "  var y: (offset int)\n")
     8431     (write _test-input-stream "  copy-to y, x\n")
     8432     (write _test-input-stream "}\n")
     8433     # convert
     8434     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     8435     # registers except esp clobbered at this point
     8436     # restore ed
     8437     89/<- %edx 4/r32/esp
     8438     (flush _test-output-buffered-file)
     8439     (flush _test-error-buffered-file)
     8440 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     8446     # check output
     8447     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-invalid-value-to-offset: output should be empty")
     8448     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt copy-to: 'y' must be a non-addr non-offset scalar"  "F - test-copy-to-invalid-value-to-offset: error message")
     8449     # check that stop(1) was called
     8450     (check-ints-equal *(edx+4) 2 "F - test-copy-to-invalid-value-to-offset: exit status")
     8451     # don't restore from ebp
     8452     81 0/subop/add %esp 8/imm32
     8453     # . epilogue
     8454     5d/pop-to-ebp
     8455     c3/return
     8456
     8457 test-copy-to-null-value-to-offset:
     8458     # . prologue
     8459     55/push-ebp
     8460     89/<- %ebp 4/r32/esp
     8461     # setup
     8462     (clear-stream _test-input-stream)
     8463     (clear-stream $_test-input-buffered-file->buffer)
     8464     (clear-stream _test-output-stream)
     8465     (clear-stream $_test-output-buffered-file->buffer)
     8466     #
     8467     (write _test-input-stream "fn foo {\n")
     8468     (write _test-input-stream "  var y: (offset int)\n")
     8469     (write _test-input-stream "  copy-to y, 0\n")
     8470     (write _test-input-stream "}\n")
     8471     # convert
     8472     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     8473     (flush _test-output-buffered-file)
     8474     # no errors
     8475     # . epilogue
     8476     89/<- %esp 5/r32/ebp
     8477     5d/pop-to-ebp
     8478     c3/return
     8479
     8480 test-copy-to-non-literal-to-byte:
     8481     # . prologue
     8482     55/push-ebp
     8483     89/<- %ebp 4/r32/esp
     8484     # setup
     8485     (clear-stream _test-input-stream)
     8486     (clear-stream $_test-input-buffered-file->buffer)
     8487     (clear-stream _test-output-stream)
     8488     (clear-stream $_test-output-buffered-file->buffer)
     8489     (clear-stream _test-error-stream)
     8490     (clear-stream $_test-error-buffered-file->buffer)
     8491     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     8492     68/push 0/imm32
     8493     68/push 0/imm32
     8494     89/<- %edx 4/r32/esp
     8495     (tailor-exit-descriptor %edx 0x10)
     8496     #
     8497     (write _test-input-stream "fn foo {\n")
     8498     (write _test-input-stream "  var x/ecx: byte <- copy 3\n")
     8499     (write _test-input-stream "  var y/eax: (addr byte) <- copy 0\n")
     8500     (write _test-input-stream "  copy-to *y, x\n")
     8501     (write _test-input-stream "}\n")
     8502     # convert
     8503     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     8504     # registers except esp clobbered at this point
     8505     # restore ed
     8506     89/<- %edx 4/r32/esp
     8507     (flush _test-output-buffered-file)
     8508     (flush _test-error-buffered-file)
     8509 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     8515     # check output
     8516     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-non-literal-to-byte: output should be empty")
     8517     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt copy-to: cannot copy non-literal to type byte; use copy-byte-to"  "F - test-copy-to-non-literal-to-byte: error message")
     8518     # check that stop(1) was called
     8519     (check-ints-equal *(edx+4) 2 "F - test-copy-to-non-literal-to-byte: exit status")
     8520     # don't restore from ebp
     8521     81 0/subop/add %esp 8/imm32
     8522     # . epilogue
     8523     5d/pop-to-ebp
     8524     c3/return
     8525
     8526 test-copy-to-deref-address:
     8527     # . prologue
     8528     55/push-ebp
     8529     89/<- %ebp 4/r32/esp
     8530     # setup
     8531     (clear-stream _test-input-stream)
     8532     (clear-stream $_test-input-buffered-file->buffer)
     8533     (clear-stream _test-output-stream)
     8534     (clear-stream $_test-output-buffered-file->buffer)
     8535     #
     8536     (write _test-input-stream "fn foo {\n")
     8537     (write _test-input-stream "  var x/eax: (addr int) <- copy 0\n")
     8538     (write _test-input-stream "  var y/ecx: (addr addr int) <- copy 0\n")
     8539     (write _test-input-stream "  copy-to *y, x\n")
     8540     (write _test-input-stream "}\n")
     8541     # convert
     8542     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     8543     (flush _test-output-buffered-file)
     8544     # no errors
     8545     # . epilogue
     8546     5d/pop-to-ebp
     8547     c3/return
     8548
     8549 test-copy-to-from-non-scalar-inout:
     8550     # . prologue
     8551     55/push-ebp
     8552     89/<- %ebp 4/r32/esp
     8553     # setup
     8554     (clear-stream _test-input-stream)
     8555     (clear-stream $_test-input-buffered-file->buffer)
     8556     (clear-stream _test-output-stream)
     8557     (clear-stream $_test-output-buffered-file->buffer)
     8558     (clear-stream _test-error-stream)
     8559     (clear-stream $_test-error-buffered-file->buffer)
     8560     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     8561     68/push 0/imm32
     8562     68/push 0/imm32
     8563     89/<- %edx 4/r32/esp
     8564     (tailor-exit-descriptor %edx 0x10)
     8565     #
     8566     (write _test-input-stream "fn foo {\n")
     8567     (write _test-input-stream "  var x: (handle int)\n")
     8568     (write _test-input-stream "  var y: int\n")
     8569     (write _test-input-stream "  copy-to y, x\n")
     8570     (write _test-input-stream "}\n")
     8571     # convert
     8572     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     8573     # registers except esp clobbered at this point
     8574     # restore ed
     8575     89/<- %edx 4/r32/esp
     8576     (flush _test-output-buffered-file)
     8577     (flush _test-error-buffered-file)
     8578 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     8584     # check output
     8585     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-from-non-scalar-inout: output should be empty")
     8586     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt copy-to: 'x' is too large to copy"  "F - test-copy-to-from-non-scalar-inout: error message")
     8587     # check that stop(1) was called
     8588     (check-ints-equal *(edx+4) 2 "F - test-copy-to-from-non-scalar-inout: exit status")
     8589     # don't restore from ebp
     8590     81 0/subop/add %esp 8/imm32
     8591     # . epilogue
     8592     5d/pop-to-ebp
     8593     c3/return
     8594
     8595 test-copy-byte-with-no-inout:
     8596     # . prologue
     8597     55/push-ebp
     8598     89/<- %ebp 4/r32/esp
     8599     # setup
     8600     (clear-stream _test-input-stream)
     8601     (clear-stream $_test-input-buffered-file->buffer)
     8602     (clear-stream _test-output-stream)
     8603     (clear-stream $_test-output-buffered-file->buffer)
     8604     (clear-stream _test-error-stream)
     8605     (clear-stream $_test-error-buffered-file->buffer)
     8606     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     8607     68/push 0/imm32
     8608     68/push 0/imm32
     8609     89/<- %edx 4/r32/esp
     8610     (tailor-exit-descriptor %edx 0x10)
     8611     #
     8612     (write _test-input-stream "fn foo {\n")
     8613     (write _test-input-stream "  var x/eax: byte <- copy-byte\n")
     8614     (write _test-input-stream "}\n")
     8615     # convert
     8616     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     8617     # registers except esp clobbered at this point
     8618     # restore ed
     8619     89/<- %edx 4/r32/esp
     8620     (flush _test-output-buffered-file)
     8621     (flush _test-error-buffered-file)
     8622 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     8628     # check output
     8629     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-with-no-inout: output should be empty")
     8630     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy-byte' expects an inout"  "F - test-copy-byte-with-no-inout: error message")
     8631     # check that stop(1) was called
     8632     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-with-no-inout: exit status")
     8633     # don't restore from ebp
     8634     81 0/subop/add %esp 8/imm32
     8635     # . epilogue
     8636     5d/pop-to-ebp
     8637     c3/return
     8638
     8639 test-copy-byte-with-multiple-inouts:
     8640     # . prologue
     8641     55/push-ebp
     8642     89/<- %ebp 4/r32/esp
     8643     # setup
     8644     (clear-stream _test-input-stream)
     8645     (clear-stream $_test-input-buffered-file->buffer)
     8646     (clear-stream _test-output-stream)
     8647     (clear-stream $_test-output-buffered-file->buffer)
     8648     (clear-stream _test-error-stream)
     8649     (clear-stream $_test-error-buffered-file->buffer)
     8650     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     8651     68/push 0/imm32
     8652     68/push 0/imm32
     8653     89/<- %edx 4/r32/esp
     8654     (tailor-exit-descriptor %edx 0x10)
     8655     #
     8656     (write _test-input-stream "fn foo {\n")
     8657     (write _test-input-stream "  var x/eax: byte <- copy-byte 0, 0\n")
     8658     (write _test-input-stream "}\n")
     8659     # convert
     8660     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     8661     # registers except esp clobbered at this point
     8662     # restore ed
     8663     89/<- %edx 4/r32/esp
     8664     (flush _test-output-buffered-file)
     8665     (flush _test-error-buffered-file)
     8666 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     8672     # check output
     8673     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-with-multiple-inouts: output should be empty")
     8674     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy-byte' must have just one inout"  "F - test-copy-byte-with-multiple-inouts: error message")
     8675     # check that stop(1) was called
     8676     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-with-multiple-inouts: exit status")
     8677     # don't restore from ebp
     8678     81 0/subop/add %esp 8/imm32
     8679     # . epilogue
     8680     5d/pop-to-ebp
     8681     c3/return
     8682
     8683 test-copy-byte-with-no-output:
     8684     # . prologue
     8685     55/push-ebp
     8686     89/<- %ebp 4/r32/esp
     8687     # setup
     8688     (clear-stream _test-input-stream)
     8689     (clear-stream $_test-input-buffered-file->buffer)
     8690     (clear-stream _test-output-stream)
     8691     (clear-stream $_test-output-buffered-file->buffer)
     8692     (clear-stream _test-error-stream)
     8693     (clear-stream $_test-error-buffered-file->buffer)
     8694     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     8695     68/push 0/imm32
     8696     68/push 0/imm32
     8697     89/<- %edx 4/r32/esp
     8698     (tailor-exit-descriptor %edx 0x10)
     8699     #
     8700     (write _test-input-stream "fn foo {\n")
     8701     (write _test-input-stream "  copy-byte 0\n")
     8702     (write _test-input-stream "}\n")
     8703     # convert
     8704     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     8705     # registers except esp clobbered at this point
     8706     # restore ed
     8707     89/<- %edx 4/r32/esp
     8708     (flush _test-output-buffered-file)
     8709     (flush _test-error-buffered-file)
     8710 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     8716     # check output
     8717     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-with-no-output: output should be empty")
     8718     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy-byte' expects an output"  "F - test-copy-byte-with-no-output: error message")
     8719     # check that stop(1) was called
     8720     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-with-no-output: exit status")
     8721     # don't restore from ebp
     8722     81 0/subop/add %esp 8/imm32
     8723     # . epilogue
     8724     5d/pop-to-ebp
     8725     c3/return
     8726
     8727 test-copy-byte-with-multiple-outputs:
     8728     # . prologue
     8729     55/push-ebp
     8730     89/<- %ebp 4/r32/esp
     8731     # setup
     8732     (clear-stream _test-input-stream)
     8733     (clear-stream $_test-input-buffered-file->buffer)
     8734     (clear-stream _test-output-stream)
     8735     (clear-stream $_test-output-buffered-file->buffer)
     8736     (clear-stream _test-error-stream)
     8737     (clear-stream $_test-error-buffered-file->buffer)
     8738     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     8739     68/push 0/imm32
     8740     68/push 0/imm32
     8741     89/<- %edx 4/r32/esp
     8742     (tailor-exit-descriptor %edx 0x10)
     8743     #
     8744     (write _test-input-stream "fn foo {\n")
     8745     (write _test-input-stream "  var x/eax: byte <- copy 0\n")
     8746     (write _test-input-stream "  var y/ecx: byte <- copy 0\n")
     8747     (write _test-input-stream "  x, y <- copy-byte 0\n")
     8748     (write _test-input-stream "}\n")
     8749     # convert
     8750     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     8751     # registers except esp clobbered at this point
     8752     # restore ed
     8753     89/<- %edx 4/r32/esp
     8754     (flush _test-output-buffered-file)
     8755     (flush _test-error-buffered-file)
     8756 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     8762     # check output
     8763     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-with-multiple-outputs: output should be empty")
     8764     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy-byte' must have just one output"  "F - test-copy-byte-with-multiple-outputs: error message")
     8765     # check that stop(1) was called
     8766     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-with-multiple-outputs: exit status")
     8767     # don't restore from ebp
     8768     81 0/subop/add %esp 8/imm32
     8769     # . epilogue
     8770     5d/pop-to-ebp
     8771     c3/return
     8772
     8773 test-copy-byte-deref-address:
     8774     # . prologue
     8775     55/push-ebp
     8776     89/<- %ebp 4/r32/esp
     8777     # setup
     8778     (clear-stream _test-input-stream)
     8779     (clear-stream $_test-input-buffered-file->buffer)
     8780     (clear-stream _test-output-stream)
     8781     (clear-stream $_test-output-buffered-file->buffer)
     8782     #
     8783     (write _test-input-stream "fn foo {\n")
     8784     (write _test-input-stream "  var x/eax: (addr byte) <- copy 0\n")
     8785     (write _test-input-stream "  var y/ecx: byte <- copy-byte *x\n")
     8786     (write _test-input-stream "}\n")
     8787     # convert
     8788     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     8789     (flush _test-output-buffered-file)
     8790 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     8796     # not bothering checking output
     8797     (check-next-stream-line-equal _test-error-stream  ""  "F - test-copy-byte-deref-address: error message")
     8798     # . epilogue
     8799     5d/pop-to-ebp
     8800     c3/return
     8801
     8802 test-copy-byte-with-invalid-output-type:
     8803     # . prologue
     8804     55/push-ebp
     8805     89/<- %ebp 4/r32/esp
     8806     # setup
     8807     (clear-stream _test-input-stream)
     8808     (clear-stream $_test-input-buffered-file->buffer)
     8809     (clear-stream _test-output-stream)
     8810     (clear-stream $_test-output-buffered-file->buffer)
     8811     (clear-stream _test-error-stream)
     8812     (clear-stream $_test-error-buffered-file->buffer)
     8813     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     8814     68/push 0/imm32
     8815     68/push 0/imm32
     8816     89/<- %edx 4/r32/esp
     8817     (tailor-exit-descriptor %edx 0x10)
     8818     #
     8819     (write _test-input-stream "fn foo {\n")
     8820     (write _test-input-stream "  var x/eax: (addr byte) <- copy 0\n")
     8821     (write _test-input-stream "  var y/eax: int <- copy-byte *x\n")
     8822     (write _test-input-stream "}\n")
     8823     # convert
     8824     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     8825     # registers except esp clobbered at this point
     8826     # restore ed
     8827     89/<- %edx 4/r32/esp
     8828     (flush _test-output-buffered-file)
     8829     (flush _test-error-buffered-file)
     8830 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     8836     # check output
     8837     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-with-invalid-output-type: output should be empty")
     8838     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy-byte' must write to output of type byte"  "F - test-copy-byte-with-invalid-output-type: error message")
     8839     # check that stop(1) was called
     8840     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-with-invalid-output-type: exit status")
     8841     # don't restore from ebp
     8842     81 0/subop/add %esp 8/imm32
     8843     # . epilogue
     8844     5d/pop-to-ebp
     8845     c3/return
     8846
     8847 test-copy-byte-from-non-scalar-inout:
     8848     # . prologue
     8849     55/push-ebp
     8850     89/<- %ebp 4/r32/esp
     8851     # setup
     8852     (clear-stream _test-input-stream)
     8853     (clear-stream $_test-input-buffered-file->buffer)
     8854     (clear-stream _test-output-stream)
     8855     (clear-stream $_test-output-buffered-file->buffer)
     8856     (clear-stream _test-error-stream)
     8857     (clear-stream $_test-error-buffered-file->buffer)
     8858     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     8859     68/push 0/imm32
     8860     68/push 0/imm32
     8861     89/<- %edx 4/r32/esp
     8862     (tailor-exit-descriptor %edx 0x10)
     8863     #
     8864     (write _test-input-stream "fn foo {\n")
     8865     (write _test-input-stream "  var x: (handle int)\n")
     8866     (write _test-input-stream "  var y/eax: byte <- copy-byte x\n")
     8867     (write _test-input-stream "}\n")
     8868     # convert
     8869     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     8870     # registers except esp clobbered at this point
     8871     # restore ed
     8872     89/<- %edx 4/r32/esp
     8873     (flush _test-output-buffered-file)
     8874     (flush _test-error-buffered-file)
     8875 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     8881     # check output
     8882     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-from-non-scalar-inout: output should be empty")
     8883     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt copy-byte: 'x' is too large to fit in a register"  "F - test-copy-byte-from-non-scalar-inout: error message")
     8884     # check that stop(1) was called
     8885     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-from-non-scalar-inout: exit status")
     8886     # don't restore from ebp
     8887     81 0/subop/add %esp 8/imm32
     8888     # . epilogue
     8889     5d/pop-to-ebp
     8890     c3/return
     8891
     8892 test-copy-byte-to-with-no-inout:
     8893     # . prologue
     8894     55/push-ebp
     8895     89/<- %ebp 4/r32/esp
     8896     # setup
     8897     (clear-stream _test-input-stream)
     8898     (clear-stream $_test-input-buffered-file->buffer)
     8899     (clear-stream _test-output-stream)
     8900     (clear-stream $_test-output-buffered-file->buffer)
     8901     (clear-stream _test-error-stream)
     8902     (clear-stream $_test-error-buffered-file->buffer)
     8903     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     8904     68/push 0/imm32
     8905     68/push 0/imm32
     8906     89/<- %edx 4/r32/esp
     8907     (tailor-exit-descriptor %edx 0x10)
     8908     #
     8909     (write _test-input-stream "fn foo {\n")
     8910     (write _test-input-stream "  copy-byte-to\n")
     8911     (write _test-input-stream "}\n")
     8912     # convert
     8913     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     8914     # registers except esp clobbered at this point
     8915     # restore ed
     8916     89/<- %edx 4/r32/esp
     8917     (flush _test-output-buffered-file)
     8918     (flush _test-error-buffered-file)
     8919 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     8925     # check output
     8926     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-to-with-no-inout: output should be empty")
     8927     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy-byte-to' must have two inouts"  "F - test-copy-byte-to-with-no-inout: error message")
     8928     # check that stop(1) was called
     8929     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-to-with-no-inout: exit status")
     8930     # don't restore from ebp
     8931     81 0/subop/add %esp 8/imm32
     8932     # . epilogue
     8933     5d/pop-to-ebp
     8934     c3/return
     8935
     8936 test-copy-byte-to-with-no-source:
     8937     # . prologue
     8938     55/push-ebp
     8939     89/<- %ebp 4/r32/esp
     8940     # setup
     8941     (clear-stream _test-input-stream)
     8942     (clear-stream $_test-input-buffered-file->buffer)
     8943     (clear-stream _test-output-stream)
     8944     (clear-stream $_test-output-buffered-file->buffer)
     8945     (clear-stream _test-error-stream)
     8946     (clear-stream $_test-error-buffered-file->buffer)
     8947     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     8948     68/push 0/imm32
     8949     68/push 0/imm32
     8950     89/<- %edx 4/r32/esp
     8951     (tailor-exit-descriptor %edx 0x10)
     8952     #
     8953     (write _test-input-stream "fn foo {\n")
     8954     (write _test-input-stream "  var x/eax: (addr byte) <- copy 0\n")
     8955     (write _test-input-stream "  copy-byte-to *x\n")
     8956     (write _test-input-stream "}\n")
     8957     # convert
     8958     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     8959     # registers except esp clobbered at this point
     8960     # restore ed
     8961     89/<- %edx 4/r32/esp
     8962     (flush _test-output-buffered-file)
     8963     (flush _test-error-buffered-file)
     8964 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     8970     # check output
     8971     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-to-with-no-source: output should be empty")
     8972     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy-byte-to' must have two inouts"  "F - test-copy-byte-to-with-no-source: error message")
     8973     # check that stop(1) was called
     8974     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-to-with-no-source: exit status")
     8975     # don't restore from ebp
     8976     81 0/subop/add %esp 8/imm32
     8977     # . epilogue
     8978     5d/pop-to-ebp
     8979     c3/return
     8980
     8981 test-copy-byte-to-with-too-many-inouts:
     8982     # . prologue
     8983     55/push-ebp
     8984     89/<- %ebp 4/r32/esp
     8985     # setup
     8986     (clear-stream _test-input-stream)
     8987     (clear-stream $_test-input-buffered-file->buffer)
     8988     (clear-stream _test-output-stream)
     8989     (clear-stream $_test-output-buffered-file->buffer)
     8990     (clear-stream _test-error-stream)
     8991     (clear-stream $_test-error-buffered-file->buffer)
     8992     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     8993     68/push 0/imm32
     8994     68/push 0/imm32
     8995     89/<- %edx 4/r32/esp
     8996     (tailor-exit-descriptor %edx 0x10)
     8997     #
     8998     (write _test-input-stream "fn foo {\n")
     8999     (write _test-input-stream "  var x/eax: (addr byte) <- copy 0\n")
     9000     (write _test-input-stream "  copy-byte-to *x, 0, 0\n")
     9001     (write _test-input-stream "}\n")
     9002     # convert
     9003     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     9004     # registers except esp clobbered at this point
     9005     # restore ed
     9006     89/<- %edx 4/r32/esp
     9007     (flush _test-output-buffered-file)
     9008     (flush _test-error-buffered-file)
     9009 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     9015     # check output
     9016     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-to-with-too-many-inouts: output should be empty")
     9017     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy-byte-to' must have two inouts"  "F - test-copy-byte-to-with-too-many-inouts: error message")
     9018     # check that stop(1) was called
     9019     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-to-with-too-many-inouts: exit status")
     9020     # don't restore from ebp
     9021     81 0/subop/add %esp 8/imm32
     9022     # . epilogue
     9023     5d/pop-to-ebp
     9024     c3/return
     9025
     9026 test-copy-byte-to-with-output:
     9027     # . prologue
     9028     55/push-ebp
     9029     89/<- %ebp 4/r32/esp
     9030     # setup
     9031     (clear-stream _test-input-stream)
     9032     (clear-stream $_test-input-buffered-file->buffer)
     9033     (clear-stream _test-output-stream)
     9034     (clear-stream $_test-output-buffered-file->buffer)
     9035     (clear-stream _test-error-stream)
     9036     (clear-stream $_test-error-buffered-file->buffer)
     9037     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     9038     68/push 0/imm32
     9039     68/push 0/imm32
     9040     89/<- %edx 4/r32/esp
     9041     (tailor-exit-descriptor %edx 0x10)
     9042     #
     9043     (write _test-input-stream "fn foo {\n")
     9044     (write _test-input-stream "  var x/eax: byte <- copy 0\n")
     9045     (write _test-input-stream "  var y/ecx: (addr byte) <- copy 0\n")
     9046     (write _test-input-stream "  x <- copy-byte-to *y, 0\n")
     9047     (write _test-input-stream "}\n")
     9048     # convert
     9049     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     9050     # registers except esp clobbered at this point
     9051     # restore ed
     9052     89/<- %edx 4/r32/esp
     9053     (flush _test-output-buffered-file)
     9054     (flush _test-error-buffered-file)
     9055 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     9061     # check output
     9062     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-to-with-output: output should be empty")
     9063     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy-byte-to' must not have any outputs"  "F - test-copy-byte-to-with-output: error message")
     9064     # check that stop(1) was called
     9065     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-to-with-output: exit status")
     9066     # don't restore from ebp
     9067     81 0/subop/add %esp 8/imm32
     9068     # . epilogue
     9069     5d/pop-to-ebp
     9070     c3/return
     9071
     9072 test-copy-byte-to-with-invalid-output-type:
     9073     # . prologue
     9074     55/push-ebp
     9075     89/<- %ebp 4/r32/esp
     9076     # setup
     9077     (clear-stream _test-input-stream)
     9078     (clear-stream $_test-input-buffered-file->buffer)
     9079     (clear-stream _test-output-stream)
     9080     (clear-stream $_test-output-buffered-file->buffer)
     9081     (clear-stream _test-error-stream)
     9082     (clear-stream $_test-error-buffered-file->buffer)
     9083     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     9084     68/push 0/imm32
     9085     68/push 0/imm32
     9086     89/<- %edx 4/r32/esp
     9087     (tailor-exit-descriptor %edx 0x10)
     9088     #
     9089     (write _test-input-stream "fn foo {\n")
     9090     (write _test-input-stream "  var x/eax: byte <- copy 0\n")
     9091     (write _test-input-stream "  var y: int\n")
     9092     (write _test-input-stream "  copy-byte-to y, x\n")
     9093     (write _test-input-stream "}\n")
     9094     # convert
     9095     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     9096     # registers except esp clobbered at this point
     9097     # restore ed
     9098     89/<- %edx 4/r32/esp
     9099     (flush _test-output-buffered-file)
     9100     (flush _test-error-buffered-file)
     9101 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     9107     # check output
     9108     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-to-with-invalid-output-type: output should be empty")
     9109     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt copy-byte-to: 'y' must be a byte"  "F - test-copy-byte-to-with-invalid-output-type: error message")
     9110     # check that stop(1) was called
     9111     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-to-with-invalid-output-type: exit status")
     9112     # don't restore from ebp
     9113     81 0/subop/add %esp 8/imm32
     9114     # . epilogue
     9115     5d/pop-to-ebp
     9116     c3/return
     9117
     9118 test-copy-byte-to-with-literal-inout:
     9119     # . prologue
     9120     55/push-ebp
     9121     89/<- %ebp 4/r32/esp
     9122     # setup
     9123     (clear-stream _test-input-stream)
     9124     (clear-stream $_test-input-buffered-file->buffer)
     9125     (clear-stream _test-output-stream)
     9126     (clear-stream $_test-output-buffered-file->buffer)
     9127     (clear-stream _test-error-stream)
     9128     (clear-stream $_test-error-buffered-file->buffer)
     9129     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     9130     68/push 0/imm32
     9131     68/push 0/imm32
     9132     89/<- %edx 4/r32/esp
     9133     (tailor-exit-descriptor %edx 0x10)
     9134     #
     9135     (write _test-input-stream "fn foo {\n")
     9136     (write _test-input-stream "  var x/eax: (addr byte) <- copy 0\n")
     9137     (write _test-input-stream "  copy-byte-to *x, 0\n")
     9138     (write _test-input-stream "}\n")
     9139     # convert
     9140     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     9141     # registers except esp clobbered at this point
     9142     # restore ed
     9143     89/<- %edx 4/r32/esp
     9144     (flush _test-output-buffered-file)
     9145     (flush _test-error-buffered-file)
     9146 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     9152     # check output
     9153     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-to-with-literal-inout: output should be empty")
     9154     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt copy-byte-to: source (second inout) must be in a register"  "F - test-copy-byte-to-with-literal-inout: error message")
     9155     # check that stop(1) was called
     9156     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-to-with-literal-inout: exit status")
     9157     # don't restore from ebp
     9158     81 0/subop/add %esp 8/imm32
     9159     # . epilogue
     9160     5d/pop-to-ebp
     9161     c3/return
     9162
     9163 test-copy-byte-to-deref-address:
     9164     # . prologue
     9165     55/push-ebp
     9166     89/<- %ebp 4/r32/esp
     9167     # setup
     9168     (clear-stream _test-input-stream)
     9169     (clear-stream $_test-input-buffered-file->buffer)
     9170     (clear-stream _test-output-stream)
     9171     (clear-stream $_test-output-buffered-file->buffer)
     9172     #
     9173     (write _test-input-stream "fn foo {\n")
     9174     (write _test-input-stream "  var x/eax: byte <- copy 0\n")
     9175     (write _test-input-stream "  var y/ecx: (addr byte) <- copy 0\n")
     9176     (write _test-input-stream "  copy-byte-to *y, x\n")
     9177     (write _test-input-stream "}\n")
     9178     # convert
     9179     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     9180     (flush _test-output-buffered-file)
     9181     # no errors
     9182     # . epilogue
     9183     5d/pop-to-ebp
     9184     c3/return
     9185
     9186 test-copy-byte-to-from-non-scalar-inout:
     9187     # . prologue
     9188     55/push-ebp
     9189     89/<- %ebp 4/r32/esp
     9190     # setup
     9191     (clear-stream _test-input-stream)
     9192     (clear-stream $_test-input-buffered-file->buffer)
     9193     (clear-stream _test-output-stream)
     9194     (clear-stream $_test-output-buffered-file->buffer)
     9195     (clear-stream _test-error-stream)
     9196     (clear-stream $_test-error-buffered-file->buffer)
     9197     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     9198     68/push 0/imm32
     9199     68/push 0/imm32
     9200     89/<- %edx 4/r32/esp
     9201     (tailor-exit-descriptor %edx 0x10)
     9202     #
     9203     (write _test-input-stream "fn foo {\n")
     9204     (write _test-input-stream "  var x: (handle int)\n")
     9205     (write _test-input-stream "  var y/eax: (addr byte) <- copy 0\n")
     9206     (write _test-input-stream "  copy-byte-to *y, x\n")
     9207     (write _test-input-stream "}\n")
     9208     # convert
     9209     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     9210     # registers except esp clobbered at this point
     9211     # restore ed
     9212     89/<- %edx 4/r32/esp
     9213     (flush _test-output-buffered-file)
     9214     (flush _test-error-buffered-file)
     9215 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     9221     # check output
     9222     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-to-from-non-scalar-inout: output should be empty")
     9223     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt copy-byte-to: 'x' is too large to copy"  "F - test-copy-byte-to-from-non-scalar-inout: error message")
     9224     # check that stop(1) was called
     9225     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-to-from-non-scalar-inout: exit status")
     9226     # don't restore from ebp
     9227     81 0/subop/add %esp 8/imm32
     9228     # . epilogue
     9229     5d/pop-to-ebp
     9230     c3/return
     9231
     9232 test-compare-with-no-inout:
     9233     # . prologue
     9234     55/push-ebp
     9235     89/<- %ebp 4/r32/esp
     9236     # setup
     9237     (clear-stream _test-input-stream)
     9238     (clear-stream $_test-input-buffered-file->buffer)
     9239     (clear-stream _test-output-stream)
     9240     (clear-stream $_test-output-buffered-file->buffer)
     9241     (clear-stream _test-error-stream)
     9242     (clear-stream $_test-error-buffered-file->buffer)
     9243     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     9244     68/push 0/imm32
     9245     68/push 0/imm32
     9246     89/<- %edx 4/r32/esp
     9247     (tailor-exit-descriptor %edx 0x10)
     9248     #
     9249     (write _test-input-stream "fn foo {\n")
     9250     (write _test-input-stream "  var x: boolean\n")
     9251     (write _test-input-stream "  compare\n")
     9252     (write _test-input-stream "}\n")
     9253     # convert
     9254     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     9255     # registers except esp clobbered at this point
     9256     # restore ed
     9257     89/<- %edx 4/r32/esp
     9258     (flush _test-output-buffered-file)
     9259     (flush _test-error-buffered-file)
     9260 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     9266     # check output
     9267     (check-stream-equal _test-output-stream  ""  "F - test-compare-with-no-inout: output should be empty")
     9268     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'compare' must have two inouts"  "F - test-compare-with-no-inout: error message")
     9269     # check that stop(1) was called
     9270     (check-ints-equal *(edx+4) 2 "F - test-compare-with-no-inout: exit status")
     9271     # don't restore from ebp
     9272     81 0/subop/add %esp 8/imm32
     9273     # . epilogue
     9274     5d/pop-to-ebp
     9275     c3/return
     9276
     9277 test-compare-with-just-one-inout:
     9278     # . prologue
     9279     55/push-ebp
     9280     89/<- %ebp 4/r32/esp
     9281     # setup
     9282     (clear-stream _test-input-stream)
     9283     (clear-stream $_test-input-buffered-file->buffer)
     9284     (clear-stream _test-output-stream)
     9285     (clear-stream $_test-output-buffered-file->buffer)
     9286     (clear-stream _test-error-stream)
     9287     (clear-stream $_test-error-buffered-file->buffer)
     9288     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     9289     68/push 0/imm32
     9290     68/push 0/imm32
     9291     89/<- %edx 4/r32/esp
     9292     (tailor-exit-descriptor %edx 0x10)
     9293     #
     9294     (write _test-input-stream "fn foo {\n")
     9295     (write _test-input-stream "  var x: boolean\n")
     9296     (write _test-input-stream "  compare x\n")
     9297     (write _test-input-stream "}\n")
     9298     # convert
     9299     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     9300     # registers except esp clobbered at this point
     9301     # restore ed
     9302     89/<- %edx 4/r32/esp
     9303     (flush _test-output-buffered-file)
     9304     (flush _test-error-buffered-file)
     9305 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     9311     # check output
     9312     (check-stream-equal _test-output-stream  ""  "F - test-compare-with-just-one-inout: output should be empty")
     9313     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'compare' must have two inouts"  "F - test-compare-with-just-one-inout: error message")
     9314     # check that stop(1) was called
     9315     (check-ints-equal *(edx+4) 2 "F - test-compare-with-just-one-inout: exit status")
     9316     # don't restore from ebp
     9317     81 0/subop/add %esp 8/imm32
     9318     # . epilogue
     9319     5d/pop-to-ebp
     9320     c3/return
     9321
     9322 test-compare-with-too-many-inouts:
     9323     # . prologue
     9324     55/push-ebp
     9325     89/<- %ebp 4/r32/esp
     9326     # setup
     9327     (clear-stream _test-input-stream)
     9328     (clear-stream $_test-input-buffered-file->buffer)
     9329     (clear-stream _test-output-stream)
     9330     (clear-stream $_test-output-buffered-file->buffer)
     9331     (clear-stream _test-error-stream)
     9332     (clear-stream $_test-error-buffered-file->buffer)
     9333     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     9334     68/push 0/imm32
     9335     68/push 0/imm32
     9336     89/<- %edx 4/r32/esp
     9337     (tailor-exit-descriptor %edx 0x10)
     9338     #
     9339     (write _test-input-stream "fn foo {\n")
     9340     (write _test-input-stream "  var x: boolean\n")
     9341     (write _test-input-stream "  compare x, 0, 0\n")
     9342     (write _test-input-stream "}\n")
     9343     # convert
     9344     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     9345     # registers except esp clobbered at this point
     9346     # restore ed
     9347     89/<- %edx 4/r32/esp
     9348     (flush _test-output-buffered-file)
     9349     (flush _test-error-buffered-file)
     9350 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     9356     # check output
     9357     (check-stream-equal _test-output-stream  ""  "F - test-compare-with-too-many-inouts: output should be empty")
     9358     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'compare' must have two inouts"  "F - test-compare-with-too-many-inouts: error message")
     9359     # check that stop(1) was called
     9360     (check-ints-equal *(edx+4) 2 "F - test-compare-with-too-many-inouts: exit status")
     9361     # don't restore from ebp
     9362     81 0/subop/add %esp 8/imm32
     9363     # . epilogue
     9364     5d/pop-to-ebp
     9365     c3/return
     9366
     9367 test-compare-with-output:
     9368     # . prologue
     9369     55/push-ebp
     9370     89/<- %ebp 4/r32/esp
     9371     # setup
     9372     (clear-stream _test-input-stream)
     9373     (clear-stream $_test-input-buffered-file->buffer)
     9374     (clear-stream _test-output-stream)
     9375     (clear-stream $_test-output-buffered-file->buffer)
     9376     (clear-stream _test-error-stream)
     9377     (clear-stream $_test-error-buffered-file->buffer)
     9378     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     9379     68/push 0/imm32
     9380     68/push 0/imm32
     9381     89/<- %edx 4/r32/esp
     9382     (tailor-exit-descriptor %edx 0x10)
     9383     #
     9384     (write _test-input-stream "fn foo {\n")
     9385     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
     9386     (write _test-input-stream "  var y/ecx: boolean <- copy 0\n")
     9387     (write _test-input-stream "  x <- compare y, 0\n")
     9388     (write _test-input-stream "}\n")
     9389     # convert
     9390     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     9391     # registers except esp clobbered at this point
     9392     # restore ed
     9393     89/<- %edx 4/r32/esp
     9394     (flush _test-output-buffered-file)
     9395     (flush _test-error-buffered-file)
     9396 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     9402     # check output
     9403     (check-stream-equal _test-output-stream  ""  "F - test-compare-with-output: output should be empty")
     9404     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'compare' must not have any outputs"  "F - test-compare-with-output: error message")
     9405     # check that stop(1) was called
     9406     (check-ints-equal *(edx+4) 2 "F - test-compare-with-output: exit status")
     9407     # don't restore from ebp
     9408     81 0/subop/add %esp 8/imm32
     9409     # . epilogue
     9410     5d/pop-to-ebp
     9411     c3/return
     9412
     9413 test-compare-invalid-value-to-address:
     9414     # . prologue
     9415     55/push-ebp
     9416     89/<- %ebp 4/r32/esp
     9417     # setup
     9418     (clear-stream _test-input-stream)
     9419     (clear-stream $_test-input-buffered-file->buffer)
     9420     (clear-stream _test-output-stream)
     9421     (clear-stream $_test-output-buffered-file->buffer)
     9422     (clear-stream _test-error-stream)
     9423     (clear-stream $_test-error-buffered-file->buffer)
     9424     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     9425     68/push 0/imm32
     9426     68/push 0/imm32
     9427     89/<- %edx 4/r32/esp
     9428     (tailor-exit-descriptor %edx 0x10)
     9429     #
     9430     (write _test-input-stream "fn foo {\n")
     9431     (write _test-input-stream "  var x/eax: int <- copy 0\n")
     9432     (write _test-input-stream "  var y: (addr int)\n")
     9433     (write _test-input-stream "  compare y, x\n")
     9434     (write _test-input-stream "}\n")
     9435     # convert
     9436     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     9437     # registers except esp clobbered at this point
     9438     # restore ed
     9439     89/<- %edx 4/r32/esp
     9440     (flush _test-output-buffered-file)
     9441     (flush _test-error-buffered-file)
     9442 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     9448     # check output
     9449     (check-stream-equal _test-output-stream  ""  "F - test-compare-invalid-value-to-address: output should be empty")
     9450     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt compare: 'y' must be a non-addr non-offset scalar"  "F - test-compare-invalid-value-to-address: error message")
     9451     # check that stop(1) was called
     9452     (check-ints-equal *(edx+4) 2 "F - test-compare-invalid-value-to-address: exit status")
     9453     # don't restore from ebp
     9454     81 0/subop/add %esp 8/imm32
     9455     # . epilogue
     9456     5d/pop-to-ebp
     9457     c3/return
     9458
     9459 test-compare-address:
     9460     # . prologue
     9461     55/push-ebp
     9462     89/<- %ebp 4/r32/esp
     9463     # setup
     9464     (clear-stream _test-input-stream)
     9465     (clear-stream $_test-input-buffered-file->buffer)
     9466     (clear-stream _test-output-stream)
     9467     (clear-stream $_test-output-buffered-file->buffer)
     9468     #
     9469     (write _test-input-stream "fn foo {\n")
     9470     (write _test-input-stream "  var x/eax: (addr int) <- copy 0\n")
     9471     (write _test-input-stream "  var y/ecx: (addr int) <- copy 0\n")
     9472     (write _test-input-stream "  compare y, x\n")
     9473     (write _test-input-stream "}\n")
     9474     # convert
     9475     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     9476     (flush _test-output-buffered-file)
     9477     # no errors
     9478     # . epilogue
     9479     5d/pop-to-ebp
     9480     c3/return
     9481
     9482 test-compare-deref-address:
     9483     # . prologue
     9484     55/push-ebp
     9485     89/<- %ebp 4/r32/esp
     9486     # setup
     9487     (clear-stream _test-input-stream)
     9488     (clear-stream $_test-input-buffered-file->buffer)
     9489     (clear-stream _test-output-stream)
     9490     (clear-stream $_test-output-buffered-file->buffer)
     9491     #
     9492     (write _test-input-stream "fn foo {\n")
     9493     (write _test-input-stream "  var x/eax: (addr int) <- copy 0\n")
     9494     (write _test-input-stream "  var y/ecx: (addr addr int) <- copy 0\n")
     9495     (write _test-input-stream "  compare *y, x\n")
     9496     (write _test-input-stream "}\n")
     9497     # convert
     9498     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     9499     (flush _test-output-buffered-file)
     9500     # no errors
     9501     # . epilogue
     9502     5d/pop-to-ebp
     9503     c3/return
     9504
     9505 test-compare-two-vars-in-memory:
     9506     # . prologue
     9507     55/push-ebp
     9508     89/<- %ebp 4/r32/esp
     9509     # setup
     9510     (clear-stream _test-input-stream)
     9511     (clear-stream $_test-input-buffered-file->buffer)
     9512     (clear-stream _test-output-stream)
     9513     (clear-stream $_test-output-buffered-file->buffer)
     9514     (clear-stream _test-error-stream)
     9515     (clear-stream $_test-error-buffered-file->buffer)
     9516     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     9517     68/push 0/imm32
     9518     68/push 0/imm32
     9519     89/<- %edx 4/r32/esp
     9520     (tailor-exit-descriptor %edx 0x10)
     9521     #
     9522     (write _test-input-stream "fn foo {\n")
     9523     (write _test-input-stream "  var x: boolean\n")
     9524     (write _test-input-stream "  compare x, x\n")
     9525     (write _test-input-stream "}\n")
     9526     # convert
     9527     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     9528     # registers except esp clobbered at this point
     9529     # restore ed
     9530     89/<- %edx 4/r32/esp
     9531     (flush _test-output-buffered-file)
     9532     (flush _test-error-buffered-file)
     9533 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     9539     # check output
     9540     (check-stream-equal _test-output-stream  ""  "F - test-compare-two-vars-in-memory: output should be empty")
     9541     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt compare: both inouts are in memory"  "F - test-compare-two-vars-in-memory: error message")
     9542     # check that stop(1) was called
     9543     (check-ints-equal *(edx+4) 2 "F - test-compare-two-vars-in-memory: exit status")
     9544     # don't restore from ebp
     9545     81 0/subop/add %esp 8/imm32
     9546     # . epilogue
     9547     5d/pop-to-ebp
     9548     c3/return
     9549
     9550 test-compare-non-scalar:
     9551     # . prologue
     9552     55/push-ebp
     9553     89/<- %ebp 4/r32/esp
     9554     # setup
     9555     (clear-stream _test-input-stream)
     9556     (clear-stream $_test-input-buffered-file->buffer)
     9557     (clear-stream _test-output-stream)
     9558     (clear-stream $_test-output-buffered-file->buffer)
     9559     (clear-stream _test-error-stream)
     9560     (clear-stream $_test-error-buffered-file->buffer)
     9561     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     9562     68/push 0/imm32
     9563     68/push 0/imm32
     9564     89/<- %edx 4/r32/esp
     9565     (tailor-exit-descriptor %edx 0x10)
     9566     #
     9567     (write _test-input-stream "fn foo {\n")
     9568     (write _test-input-stream "  var x: (handle int)\n")
     9569     (write _test-input-stream "  var y: int\n")
     9570     (write _test-input-stream "  compare y, x\n")
     9571     (write _test-input-stream "}\n")
     9572     # convert
     9573     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     9574     # registers except esp clobbered at this point
     9575     # restore ed
     9576     89/<- %edx 4/r32/esp
     9577     (flush _test-output-buffered-file)
     9578     (flush _test-error-buffered-file)
     9579 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     9585     # check output
     9586     (check-stream-equal _test-output-stream  ""  "F - test-compare-non-scalar: output should be empty")
     9587 #?     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt compare: 'x' is too large to compare"  "F - test-compare-non-scalar: error message")
     9588     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt compare: both inouts are in memory"  "F - test-compare-non-scalar: error message")
     9589     # check that stop(1) was called
     9590     (check-ints-equal *(edx+4) 2 "F - test-compare-non-scalar: exit status")
     9591     # don't restore from ebp
     9592     81 0/subop/add %esp 8/imm32
     9593     # . epilogue
     9594     5d/pop-to-ebp
     9595     c3/return
     9596
     9597 test-compare-with-string-literal:
     9598     # . prologue
     9599     55/push-ebp
     9600     89/<- %ebp 4/r32/esp
     9601     # setup
     9602     (clear-stream _test-input-stream)
     9603     (clear-stream $_test-input-buffered-file->buffer)
     9604     (clear-stream _test-output-stream)
     9605     (clear-stream $_test-output-buffered-file->buffer)
     9606     (clear-stream _test-error-stream)
     9607     (clear-stream $_test-error-buffered-file->buffer)
     9608     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     9609     68/push 0/imm32
     9610     68/push 0/imm32
     9611     89/<- %edx 4/r32/esp
     9612     (tailor-exit-descriptor %edx 0x10)
     9613     #
     9614     (write _test-input-stream "fn foo {\n")
     9615     (write _test-input-stream "  var x/eax: (addr array byte) <- copy 0\n")
     9616     (write _test-input-stream "  compare x, \"abc\"\n")
     9617     (write _test-input-stream "}\n")
     9618     # convert
     9619     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     9620     # registers except esp clobbered at this point
     9621     # restore ed
     9622     89/<- %edx 4/r32/esp
     9623     (flush _test-output-buffered-file)
     9624     (flush _test-error-buffered-file)
     9625 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     9631     # check output
     9632     (check-stream-equal _test-output-stream  ""  "F - test-compare-with-string-literal: output should be empty")
     9633     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt compare: string literal \"abc\" is not supported; use the string-equal? function"  "F - test-compare-with-string-literal: error message")
     9634     # check that stop(1) was called
     9635     (check-ints-equal *(edx+4) 2 "F - test-compare-with-string-literal: exit status")
     9636     # don't restore from ebp
     9637     81 0/subop/add %esp 8/imm32
     9638     # . epilogue
     9639     5d/pop-to-ebp
     9640     c3/return
     9641
     9642 test-address-with-no-inout:
     9643     # . prologue
     9644     55/push-ebp
     9645     89/<- %ebp 4/r32/esp
     9646     # setup
     9647     (clear-stream _test-input-stream)
     9648     (clear-stream $_test-input-buffered-file->buffer)
     9649     (clear-stream _test-output-stream)
     9650     (clear-stream $_test-output-buffered-file->buffer)
     9651     (clear-stream _test-error-stream)
     9652     (clear-stream $_test-error-buffered-file->buffer)
     9653     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     9654     68/push 0/imm32
     9655     68/push 0/imm32
     9656     89/<- %edx 4/r32/esp
     9657     (tailor-exit-descriptor %edx 0x10)
     9658     #
     9659     (write _test-input-stream "fn foo {\n")
     9660     (write _test-input-stream "  var x/eax: boolean <- address\n")
     9661     (write _test-input-stream "}\n")
     9662     # convert
     9663     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     9664     # registers except esp clobbered at this point
     9665     # restore ed
     9666     89/<- %edx 4/r32/esp
     9667     (flush _test-output-buffered-file)
     9668     (flush _test-error-buffered-file)
     9669 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     9675     # check output
     9676     (check-stream-equal _test-output-stream  ""  "F - test-address-with-no-inout: output should be empty")
     9677     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'address' expects an inout"  "F - test-address-with-no-inout: error message")
     9678     # check that stop(1) was called
     9679     (check-ints-equal *(edx+4) 2 "F - test-address-with-no-inout: exit status")
     9680     # don't restore from ebp
     9681     81 0/subop/add %esp 8/imm32
     9682     # . epilogue
     9683     5d/pop-to-ebp
     9684     c3/return
     9685
     9686 test-address-with-multiple-inouts:
     9687     # . prologue
     9688     55/push-ebp
     9689     89/<- %ebp 4/r32/esp
     9690     # setup
     9691     (clear-stream _test-input-stream)
     9692     (clear-stream $_test-input-buffered-file->buffer)
     9693     (clear-stream _test-output-stream)
     9694     (clear-stream $_test-output-buffered-file->buffer)
     9695     (clear-stream _test-error-stream)
     9696     (clear-stream $_test-error-buffered-file->buffer)
     9697     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     9698     68/push 0/imm32
     9699     68/push 0/imm32
     9700     89/<- %edx 4/r32/esp
     9701     (tailor-exit-descriptor %edx 0x10)
     9702     #
     9703     (write _test-input-stream "fn foo {\n")
     9704     (write _test-input-stream "  var x/eax: boolean <- address 0, 0\n")
     9705     (write _test-input-stream "}\n")
     9706     # convert
     9707     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     9708     # registers except esp clobbered at this point
     9709     # restore ed
     9710     89/<- %edx 4/r32/esp
     9711     (flush _test-output-buffered-file)
     9712     (flush _test-error-buffered-file)
     9713 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     9719     # check output
     9720     (check-stream-equal _test-output-stream  ""  "F - test-address-with-multiple-inouts: output should be empty")
     9721     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'address' must have just one inout"  "F - test-address-with-multiple-inouts: error message")
     9722     # check that stop(1) was called
     9723     (check-ints-equal *(edx+4) 2 "F - test-address-with-multiple-inouts: exit status")
     9724     # don't restore from ebp
     9725     81 0/subop/add %esp 8/imm32
     9726     # . epilogue
     9727     5d/pop-to-ebp
     9728     c3/return
     9729
     9730 test-address-with-no-output:
     9731     # . prologue
     9732     55/push-ebp
     9733     89/<- %ebp 4/r32/esp
     9734     # setup
     9735     (clear-stream _test-input-stream)
     9736     (clear-stream $_test-input-buffered-file->buffer)
     9737     (clear-stream _test-output-stream)
     9738     (clear-stream $_test-output-buffered-file->buffer)
     9739     (clear-stream _test-error-stream)
     9740     (clear-stream $_test-error-buffered-file->buffer)
     9741     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     9742     68/push 0/imm32
     9743     68/push 0/imm32
     9744     89/<- %edx 4/r32/esp
     9745     (tailor-exit-descriptor %edx 0x10)
     9746     #
     9747     (write _test-input-stream "fn foo {\n")
     9748     (write _test-input-stream "  address 0\n")
     9749     (write _test-input-stream "}\n")
     9750     # convert
     9751     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     9752     # registers except esp clobbered at this point
     9753     # restore ed
     9754     89/<- %edx 4/r32/esp
     9755     (flush _test-output-buffered-file)
     9756     (flush _test-error-buffered-file)
     9757 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     9763     # check output
     9764     (check-stream-equal _test-output-stream  ""  "F - test-address-with-no-output: output should be empty")
     9765     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'address' expects an output"  "F - test-address-with-no-output: error message")
     9766     # check that stop(1) was called
     9767     (check-ints-equal *(edx+4) 2 "F - test-address-with-no-output: exit status")
     9768     # don't restore from ebp
     9769     81 0/subop/add %esp 8/imm32
     9770     # . epilogue
     9771     5d/pop-to-ebp
     9772     c3/return
     9773
     9774 test-address-with-multiple-outputs:
     9775     # . prologue
     9776     55/push-ebp
     9777     89/<- %ebp 4/r32/esp
     9778     # setup
     9779     (clear-stream _test-input-stream)
     9780     (clear-stream $_test-input-buffered-file->buffer)
     9781     (clear-stream _test-output-stream)
     9782     (clear-stream $_test-output-buffered-file->buffer)
     9783     (clear-stream _test-error-stream)
     9784     (clear-stream $_test-error-buffered-file->buffer)
     9785     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     9786     68/push 0/imm32
     9787     68/push 0/imm32
     9788     89/<- %edx 4/r32/esp
     9789     (tailor-exit-descriptor %edx 0x10)
     9790     #
     9791     (write _test-input-stream "fn foo {\n")
     9792     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
     9793     (write _test-input-stream "  var y/ecx: boolean <- copy 0\n")
     9794     (write _test-input-stream "  x, y <- address 0\n")
     9795     (write _test-input-stream "}\n")
     9796     # convert
     9797     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     9798     # registers except esp clobbered at this point
     9799     # restore ed
     9800     89/<- %edx 4/r32/esp
     9801     (flush _test-output-buffered-file)
     9802     (flush _test-error-buffered-file)
     9803 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     9809     # check output
     9810     (check-stream-equal _test-output-stream  ""  "F - test-address-with-multiple-outputs: output should be empty")
     9811     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'address' must have just one output"  "F - test-address-with-multiple-outputs: error message")
     9812     # check that stop(1) was called
     9813     (check-ints-equal *(edx+4) 2 "F - test-address-with-multiple-outputs: exit status")
     9814     # don't restore from ebp
     9815     81 0/subop/add %esp 8/imm32
     9816     # . epilogue
     9817     5d/pop-to-ebp
     9818     c3/return
     9819
     9820 # silly but it works
     9821 test-address-of-deref:
     9822     # . prologue
     9823     55/push-ebp
     9824     89/<- %ebp 4/r32/esp
     9825     # setup
     9826     (clear-stream _test-input-stream)
     9827     (clear-stream $_test-input-buffered-file->buffer)
     9828     (clear-stream _test-output-stream)
     9829     (clear-stream $_test-output-buffered-file->buffer)
     9830     #
     9831     (write _test-input-stream "fn foo {\n")
     9832     (write _test-input-stream "  var x/eax: (addr int) <- copy 0\n")
     9833     (write _test-input-stream "  var y/ecx: (addr int) <- address *x\n")
     9834     (write _test-input-stream "}\n")
     9835     # convert
     9836     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     9837     (flush _test-output-buffered-file)
     9838     # no errors
     9839     # . epilogue
     9840     5d/pop-to-ebp
     9841     c3/return
     9842
     9843 test-address-to-non-register:
     9844     # . prologue
     9845     55/push-ebp
     9846     89/<- %ebp 4/r32/esp
     9847     # setup
     9848     (clear-stream _test-input-stream)
     9849     (clear-stream $_test-input-buffered-file->buffer)
     9850     (clear-stream _test-output-stream)
     9851     (clear-stream $_test-output-buffered-file->buffer)
     9852     (clear-stream _test-error-stream)
     9853     (clear-stream $_test-error-buffered-file->buffer)
     9854     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     9855     68/push 0/imm32
     9856     68/push 0/imm32
     9857     89/<- %edx 4/r32/esp
     9858     (tailor-exit-descriptor %edx 0x10)
     9859     #
     9860     (write _test-input-stream "fn foo {\n")
     9861     (write _test-input-stream "  var x: (addr int)\n")
     9862     (write _test-input-stream "  x <- address 0\n")
     9863     (write _test-input-stream "}\n")
     9864     # convert
     9865     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     9866     # registers except esp clobbered at this point
     9867     # restore ed
     9868     89/<- %edx 4/r32/esp
     9869     (flush _test-output-buffered-file)
     9870     (flush _test-error-buffered-file)
     9871 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     9877     # check output
     9878     (check-stream-equal _test-output-stream  ""  "F - test-address-to-non-register: output should be empty")
     9879     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt address: output 'x' not in a register"  "F - test-address-to-non-register: error message")
     9880     # check that stop(1) was called
     9881     (check-ints-equal *(edx+4) 2 "F - test-address-to-non-register: exit status")
     9882     # don't restore from ebp
     9883     81 0/subop/add %esp 8/imm32
     9884     # . epilogue
     9885     5d/pop-to-ebp
     9886     c3/return
     9887
     9888 test-address-with-wrong-type:
     9889     # . prologue
     9890     55/push-ebp
     9891     89/<- %ebp 4/r32/esp
     9892     # setup
     9893     (clear-stream _test-input-stream)
     9894     (clear-stream $_test-input-buffered-file->buffer)
     9895     (clear-stream _test-output-stream)
     9896     (clear-stream $_test-output-buffered-file->buffer)
     9897     (clear-stream _test-error-stream)
     9898     (clear-stream $_test-error-buffered-file->buffer)
     9899     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     9900     68/push 0/imm32
     9901     68/push 0/imm32
     9902     89/<- %edx 4/r32/esp
     9903     (tailor-exit-descriptor %edx 0x10)
     9904     #
     9905     (write _test-input-stream "fn foo {\n")
     9906     (write _test-input-stream "  var x: int\n")
     9907     (write _test-input-stream "  var y/eax: (addr boolean) <- address x\n")
     9908     (write _test-input-stream "}\n")
     9909     # convert
     9910     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     9911     # registers except esp clobbered at this point
     9912     # restore ed
     9913     89/<- %edx 4/r32/esp
     9914     (flush _test-output-buffered-file)
     9915     (flush _test-error-buffered-file)
     9916 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     9922     # check output
     9923     (check-stream-equal _test-output-stream  ""  "F - test-address-with-wrong-type: output should be empty")
     9924     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt address: output 'y' cannot hold address of 'x'"  "F - test-address-with-wrong-type: error message")
     9925     # check that stop(1) was called
     9926     (check-ints-equal *(edx+4) 2 "F - test-address-with-wrong-type: exit status")
     9927     # don't restore from ebp
     9928     81 0/subop/add %esp 8/imm32
     9929     # . epilogue
     9930     5d/pop-to-ebp
     9931     c3/return
     9932
     9933 test-address-with-right-type-for-array:
     9934     # . prologue
     9935     55/push-ebp
     9936     89/<- %ebp 4/r32/esp
     9937     # setup
     9938     (clear-stream _test-input-stream)
     9939     (clear-stream $_test-input-buffered-file->buffer)
     9940     (clear-stream _test-output-stream)
     9941     (clear-stream $_test-output-buffered-file->buffer)
     9942     #
     9943     (write _test-input-stream "fn foo {\n")
     9944     (write _test-input-stream "  var x: (array int 3)\n")
     9945     (write _test-input-stream "  var y/eax: (addr array int) <- address x\n")
     9946     (write _test-input-stream "}\n")
     9947     # convert
     9948     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     9949     (flush _test-output-buffered-file)
     9950     # no errors
     9951     # . epilogue
     9952     89/<- %esp 5/r32/ebp
     9953     5d/pop-to-ebp
     9954     c3/return
     9955
     9956 test-address-with-right-type-for-stream:
     9957     # . prologue
     9958     55/push-ebp
     9959     89/<- %ebp 4/r32/esp
     9960     # setup
     9961     (clear-stream _test-input-stream)
     9962     (clear-stream $_test-input-buffered-file->buffer)
     9963     (clear-stream _test-output-stream)
     9964     (clear-stream $_test-output-buffered-file->buffer)
     9965     #
     9966     (write _test-input-stream "fn foo {\n")
     9967     (write _test-input-stream "  var x: (stream int 3)\n")
     9968     (write _test-input-stream "  var y/eax: (addr stream int) <- address x\n")
     9969     (write _test-input-stream "}\n")
     9970     # convert
     9971     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     9972     (flush _test-output-buffered-file)
     9973     # no errors
     9974     # . epilogue
     9975     89/<- %esp 5/r32/ebp
     9976     5d/pop-to-ebp
     9977     c3/return
     9978
     9979 test-get-with-wrong-field:
     9980     # . prologue
     9981     55/push-ebp
     9982     89/<- %ebp 4/r32/esp
     9983     # setup
     9984     (clear-stream _test-input-stream)
     9985     (clear-stream $_test-input-buffered-file->buffer)
     9986     (clear-stream _test-output-stream)
     9987     (clear-stream $_test-output-buffered-file->buffer)
     9988     (clear-stream _test-error-stream)
     9989     (clear-stream $_test-error-buffered-file->buffer)
     9990     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     9991     68/push 0/imm32
     9992     68/push 0/imm32
     9993     89/<- %edx 4/r32/esp
     9994     (tailor-exit-descriptor %edx 0x10)
     9995     #
     9996     (write _test-input-stream "fn foo {\n")
     9997     (write _test-input-stream "  var a: t\n")
     9998     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
     9999     (write _test-input-stream "}\n")
    10000     (write _test-input-stream "type t {\n")
    10001     (write _test-input-stream "  x: int\n")
    10002     (write _test-input-stream "}\n")
    10003     # convert
    10004     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    10005     # registers except esp clobbered at this point
    10006     # restore ed
    10007     89/<- %edx 4/r32/esp
    10008     (flush _test-output-buffered-file)
    10009     (flush _test-error-buffered-file)
    10010 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    10016     # check output
    10017     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-field: output should be empty")
    10018     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt get: type 't' has no member called 'y'"  "F - test-get-with-wrong-field: error message")
    10019     # check that stop(1) was called
    10020     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-field: exit status")
    10021     # don't restore from ebp
    10022     81 0/subop/add %esp 8/imm32
    10023     # . epilogue
    10024     5d/pop-to-ebp
    10025     c3/return
    10026
    10027 test-get-with-wrong-base-type:
    10028     # . prologue
    10029     55/push-ebp
    10030     89/<- %ebp 4/r32/esp
    10031     # setup
    10032     (clear-stream _test-input-stream)
    10033     (clear-stream $_test-input-buffered-file->buffer)
    10034     (clear-stream _test-output-stream)
    10035     (clear-stream $_test-output-buffered-file->buffer)
    10036     (clear-stream _test-error-stream)
    10037     (clear-stream $_test-error-buffered-file->buffer)
    10038     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    10039     68/push 0/imm32
    10040     68/push 0/imm32
    10041     89/<- %edx 4/r32/esp
    10042     (tailor-exit-descriptor %edx 0x10)
    10043     #
    10044     (write _test-input-stream "fn foo {\n")
    10045     (write _test-input-stream "  var a: int\n")
    10046     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
    10047     (write _test-input-stream "}\n")
    10048     # convert
    10049     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    10050     # registers except esp clobbered at this point
    10051     # restore ed
    10052     89/<- %edx 4/r32/esp
    10053     (flush _test-output-buffered-file)
    10054     (flush _test-error-buffered-file)
    10055 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    10061     # check output
    10062     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-base-type: output should be empty")
    10063     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt get: var 'a' must have a 'type' definition"  "F - test-get-with-wrong-base-type: error message")
    10064     # check that stop(1) was called
    10065     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-base-type: exit status")
    10066     # don't restore from ebp
    10067     81 0/subop/add %esp 8/imm32
    10068     # . epilogue
    10069     5d/pop-to-ebp
    10070     c3/return
    10071
    10072 test-get-with-wrong-base-type-2:
    10073     # . prologue
    10074     55/push-ebp
    10075     89/<- %ebp 4/r32/esp
    10076     # setup
    10077     (clear-stream _test-input-stream)
    10078     (clear-stream $_test-input-buffered-file->buffer)
    10079     (clear-stream _test-output-stream)
    10080     (clear-stream $_test-output-buffered-file->buffer)
    10081     (clear-stream _test-error-stream)
    10082     (clear-stream $_test-error-buffered-file->buffer)
    10083     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    10084     68/push 0/imm32
    10085     68/push 0/imm32
    10086     89/<- %edx 4/r32/esp
    10087     (tailor-exit-descriptor %edx 0x10)
    10088     #
    10089     (write _test-input-stream "fn foo {\n")
    10090     (write _test-input-stream "  var a: (addr t)\n")
    10091     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
    10092     (write _test-input-stream "}\n")
    10093     (write _test-input-stream "type t {\n")
    10094     (write _test-input-stream "  x: int\n")
    10095     (write _test-input-stream "}\n")
    10096     # convert
    10097     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    10098     # registers except esp clobbered at this point
    10099     # restore ed
    10100     89/<- %edx 4/r32/esp
    10101     (flush _test-output-buffered-file)
    10102     (flush _test-error-buffered-file)
    10103 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    10109     # check output
    10110     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-base-type-2: output should be empty")
    10111     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt get: var 'a' is an 'addr' type, and so must live in a register"  "F - test-get-with-wrong-base-type-2: error message")
    10112     # check that stop(1) was called
    10113     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-base-type-2: exit status")
    10114     # don't restore from ebp
    10115     81 0/subop/add %esp 8/imm32
    10116     # . epilogue
    10117     5d/pop-to-ebp
    10118     c3/return
    10119
    10120 test-get-with-wrong-base-type-3:
    10121     # . prologue
    10122     55/push-ebp
    10123     89/<- %ebp 4/r32/esp
    10124     # setup
    10125     (clear-stream _test-input-stream)
    10126     (clear-stream $_test-input-buffered-file->buffer)
    10127     (clear-stream _test-output-stream)
    10128     (clear-stream $_test-output-buffered-file->buffer)
    10129     (clear-stream _test-error-stream)
    10130     (clear-stream $_test-error-buffered-file->buffer)
    10131     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    10132     68/push 0/imm32
    10133     68/push 0/imm32
    10134     89/<- %edx 4/r32/esp
    10135     (tailor-exit-descriptor %edx 0x10)
    10136     #
    10137     (write _test-input-stream "fn foo {\n")
    10138     (write _test-input-stream "  var a: (handle int)\n")
    10139     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
    10140     (write _test-input-stream "}\n")
    10141     # convert
    10142     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    10143     # registers except esp clobbered at this point
    10144     # restore ed
    10145     89/<- %edx 4/r32/esp
    10146     (flush _test-output-buffered-file)
    10147     (flush _test-error-buffered-file)
    10148 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    10154     # check output
    10155     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-base-type-3: output should be empty")
    10156     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt get: var 'a' must have a 'type' definition"  "F - test-get-with-wrong-base-type-3: error message")
    10157     # check that stop(1) was called
    10158     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-base-type-3: exit status")
    10159     # don't restore from ebp
    10160     81 0/subop/add %esp 8/imm32
    10161     # . epilogue
    10162     5d/pop-to-ebp
    10163     c3/return
    10164
    10165 test-get-with-wrong-offset-type:
    10166     # . prologue
    10167     55/push-ebp
    10168     89/<- %ebp 4/r32/esp
    10169     # setup
    10170     (clear-stream _test-input-stream)
    10171     (clear-stream $_test-input-buffered-file->buffer)
    10172     (clear-stream _test-output-stream)
    10173     (clear-stream $_test-output-buffered-file->buffer)
    10174     (clear-stream _test-error-stream)
    10175     (clear-stream $_test-error-buffered-file->buffer)
    10176     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    10177     68/push 0/imm32
    10178     68/push 0/imm32
    10179     89/<- %edx 4/r32/esp
    10180     (tailor-exit-descriptor %edx 0x10)
    10181     #
    10182     (write _test-input-stream "fn foo {\n")
    10183     (write _test-input-stream "  var a: t\n")
    10184     (write _test-input-stream "  var b: int\n")
    10185     (write _test-input-stream "  var c/ecx: (addr int) <- get a, b\n")
    10186     (write _test-input-stream "}\n")
    10187     (write _test-input-stream "type t {\n")
    10188     (write _test-input-stream "  x: int\n")
    10189     (write _test-input-stream "}\n")
    10190     # convert
    10191     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    10192     # registers except esp clobbered at this point
    10193     # restore ed
    10194     89/<- %edx 4/r32/esp
    10195     (flush _test-output-buffered-file)
    10196     (flush _test-error-buffered-file)
    10197 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    10203     # check output
    10204     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-offset-type: output should be empty")
    10205     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt get: type 't' has no member called 'b'"  "F - test-get-with-wrong-offset-type: error message")
    10206     # check that stop(1) was called
    10207     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-offset-type: exit status")
    10208     # don't restore from ebp
    10209     81 0/subop/add %esp 8/imm32
    10210     # . epilogue
    10211     5d/pop-to-ebp
    10212     c3/return
    10213
    10214 test-get-with-wrong-output-type:
    10215     # . prologue
    10216     55/push-ebp
    10217     89/<- %ebp 4/r32/esp
    10218     # setup
    10219     (clear-stream _test-input-stream)
    10220     (clear-stream $_test-input-buffered-file->buffer)
    10221     (clear-stream _test-output-stream)
    10222     (clear-stream $_test-output-buffered-file->buffer)
    10223     (clear-stream _test-error-stream)
    10224     (clear-stream $_test-error-buffered-file->buffer)
    10225     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    10226     68/push 0/imm32
    10227     68/push 0/imm32
    10228     89/<- %edx 4/r32/esp
    10229     (tailor-exit-descriptor %edx 0x10)
    10230     #
    10231     (write _test-input-stream "fn foo {\n")
    10232     (write _test-input-stream "  var a: t\n")
    10233     (write _test-input-stream "  var c: (addr int)\n")
    10234     (write _test-input-stream "  c <- get a, x\n")
    10235     (write _test-input-stream "}\n")
    10236     (write _test-input-stream "type t {\n")
    10237     (write _test-input-stream "  x: int\n")
    10238     (write _test-input-stream "}\n")
    10239     # convert
    10240     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    10241     # registers except esp clobbered at this point
    10242     # restore ed
    10243     89/<- %edx 4/r32/esp
    10244     (flush _test-output-buffered-file)
    10245     (flush _test-error-buffered-file)
    10246 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    10252     # check output
    10253     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-output-type: output should be empty")
    10254     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt get: output 'c' is not in a register"  "F - test-get-with-wrong-output-type: error message")
    10255     # check that stop(1) was called
    10256     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-output-type: exit status")
    10257     # don't restore from ebp
    10258     81 0/subop/add %esp 8/imm32
    10259     # . epilogue
    10260     5d/pop-to-ebp
    10261     c3/return
    10262
    10263 test-get-with-wrong-output-type-2:
    10264     # . prologue
    10265     55/push-ebp
    10266     89/<- %ebp 4/r32/esp
    10267     # setup
    10268     (clear-stream _test-input-stream)
    10269     (clear-stream $_test-input-buffered-file->buffer)
    10270     (clear-stream _test-output-stream)
    10271     (clear-stream $_test-output-buffered-file->buffer)
    10272     (clear-stream _test-error-stream)
    10273     (clear-stream $_test-error-buffered-file->buffer)
    10274     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    10275     68/push 0/imm32
    10276     68/push 0/imm32
    10277     89/<- %edx 4/r32/esp
    10278     (tailor-exit-descriptor %edx 0x10)
    10279     #
    10280     (write _test-input-stream "fn foo {\n")
    10281     (write _test-input-stream "  var a: t\n")
    10282     (write _test-input-stream "  var c/ecx: int <- get a, x\n")
    10283     (write _test-input-stream "}\n")
    10284     (write _test-input-stream "type t {\n")
    10285     (write _test-input-stream "  x: int\n")
    10286     (write _test-input-stream "}\n")
    10287     # convert
    10288     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    10289     # registers except esp clobbered at this point
    10290     # restore ed
    10291     89/<- %edx 4/r32/esp
    10292     (flush _test-output-buffered-file)
    10293     (flush _test-error-buffered-file)
    10294 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    10300     # check output
    10301     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-output-type-2: output should be empty")
    10302     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt get: output must be an addr"  "F - test-get-with-wrong-output-type-2: error message")
    10303     # check that stop(1) was called
    10304     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-output-type-2: exit status")
    10305     # don't restore from ebp
    10306     81 0/subop/add %esp 8/imm32
    10307     # . epilogue
    10308     5d/pop-to-ebp
    10309     c3/return
    10310
    10311 test-get-with-wrong-output-type-3:
    10312     # . prologue
    10313     55/push-ebp
    10314     89/<- %ebp 4/r32/esp
    10315     # setup
    10316     (clear-stream _test-input-stream)
    10317     (clear-stream $_test-input-buffered-file->buffer)
    10318     (clear-stream _test-output-stream)
    10319     (clear-stream $_test-output-buffered-file->buffer)
    10320     (clear-stream _test-error-stream)
    10321     (clear-stream $_test-error-buffered-file->buffer)
    10322     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    10323     68/push 0/imm32
    10324     68/push 0/imm32
    10325     89/<- %edx 4/r32/esp
    10326     (tailor-exit-descriptor %edx 0x10)
    10327     #
    10328     (write _test-input-stream "fn foo {\n")
    10329     (write _test-input-stream "  var a: t\n")
    10330     (write _test-input-stream "  var c/ecx: (array int) <- get a, x\n")
    10331     (write _test-input-stream "}\n")
    10332     (write _test-input-stream "type t {\n")
    10333     (write _test-input-stream "  x: int\n")
    10334     (write _test-input-stream "}\n")
    10335     # convert
    10336     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    10337     # registers except esp clobbered at this point
    10338     # restore ed
    10339     89/<- %edx 4/r32/esp
    10340     (flush _test-output-buffered-file)
    10341     (flush _test-error-buffered-file)
    10342 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    10348     # check output
    10349     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-output-type-3: output should be empty")
    10350     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt get: output must be an addr"  "F - test-get-with-wrong-output-type-3: error message")
    10351     # check that stop(1) was called
    10352     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-output-type-3: exit status")
    10353     # don't restore from ebp
    10354     81 0/subop/add %esp 8/imm32
    10355     # . epilogue
    10356     5d/pop-to-ebp
    10357     c3/return
    10358
    10359 test-get-with-wrong-output-type-4:
    10360     # . prologue
    10361     55/push-ebp
    10362     89/<- %ebp 4/r32/esp
    10363     # setup
    10364     (clear-stream _test-input-stream)
    10365     (clear-stream $_test-input-buffered-file->buffer)
    10366     (clear-stream _test-output-stream)
    10367     (clear-stream $_test-output-buffered-file->buffer)
    10368     (clear-stream _test-error-stream)
    10369     (clear-stream $_test-error-buffered-file->buffer)
    10370     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    10371     68/push 0/imm32
    10372     68/push 0/imm32
    10373     89/<- %edx 4/r32/esp
    10374     (tailor-exit-descriptor %edx 0x10)
    10375     #
    10376     (write _test-input-stream "fn foo {\n")
    10377     (write _test-input-stream "  var a: t\n")
    10378     (write _test-input-stream "  var c/ecx: (addr boolean) <- get a, x\n")
    10379     (write _test-input-stream "}\n")
    10380     (write _test-input-stream "type t {\n")
    10381     (write _test-input-stream "  x: int\n")
    10382     (write _test-input-stream "}\n")
    10383     # convert
    10384     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    10385     # registers except esp clobbered at this point
    10386     # restore ed
    10387     89/<- %edx 4/r32/esp
    10388     (flush _test-output-buffered-file)
    10389     (flush _test-error-buffered-file)
    10390 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    10396     # check output
    10397     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-output-type-4: output should be empty")
    10398     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt get: wrong output type for member 'x' of type 't'"  "F - test-get-with-wrong-output-type-4: error message")
    10399     # check that stop(1) was called
    10400     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-output-type-4: exit status")
    10401     # don't restore from ebp
    10402     81 0/subop/add %esp 8/imm32
    10403     # . epilogue
    10404     5d/pop-to-ebp
    10405     c3/return
    10406
    10407 test-get-with-wrong-output-type-5:
    10408     # . prologue
    10409     55/push-ebp
    10410     89/<- %ebp 4/r32/esp
    10411     # setup
    10412     (clear-stream _test-input-stream)
    10413     (clear-stream $_test-input-buffered-file->buffer)
    10414     (clear-stream _test-output-stream)
    10415     (clear-stream $_test-output-buffered-file->buffer)
    10416     #
    10417     (write _test-input-stream "fn foo {\n")
    10418     (write _test-input-stream "  var a: t\n")
    10419     (write _test-input-stream "  var c/ecx: (addr handle int) <- get a, x\n")
    10420     (write _test-input-stream "}\n")
    10421     (write _test-input-stream "type t {\n")
    10422     (write _test-input-stream "  x: (handle int)\n")
    10423     (write _test-input-stream "}\n")
    10424     # convert
    10425     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
    10426     (flush _test-output-buffered-file)
    10427     # no errors
    10428     # . epilogue
    10429     89/<- %esp 5/r32/ebp
    10430     5d/pop-to-ebp
    10431     c3/return
    10432
    10433 test-get-with-too-few-inouts:
    10434     # . prologue
    10435     55/push-ebp
    10436     89/<- %ebp 4/r32/esp
    10437     # setup
    10438     (clear-stream _test-input-stream)
    10439     (clear-stream $_test-input-buffered-file->buffer)
    10440     (clear-stream _test-output-stream)
    10441     (clear-stream $_test-output-buffered-file->buffer)
    10442     (clear-stream _test-error-stream)
    10443     (clear-stream $_test-error-buffered-file->buffer)
    10444     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    10445     68/push 0/imm32
    10446     68/push 0/imm32
    10447     89/<- %edx 4/r32/esp
    10448     (tailor-exit-descriptor %edx 0x10)
    10449     #
    10450     (write _test-input-stream "fn foo {\n")
    10451     (write _test-input-stream "  var a: t\n")
    10452     (write _test-input-stream "  var c/ecx: (addr int) <- get a\n")
    10453     (write _test-input-stream "}\n")
    10454     (write _test-input-stream "type t {\n")
    10455     (write _test-input-stream "  x: int\n")
    10456     (write _test-input-stream "}\n")
    10457     # convert
    10458     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    10459     # registers except esp clobbered at this point
    10460     # restore ed
    10461     89/<- %edx 4/r32/esp
    10462     (flush _test-output-buffered-file)
    10463     (flush _test-error-buffered-file)
    10464 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    10470     # check output
    10471     (check-stream-equal _test-output-stream  ""  "F - test-get-with-too-few-inouts: output should be empty")
    10472     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt get: too few inouts (2 required)"  "F - test-get-with-too-few-inouts: error message")
    10473     # check that stop(1) was called
    10474     (check-ints-equal *(edx+4) 2 "F - test-get-with-too-few-inouts: exit status")
    10475     # don't restore from ebp
    10476     81 0/subop/add %esp 8/imm32
    10477     # . epilogue
    10478     5d/pop-to-ebp
    10479     c3/return
    10480
    10481 test-get-with-too-many-inouts:
    10482     # . prologue
    10483     55/push-ebp
    10484     89/<- %ebp 4/r32/esp
    10485     # setup
    10486     (clear-stream _test-input-stream)
    10487     (clear-stream $_test-input-buffered-file->buffer)
    10488     (clear-stream _test-output-stream)
    10489     (clear-stream $_test-output-buffered-file->buffer)
    10490     (clear-stream _test-error-stream)
    10491     (clear-stream $_test-error-buffered-file->buffer)
    10492     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    10493     68/push 0/imm32
    10494     68/push 0/imm32
    10495     89/<- %edx 4/r32/esp
    10496     (tailor-exit-descriptor %edx 0x10)
    10497     #
    10498     (write _test-input-stream "fn foo {\n")
    10499     (write _test-input-stream "  var a: t\n")
    10500     (write _test-input-stream "  var c/ecx: (addr int) <- get a, x, 0\n")
    10501     (write _test-input-stream "}\n")
    10502     (write _test-input-stream "type t {\n")
    10503     (write _test-input-stream "  x: int\n")
    10504     (write _test-input-stream "}\n")
    10505     # convert
    10506     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    10507     # registers except esp clobbered at this point
    10508     # restore ed
    10509     89/<- %edx 4/r32/esp
    10510     (flush _test-output-buffered-file)
    10511     (flush _test-error-buffered-file)
    10512 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    10518     # check output
    10519     (check-stream-equal _test-output-stream  ""  "F - test-get-with-too-many-inouts: output should be empty")
    10520     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt get: too many inouts (2 required)"  "F - test-get-with-too-many-inouts: error message")
    10521     # check that stop(1) was called
    10522     (check-ints-equal *(edx+4) 2 "F - test-get-with-too-many-inouts: exit status")
    10523     # don't restore from ebp
    10524     81 0/subop/add %esp 8/imm32
    10525     # . epilogue
    10526     5d/pop-to-ebp
    10527     c3/return
    10528
    10529 test-get-with-no-output:
    10530     # . prologue
    10531     55/push-ebp
    10532     89/<- %ebp 4/r32/esp
    10533     # setup
    10534     (clear-stream _test-input-stream)
    10535     (clear-stream $_test-input-buffered-file->buffer)
    10536     (clear-stream _test-output-stream)
    10537     (clear-stream $_test-output-buffered-file->buffer)
    10538     (clear-stream _test-error-stream)
    10539     (clear-stream $_test-error-buffered-file->buffer)
    10540     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    10541     68/push 0/imm32
    10542     68/push 0/imm32
    10543     89/<- %edx 4/r32/esp
    10544     (tailor-exit-descriptor %edx 0x10)
    10545     #
    10546     (write _test-input-stream "fn foo {\n")
    10547     (write _test-input-stream "  var a: t\n")
    10548     (write _test-input-stream "  get a, x\n")
    10549     (write _test-input-stream "}\n")
    10550     (write _test-input-stream "type t {\n")
    10551     (write _test-input-stream "  x: int\n")
    10552     (write _test-input-stream "}\n")
    10553     # convert
    10554     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    10555     # registers except esp clobbered at this point
    10556     # restore ed
    10557     89/<- %edx 4/r32/esp
    10558     (flush _test-output-buffered-file)
    10559     (flush _test-error-buffered-file)
    10560 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    10566     # check output
    10567     (check-stream-equal _test-output-stream  ""  "F - test-get-with-no-output: output should be empty")
    10568     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt get: must have an output"  "F - test-get-with-no-output: error message")
    10569     # check that stop(1) was called
    10570     (check-ints-equal *(edx+4) 2 "F - test-get-with-no-output: exit status")
    10571     # don't restore from ebp
    10572     81 0/subop/add %esp 8/imm32
    10573     # . epilogue
    10574     5d/pop-to-ebp
    10575     c3/return
    10576
    10577 test-get-with-too-many-outputs:
    10578     # . prologue
    10579     55/push-ebp
    10580     89/<- %ebp 4/r32/esp
    10581     # setup
    10582     (clear-stream _test-input-stream)
    10583     (clear-stream $_test-input-buffered-file->buffer)
    10584     (clear-stream _test-output-stream)
    10585     (clear-stream $_test-output-buffered-file->buffer)
    10586     (clear-stream _test-error-stream)
    10587     (clear-stream $_test-error-buffered-file->buffer)
    10588     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    10589     68/push 0/imm32
    10590     68/push 0/imm32
    10591     89/<- %edx 4/r32/esp
    10592     (tailor-exit-descriptor %edx 0x10)
    10593     #
    10594     (write _test-input-stream "fn foo {\n")
    10595     (write _test-input-stream "  var a: t\n")
    10596     (write _test-input-stream "  var b: int\n")
    10597     (write _test-input-stream "  var c/eax: (addr int) <- copy 0\n")
    10598     (write _test-input-stream "  c, b <- get a, x\n")
    10599     (write _test-input-stream "}\n")
    10600     (write _test-input-stream "type t {\n")
    10601     (write _test-input-stream "  x: int\n")
    10602     (write _test-input-stream "}\n")
    10603     # convert
    10604     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    10605     # registers except esp clobbered at this point
    10606     # restore ed
    10607     89/<- %edx 4/r32/esp
    10608     (flush _test-output-buffered-file)
    10609     (flush _test-error-buffered-file)
    10610 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    10616     # check output
    10617     (check-stream-equal _test-output-stream  ""  "F - test-get-with-too-many-outputs: output should be empty")
    10618     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt get: too many outputs (1 required)"  "F - test-get-with-too-many-outputs: error message")
    10619     # check that stop(1) was called
    10620     (check-ints-equal *(edx+4) 2 "F - test-get-with-too-many-outputs: exit status")
    10621     # don't restore from ebp
    10622     81 0/subop/add %esp 8/imm32
    10623     # . epilogue
    10624     5d/pop-to-ebp
    10625     c3/return
    10626
    10627 test-convert-array-of-user-defined-types:
    10628     # . prologue
    10629     55/push-ebp
    10630     89/<- %ebp 4/r32/esp
    10631     # setup
    10632     (clear-stream _test-input-stream)
    10633     (clear-stream $_test-input-buffered-file->buffer)
    10634     (clear-stream _test-output-stream)
    10635     (clear-stream $_test-output-buffered-file->buffer)
    10636     #
    10637     (write _test-input-stream "type t {\n")  # each t is 8 bytes, which is a power of 2
    10638     (write _test-input-stream "  x: int\n")
    10639     (write _test-input-stream "  y: int\n")
    10640     (write _test-input-stream "}\n")
    10641     (write _test-input-stream "fn foo {\n")
    10642     (write _test-input-stream "  var arr/eax: (addr array t) <- copy 0\n")
    10643     (write _test-input-stream "  var idx/ecx: int <- copy 3\n")
    10644     (write _test-input-stream "  var x/eax: (addr t) <- index arr, idx\n")
    10645     (write _test-input-stream "}\n")
    10646     # convert
    10647     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
    10648     (flush _test-output-buffered-file)
    10649 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
    10655     # check output
    10656     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-array-of-user-defined-types/0")
    10657     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-array-of-user-defined-types/1")
    10658     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-array-of-user-defined-types/2")
    10659     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-array-of-user-defined-types/3")
    10660     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-array-of-user-defined-types/4")
    10661     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-array-of-user-defined-types/5")
    10662     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-array-of-user-defined-types/6")
    10663     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-array-of-user-defined-types/7")
    10664     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-array-of-user-defined-types/8")
    10665     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"                  "F - test-convert-array-of-user-defined-types/9")
    10666     (check-next-stream-line-equal _test-output-stream "    (__check-mu-array-bounds %ecx 0x00000008 *eax \"foo\" \"arr\")"  "F - test-convert-array-of-user-defined-types/10")
    10667     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + ecx<<0x00000003 + 4) 0x00000000/r32"  "F - test-convert-array-of-user-defined-types/11")
    10668     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-array-of-user-defined-types/12")
    10669     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-array-of-user-defined-types/13")
    10670     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-array-of-user-defined-types/14")
    10671     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-array-of-user-defined-types/15")
    10672     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-array-of-user-defined-types/16")
    10673     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-array-of-user-defined-types/17")
    10674     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-array-of-user-defined-types/18")
    10675     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-array-of-user-defined-types/19")
    10676     # . epilogue
    10677     89/<- %esp 5/r32/ebp
    10678     5d/pop-to-ebp
    10679     c3/return
    10680
    10681 test-convert-length-of-array-of-user-defined-types-to-eax:
    10682     # . prologue
    10683     55/push-ebp
    10684     89/<- %ebp 4/r32/esp
    10685     # setup
    10686     (clear-stream _test-input-stream)
    10687     (clear-stream $_test-input-buffered-file->buffer)
    10688     (clear-stream _test-output-stream)
    10689     (clear-stream $_test-output-buffered-file->buffer)
    10690     #
    10691     (write _test-input-stream "type t {\n")  # size = 12, which is not a power of 2
    10692     (write _test-input-stream "  x: int\n")
    10693     (write _test-input-stream "  y: int\n")
    10694     (write _test-input-stream "  z: int\n")
    10695     (write _test-input-stream "}\n")
    10696     (write _test-input-stream "fn foo {\n")
    10697     (write _test-input-stream "  var arr/eax: (addr array t) <- copy 0\n")
    10698     (write _test-input-stream "  var x/eax: int <- length arr\n")
    10699     (write _test-input-stream "}\n")
    10700     # convert
    10701     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
    10702     (flush _test-output-buffered-file)
    10703 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
    10709     # check output
    10710     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array-of-user-defined-types-to-eax/0")
    10711     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array-of-user-defined-types-to-eax/1")
    10712     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array-of-user-defined-types-to-eax/2")
    10713     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-length-of-array-of-user-defined-types-to-eax/3")
    10714     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array-of-user-defined-types-to-eax/4")
    10715     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array-of-user-defined-types-to-eax/5")
    10716     # var arr
    10717     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-length-of-array-of-user-defined-types-to-eax/6")
    10718     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"  "F - test-convert-length-of-array-of-user-defined-types-to-eax/7")
    10719     # length instruction
    10720     (check-next-stream-line-equal _test-output-stream "    51/push-ecx"         "F - test-convert-length-of-array-of-user-defined-types-to-eax/8")
    10721     (check-next-stream-line-equal _test-output-stream "    52/push-edx"         "F - test-convert-length-of-array-of-user-defined-types-to-eax/9")
    10722     (check-next-stream-line-equal _test-output-stream "    8b/-> *eax 0x00000000/r32"  "F - test-convert-length-of-array-of-user-defined-types-to-eax/10")
    10723     (check-next-stream-line-equal _test-output-stream "    31/xor %edx 2/r32/edx"  "F - test-convert-length-of-array-of-user-defined-types-to-eax/11")
    10724     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0x0000000c/imm32"  "F - test-convert-length-of-array-of-user-defined-types-to-eax/12")
    10725     (check-next-stream-line-equal _test-output-stream "    f7 7/subop/idiv-eax-edx-by %ecx"  "F - test-convert-length-of-array-of-user-defined-types-to-eax/13")
    10726     (check-next-stream-line-equal _test-output-stream "    5a/pop-to-edx"       "F - test-convert-length-of-array-of-user-defined-types-to-eax/14")
    10727     (check-next-stream-line-equal _test-output-stream "    59/pop-to-ecx"       "F - test-convert-length-of-array-of-user-defined-types-to-eax/15")
    10728     # reclaim arr
    10729     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"  "F - test-convert-length-of-array-of-user-defined-types-to-eax/16")
    10730     #
    10731     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array-of-user-defined-types-to-eax/17")
    10732     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array-of-user-defined-types-to-eax/18")
    10733     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array-of-user-defined-types-to-eax/19")
    10734     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-length-of-array-of-user-defined-types-to-eax/20")
    10735     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-length-of-array-of-user-defined-types-to-eax/21")
    10736     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array-of-user-defined-types-to-eax/22")
    10737     # . epilogue
    10738     89/<- %esp 5/r32/ebp
    10739     5d/pop-to-ebp
    10740     c3/return
    10741
    10742 test-convert-length-of-array-of-user-defined-types-to-ecx:
    10743     # . prologue
    10744     55/push-ebp
    10745     89/<- %ebp 4/r32/esp
    10746     # setup
    10747     (clear-stream _test-input-stream)
    10748     (clear-stream $_test-input-buffered-file->buffer)
    10749     (clear-stream _test-output-stream)
    10750     (clear-stream $_test-output-buffered-file->buffer)
    10751     #
    10752     (write _test-input-stream "type t {\n")  # size = 12, which is not a power of 2
    10753     (write _test-input-stream "  x: int\n")
    10754     (write _test-input-stream "  y: int\n")
    10755     (write _test-input-stream "  z: int\n")
    10756     (write _test-input-stream "}\n")
    10757     (write _test-input-stream "fn foo {\n")
    10758     (write _test-input-stream "  var arr/eax: (addr array t) <- copy 0\n")
    10759     (write _test-input-stream "  var x/ecx: int <- length arr\n")
    10760     (write _test-input-stream "}\n")
    10761     # convert
    10762     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
    10763     (flush _test-output-buffered-file)
    10764 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
    10770     # check output
    10771     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array-of-user-defined-types-to-ecx/0")
    10772     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array-of-user-defined-types-to-ecx/1")
    10773     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array-of-user-defined-types-to-ecx/2")
    10774     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-length-of-array-of-user-defined-types-to-ecx/3")
    10775     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array-of-user-defined-types-to-ecx/4")
    10776     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array-of-user-defined-types-to-ecx/5")
    10777     # var a
    10778     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-length-of-array-of-user-defined-types-to-ecx/6")
    10779     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"  "F - test-convert-length-of-array-of-user-defined-types-to-ecx/7")
    10780     # var x
    10781     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-length-of-array-of-user-defined-types-to-ecx/8")
    10782     # length instruction
    10783     (check-next-stream-line-equal _test-output-stream "    50/push-eax"         "F - test-convert-length-of-array-of-user-defined-types-to-ecx/9")
    10784     (check-next-stream-line-equal _test-output-stream "    52/push-edx"         "F - test-convert-length-of-array-of-user-defined-types-to-ecx/10")
    10785     (check-next-stream-line-equal _test-output-stream "    8b/-> *eax 0x00000000/r32"  "F - test-convert-length-of-array-of-user-defined-types-to-ecx/11")
    10786     (check-next-stream-line-equal _test-output-stream "    31/xor %edx 2/r32/edx"  "F - test-convert-length-of-array-of-user-defined-types-to-ecx/12")
    10787     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0x0000000c/imm32"  "F - test-convert-length-of-array-of-user-defined-types-to-ecx/13")
    10788     (check-next-stream-line-equal _test-output-stream "    f7 7/subop/idiv-eax-edx-by %ecx"  "F - test-convert-length-of-array-of-user-defined-types-to-ecx/14")
    10789     (check-next-stream-line-equal _test-output-stream "    89/<- %ecx 0/r32/eax"  "F - test-convert-length-of-array-of-user-defined-types-to-ecx/15")
    10790     (check-next-stream-line-equal _test-output-stream "    5a/pop-to-edx"       "F - test-convert-length-of-array-of-user-defined-types-to-ecx/16")
    10791     (check-next-stream-line-equal _test-output-stream "    58/pop-to-eax"       "F - test-convert-length-of-array-of-user-defined-types-to-ecx/17")
    10792     # reclaim x
    10793     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"  "F - test-convert-length-of-array-of-user-defined-types-to-ecx/18")
    10794     # reclaim a
    10795     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"  "F - test-convert-length-of-array-of-user-defined-types-to-ecx/19")
    10796     #
    10797     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array-of-user-defined-types-to-ecx/20")
    10798     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array-of-user-defined-types-to-ecx/21")
    10799     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array-of-user-defined-types-to-ecx/22")
    10800     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-length-of-array-of-user-defined-types-to-ecx/23")
    10801     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-length-of-array-of-user-defined-types-to-ecx/24")
    10802     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array-of-user-defined-types-to-ecx/25")
    10803     # . epilogue
    10804     89/<- %esp 5/r32/ebp
    10805     5d/pop-to-ebp
    10806     c3/return
    10807
    10808 test-convert-length-of-array-of-user-defined-types-to-edx:
    10809     # . prologue
    10810     55/push-ebp
    10811     89/<- %ebp 4/r32/esp
    10812     # setup
    10813     (clear-stream _test-input-stream)
    10814     (clear-stream $_test-input-buffered-file->buffer)
    10815     (clear-stream _test-output-stream)
    10816     (clear-stream $_test-output-buffered-file->buffer)
    10817     #
    10818     (write _test-input-stream "type t {\n")  # size = 12, which is not a power of 2
    10819     (write _test-input-stream "  x: int\n")
    10820     (write _test-input-stream "  y: int\n")
    10821     (write _test-input-stream "  z: int\n")
    10822     (write _test-input-stream "}\n")
    10823     (write _test-input-stream "fn foo {\n")
    10824     (write _test-input-stream "  var arr/eax: (addr array t) <- copy 0\n")
    10825     (write _test-input-stream "  var x/edx: int <- length arr\n")
    10826     (write _test-input-stream "}\n")
    10827     # convert
    10828     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
    10829     (flush _test-output-buffered-file)
    10830 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
    10836     # check output
    10837     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array-of-user-defined-types-to-edx/0")
    10838     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array-of-user-defined-types-to-edx/1")
    10839     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array-of-user-defined-types-to-edx/2")
    10840     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-length-of-array-of-user-defined-types-to-edx/3")
    10841     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array-of-user-defined-types-to-edx/4")
    10842     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array-of-user-defined-types-to-edx/5")
    10843     # var a
    10844     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-length-of-array-of-user-defined-types-to-edx/6")
    10845     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"  "F - test-convert-length-of-array-of-user-defined-types-to-edx/7")
    10846     # var x
    10847     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %edx"  "F - test-convert-length-of-array-of-user-defined-types-to-edx/8")
    10848     # length instruction
    10849     (check-next-stream-line-equal _test-output-stream "    50/push-eax"         "F - test-convert-length-of-array-of-user-defined-types-to-edx/9")
    10850     (check-next-stream-line-equal _test-output-stream "    51/push-ecx"         "F - test-convert-length-of-array-of-user-defined-types-to-edx/10")
    10851     (check-next-stream-line-equal _test-output-stream "    8b/-> *eax 0x00000000/r32"  "F - test-convert-length-of-array-of-user-defined-types-to-edx/11")
    10852     (check-next-stream-line-equal _test-output-stream "    31/xor %edx 2/r32/edx"  "F - test-convert-length-of-array-of-user-defined-types-to-edx/12")
    10853     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0x0000000c/imm32"  "F - test-convert-length-of-array-of-user-defined-types-to-edx/13")
    10854     (check-next-stream-line-equal _test-output-stream "    f7 7/subop/idiv-eax-edx-by %ecx"  "F - test-convert-length-of-array-of-user-defined-types-to-edx/14")
    10855     (check-next-stream-line-equal _test-output-stream "    89/<- %edx 0/r32/eax"  "F - test-convert-length-of-array-of-user-defined-types-to-edx/15")
    10856     (check-next-stream-line-equal _test-output-stream "    59/pop-to-ecx"       "F - test-convert-length-of-array-of-user-defined-types-to-edx/16")
    10857     (check-next-stream-line-equal _test-output-stream "    58/pop-to-eax"       "F - test-convert-length-of-array-of-user-defined-types-to-edx/17")
    10858     # reclaim x
    10859     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %edx"  "F - test-convert-length-of-array-of-user-defined-types-to-edx/18")
    10860     # reclaim a
    10861     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"  "F - test-convert-length-of-array-of-user-defined-types-to-edx/19")
    10862     #
    10863     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array-of-user-defined-types-to-edx/20")
    10864     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array-of-user-defined-types-to-edx/21")
    10865     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array-of-user-defined-types-to-edx/22")
    10866     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-length-of-array-of-user-defined-types-to-edx/23")
    10867     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-length-of-array-of-user-defined-types-to-edx/24")
    10868     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array-of-user-defined-types-to-edx/25")
    10869     # . epilogue
    10870     89/<- %esp 5/r32/ebp
    10871     5d/pop-to-ebp
    10872     c3/return
    10873
    10874 test-convert-length-of-array-of-user-defined-types:
    10875     # . prologue
    10876     55/push-ebp
    10877     89/<- %ebp 4/r32/esp
    10878     # setup
    10879     (clear-stream _test-input-stream)
    10880     (clear-stream $_test-input-buffered-file->buffer)
    10881     (clear-stream _test-output-stream)
    10882     (clear-stream $_test-output-buffered-file->buffer)
    10883     #
    10884     (write _test-input-stream "type t {\n")  # each t is 8 bytes, which is a power of 2
    10885     (write _test-input-stream "  x: int\n")
    10886     (write _test-input-stream "  y: int\n")
    10887     (write _test-input-stream "  z: int\n")
    10888     (write _test-input-stream "}\n")
    10889     (write _test-input-stream "fn foo {\n")
    10890     (write _test-input-stream "  var arr/eax: (addr array t) <- copy 0\n")
    10891     (write _test-input-stream "  var x/ebx: int <- length arr\n")
    10892     (write _test-input-stream "}\n")
    10893     # convert
    10894     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
    10895     (flush _test-output-buffered-file)
    10896 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
    10902     # check output
    10903     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array-of-user-defined-types/0")
    10904     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array-of-user-defined-types/1")
    10905     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array-of-user-defined-types/2")
    10906     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-length-of-array-of-user-defined-types/3")
    10907     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array-of-user-defined-types/4")
    10908     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array-of-user-defined-types/5")
    10909     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-length-of-array-of-user-defined-types/6")
    10910     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"  "F - test-convert-length-of-array-of-user-defined-types/7")
    10911     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ebx"  "F - test-convert-length-of-array-of-user-defined-types/8")
    10912     (check-next-stream-line-equal _test-output-stream "    50/push-eax"         "F - test-convert-length-of-array-of-user-defined-types/9")
    10913     (check-next-stream-line-equal _test-output-stream "    51/push-ecx"         "F - test-convert-length-of-array-of-user-defined-types/10")
    10914     (check-next-stream-line-equal _test-output-stream "    52/push-edx"         "F - test-convert-length-of-array-of-user-defined-types/11")
    10915     (check-next-stream-line-equal _test-output-stream "    8b/-> *eax 0x00000000/r32"  "F - test-convert-length-of-array-of-user-defined-types/12")
    10916     (check-next-stream-line-equal _test-output-stream "    31/xor %edx 2/r32/edx"  "F - test-convert-length-of-array-of-user-defined-types/13")
    10917     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0x0000000c/imm32"  "F - test-convert-length-of-array-of-user-defined-types/14")
    10918     (check-next-stream-line-equal _test-output-stream "    f7 7/subop/idiv-eax-edx-by %ecx"  "F - test-convert-length-of-array-of-user-defined-types/15")
    10919     (check-next-stream-line-equal _test-output-stream "    89/<- %ebx 0/r32/eax"  "F - test-convert-length-of-array-of-user-defined-types/16")
    10920     (check-next-stream-line-equal _test-output-stream "    5a/pop-to-edx"       "F - test-convert-length-of-array-of-user-defined-types/17")
    10921     (check-next-stream-line-equal _test-output-stream "    59/pop-to-ecx"       "F - test-convert-length-of-array-of-user-defined-types/18")
    10922     (check-next-stream-line-equal _test-output-stream "    58/pop-to-eax"       "F - test-convert-length-of-array-of-user-defined-types/19")
    10923     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ebx"  "F - test-convert-length-of-array-of-user-defined-types/20")
    10924     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"  "F - test-convert-length-of-array-of-user-defined-types/21")
    10925     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array-of-user-defined-types/22")
    10926     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array-of-user-defined-types/23")
    10927     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array-of-user-defined-types/24")
    10928     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-length-of-array-of-user-defined-types/25")
    10929     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-length-of-array-of-user-defined-types/26")
    10930     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array-of-user-defined-types/27")
    10931     # . epilogue
    10932     89/<- %esp 5/r32/ebp
    10933     5d/pop-to-ebp
    10934     c3/return
    10935
    10936 test-index-with-non-array-atom-base-type:
    10937     # . prologue
    10938     55/push-ebp
    10939     89/<- %ebp 4/r32/esp
    10940     # setup
    10941     (clear-stream _test-input-stream)
    10942     (clear-stream $_test-input-buffered-file->buffer)
    10943     (clear-stream _test-output-stream)
    10944     (clear-stream $_test-output-buffered-file->buffer)
    10945     (clear-stream _test-error-stream)
    10946     (clear-stream $_test-error-buffered-file->buffer)
    10947     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    10948     68/push 0/imm32
    10949     68/push 0/imm32
    10950     89/<- %edx 4/r32/esp
    10951     (tailor-exit-descriptor %edx 0x10)
    10952     #
    10953     (write _test-input-stream "fn foo {\n")
    10954     (write _test-input-stream "  var a: int\n")
    10955     (write _test-input-stream "  var c/ecx: (addr int) <- index a, 0\n")
    10956     (write _test-input-stream "}\n")
    10957     # convert
    10958     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    10959     # registers except esp clobbered at this point
    10960     # restore ed
    10961     89/<- %edx 4/r32/esp
    10962     (flush _test-output-buffered-file)
    10963     (flush _test-error-buffered-file)
    10964 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    10970     # check output
    10971     (check-stream-equal _test-output-stream  ""  "F - test-index-with-non-array-atom-base-type: output should be empty")
    10972     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt index: var 'a' is not an array"  "F - test-index-with-non-array-atom-base-type: error message")
    10973     # check that stop(1) was called
    10974     (check-ints-equal *(edx+4) 2 "F - test-index-with-non-array-atom-base-type: exit status")
    10975     # don't restore from ebp
    10976     81 0/subop/add %esp 8/imm32
    10977     # . epilogue
    10978     5d/pop-to-ebp
    10979     c3/return
    10980
    10981 test-index-with-non-array-compound-base-type:
    10982     # . prologue
    10983     55/push-ebp
    10984     89/<- %ebp 4/r32/esp
    10985     # setup
    10986     (clear-stream _test-input-stream)
    10987     (clear-stream $_test-input-buffered-file->buffer)
    10988     (clear-stream _test-output-stream)
    10989     (clear-stream $_test-output-buffered-file->buffer)
    10990     (clear-stream _test-error-stream)
    10991     (clear-stream $_test-error-buffered-file->buffer)
    10992     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    10993     68/push 0/imm32
    10994     68/push 0/imm32
    10995     89/<- %edx 4/r32/esp
    10996     (tailor-exit-descriptor %edx 0x10)
    10997     #
    10998     (write _test-input-stream "fn foo {\n")
    10999     (write _test-input-stream "  var a: (handle int)\n")
    11000     (write _test-input-stream "  var c/ecx: (addr int) <- index a, 0\n")
    11001     (write _test-input-stream "}\n")
    11002     # convert
    11003     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    11004     # registers except esp clobbered at this point
    11005     # restore ed
    11006     89/<- %edx 4/r32/esp
    11007     (flush _test-output-buffered-file)
    11008     (flush _test-error-buffered-file)
    11009 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    11015     # check output
    11016     (check-stream-equal _test-output-stream  ""  "F - test-index-with-non-array-compound-base-type: output should be empty")
    11017     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt index: var 'a' is not an array"  "F - test-index-with-non-array-compound-base-type: error message")
    11018     # check that stop(1) was called
    11019     (check-ints-equal *(edx+4) 2 "F - test-index-with-non-array-compound-base-type: exit status")
    11020     # don't restore from ebp
    11021     81 0/subop/add %esp 8/imm32
    11022     # . epilogue
    11023     5d/pop-to-ebp
    11024     c3/return
    11025
    11026 test-index-with-non-array-compound-base-type-2:
    11027     # . prologue
    11028     55/push-ebp
    11029     89/<- %ebp 4/r32/esp
    11030     # setup
    11031     (clear-stream _test-input-stream)
    11032     (clear-stream $_test-input-buffered-file->buffer)
    11033     (clear-stream _test-output-stream)
    11034     (clear-stream $_test-output-buffered-file->buffer)
    11035     (clear-stream _test-error-stream)
    11036     (clear-stream $_test-error-buffered-file->buffer)
    11037     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    11038     68/push 0/imm32
    11039     68/push 0/imm32
    11040     89/<- %edx 4/r32/esp
    11041     (tailor-exit-descriptor %edx 0x10)
    11042     #
    11043     (write _test-input-stream "fn foo {\n")
    11044     (write _test-input-stream "  var a: (addr int)\n")
    11045     (write _test-input-stream "  var c/ecx: (addr int) <- index a, 0\n")
    11046     (write _test-input-stream "}\n")
    11047     # convert
    11048     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    11049     # registers except esp clobbered at this point
    11050     # restore ed
    11051     89/<- %edx 4/r32/esp
    11052     (flush _test-output-buffered-file)
    11053     (flush _test-error-buffered-file)
    11054 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    11060     # check output
    11061     (check-stream-equal _test-output-stream  ""  "F - test-index-with-non-array-compound-base-type-2: output should be empty")
    11062     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt index: var 'a' is not an array"  "F - test-index-with-non-array-compound-base-type-2: error message")
    11063     # check that stop(1) was called
    11064     (check-ints-equal *(edx+4) 2 "F - test-index-with-non-array-compound-base-type-2: exit status")
    11065     # don't restore from ebp
    11066     81 0/subop/add %esp 8/imm32
    11067     # . epilogue
    11068     5d/pop-to-ebp
    11069     c3/return
    11070
    11071 test-index-with-array-atom-base-type:
    11072     # . prologue
    11073     55/push-ebp
    11074     89/<- %ebp 4/r32/esp
    11075     # setup
    11076     (clear-stream _test-input-stream)
    11077     (clear-stream $_test-input-buffered-file->buffer)
    11078     (clear-stream _test-output-stream)
    11079     (clear-stream $_test-output-buffered-file->buffer)
    11080     (clear-stream _test-error-stream)
    11081     (clear-stream $_test-error-buffered-file->buffer)
    11082     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    11083     68/push 0/imm32
    11084     68/push 0/imm32
    11085     89/<- %edx 4/r32/esp
    11086     (tailor-exit-descriptor %edx 0x10)
    11087     #
    11088     (write _test-input-stream "fn foo {\n")
    11089     (write _test-input-stream "  var a: array\n")
    11090     (write _test-input-stream "  var c/ecx: (addr int) <- index a, 0\n")
    11091     (write _test-input-stream "}\n")
    11092     # convert
    11093     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    11094     # registers except esp clobbered at this point
    11095     # restore ed
    11096     89/<- %edx 4/r32/esp
    11097     (flush _test-output-buffered-file)
    11098     (flush _test-error-buffered-file)
    11099 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    11105     # check output
    11106     (check-stream-equal _test-output-stream  ""  "F - test-index-with-array-atom-base-type: output should be empty")
    11107     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt index: array 'a' must specify the type of its elements"  "F - test-index-with-array-atom-base-type: error message")
    11108     # check that stop(1) was called
    11109     (check-ints-equal *(edx+4) 2 "F - test-index-with-array-atom-base-type: exit status")
    11110     # don't restore from ebp
    11111     81 0/subop/add %esp 8/imm32
    11112     # . epilogue
    11113     5d/pop-to-ebp
    11114     c3/return
    11115
    11116 test-index-with-addr-base-on-stack:
    11117     # . prologue
    11118     55/push-ebp
    11119     89/<- %ebp 4/r32/esp
    11120     # setup
    11121     (clear-stream _test-input-stream)
    11122     (clear-stream $_test-input-buffered-file->buffer)
    11123     (clear-stream _test-output-stream)
    11124     (clear-stream $_test-output-buffered-file->buffer)
    11125     (clear-stream _test-error-stream)
    11126     (clear-stream $_test-error-buffered-file->buffer)
    11127     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    11128     68/push 0/imm32
    11129     68/push 0/imm32
    11130     89/<- %edx 4/r32/esp
    11131     (tailor-exit-descriptor %edx 0x10)
    11132     #
    11133     (write _test-input-stream "fn foo {\n")
    11134     (write _test-input-stream "  var a: (addr array int)\n")
    11135     (write _test-input-stream "  var c/ecx: (addr int) <- index a, 0\n")
    11136     (write _test-input-stream "}\n")
    11137     # convert
    11138     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    11139     # registers except esp clobbered at this point
    11140     # restore ed
    11141     89/<- %edx 4/r32/esp
    11142     (flush _test-output-buffered-file)
    11143     (flush _test-error-buffered-file)
    11144 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    11150     # check output
    11151     (check-stream-equal _test-output-stream  ""  "F - test-index-with-addr-base-on-stack: output should be empty")
    11152     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt index: var 'a' is an addr to an array, and so must live in a register"  "F - test-index-with-addr-base-on-stack: error message")
    11153     # check that stop(1) was called
    11154     (check-ints-equal *(edx+4) 2 "F - test-index-with-addr-base-on-stack: exit status")
    11155     # don't restore from ebp
    11156     81 0/subop/add %esp 8/imm32
    11157     # . epilogue
    11158     5d/pop-to-ebp
    11159     c3/return
    11160
    11161 test-index-with-wrong-index-type:
    11162     # . prologue
    11163     55/push-ebp
    11164     89/<- %ebp 4/r32/esp
    11165     # setup
    11166     (clear-stream _test-input-stream)
    11167     (clear-stream $_test-input-buffered-file->buffer)
    11168     (clear-stream _test-output-stream)
    11169     (clear-stream $_test-output-buffered-file->buffer)
    11170     (clear-stream _test-error-stream)
    11171     (clear-stream $_test-error-buffered-file->buffer)
    11172     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    11173     68/push 0/imm32
    11174     68/push 0/imm32
    11175     89/<- %edx 4/r32/esp
    11176     (tailor-exit-descriptor %edx 0x10)
    11177     #
    11178     (write _test-input-stream "fn foo {\n")
    11179     (write _test-input-stream "  var a/eax: (addr array int) <- copy 0\n")
    11180     (write _test-input-stream "  var b: boolean\n")
    11181     (write _test-input-stream "  var c/ecx: (addr int) <- index a, b\n")
    11182     (write _test-input-stream "}\n")
    11183     # convert
    11184     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    11185     # registers except esp clobbered at this point
    11186     # restore ed
    11187     89/<- %edx 4/r32/esp
    11188     (flush _test-output-buffered-file)
    11189     (flush _test-error-buffered-file)
    11190 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    11196     # check output
    11197     (check-stream-equal _test-output-stream  ""  "F - test-index-with-wrong-index-type: output should be empty")
    11198     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt index: second argument 'b' must be an int or offset"  "F - test-index-with-wrong-index-type: error message")
    11199     # check that stop(1) was called
    11200     (check-ints-equal *(edx+4) 2 "F - test-index-with-wrong-index-type: exit status")
    11201     # don't restore from ebp
    11202     81 0/subop/add %esp 8/imm32
    11203     # . epilogue
    11204     5d/pop-to-ebp
    11205     c3/return
    11206
    11207 test-index-with-offset-atom-index-type:
    11208     # . prologue
    11209     55/push-ebp
    11210     89/<- %ebp 4/r32/esp
    11211     # setup
    11212     (clear-stream _test-input-stream)
    11213     (clear-stream $_test-input-buffered-file->buffer)
    11214     (clear-stream _test-output-stream)
    11215     (clear-stream $_test-output-buffered-file->buffer)
    11216     (clear-stream _test-error-stream)
    11217     (clear-stream $_test-error-buffered-file->buffer)
    11218     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    11219     68/push 0/imm32
    11220     68/push 0/imm32
    11221     89/<- %edx 4/r32/esp
    11222     (tailor-exit-descriptor %edx 0x10)
    11223     #
    11224     (write _test-input-stream "fn foo {\n")
    11225     (write _test-input-stream "  var a/eax: (addr array int) <- copy 0\n")
    11226     (write _test-input-stream "  var b: offset\n")
    11227     (write _test-input-stream "  var c/ecx: (addr int) <- index a, b\n")
    11228     (write _test-input-stream "}\n")
    11229     # convert
    11230     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    11231     # registers except esp clobbered at this point
    11232     # restore ed
    11233     89/<- %edx 4/r32/esp
    11234     (flush _test-output-buffered-file)
    11235     (flush _test-error-buffered-file)
    11236 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    11242     # check output
    11243     (check-stream-equal _test-output-stream  ""  "F - test-index-with-offset-atom-index-type: output should be empty")
    11244     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt index: offset 'b' must specify the type of array elements"  "F - test-index-with-offset-atom-index-type: error message")
    11245     # check that stop(1) was called
    11246     (check-ints-equal *(edx+4) 2 "F - test-index-with-offset-atom-index-type: exit status")
    11247     # don't restore from ebp
    11248     81 0/subop/add %esp 8/imm32
    11249     # . epilogue
    11250     5d/pop-to-ebp
    11251     c3/return
    11252
    11253 test-index-with-offset-on-stack:
    11254     # . prologue
    11255     55/push-ebp
    11256     89/<- %ebp 4/r32/esp
    11257     # setup
    11258     (clear-stream _test-input-stream)
    11259     (clear-stream $_test-input-buffered-file->buffer)
    11260     (clear-stream _test-output-stream)
    11261     (clear-stream $_test-output-buffered-file->buffer)
    11262     (clear-stream _test-error-stream)
    11263     (clear-stream $_test-error-buffered-file->buffer)
    11264     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    11265     68/push 0/imm32
    11266     68/push 0/imm32
    11267     89/<- %edx 4/r32/esp
    11268     (tailor-exit-descriptor %edx 0x10)
    11269     #
    11270     (write _test-input-stream "fn foo {\n")
    11271     (write _test-input-stream "  var a/eax: (addr array int) <- copy 0\n")
    11272     (write _test-input-stream "  var b: int\n")
    11273     (write _test-input-stream "  var c/ecx: (addr int) <- index a, b\n")
    11274     (write _test-input-stream "}\n")
    11275     # convert
    11276     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    11277     # registers except esp clobbered at this point
    11278     # restore ed
    11279     89/<- %edx 4/r32/esp
    11280     (flush _test-output-buffered-file)
    11281     (flush _test-error-buffered-file)
    11282 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    11288     # check output
    11289     (check-stream-equal _test-output-stream  ""  "F - test-index-with-offset-on-stack: output should be empty")
    11290     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt index: second argument 'b' must be in a register"  "F - test-index-with-offset-on-stack: error message")
    11291     # check that stop(1) was called
    11292     (check-ints-equal *(edx+4) 2 "F - test-index-with-offset-on-stack: exit status")
    11293     # don't restore from ebp
    11294     81 0/subop/add %esp 8/imm32
    11295     # . epilogue
    11296     5d/pop-to-ebp
    11297     c3/return
    11298
    11299 test-index-needs-offset-type:
    11300     # . prologue
    11301     55/push-ebp
    11302     89/<- %ebp 4/r32/esp
    11303     # setup
    11304     (clear-stream _test-input-stream)
    11305     (clear-stream $_test-input-buffered-file->buffer)
    11306     (clear-stream _test-output-stream)
    11307     (clear-stream $_test-output-buffered-file->buffer)
    11308     (clear-stream _test-error-stream)
    11309     (clear-stream $_test-error-buffered-file->buffer)
    11310     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    11311     68/push 0/imm32
    11312     68/push 0/imm32
    11313     89/<- %edx 4/r32/esp
    11314     (tailor-exit-descriptor %edx 0x10)
    11315     #
    11316     (write _test-input-stream "fn foo {\n")
    11317     (write _test-input-stream "  var a/eax: (addr array t) <- copy 0\n")
    11318     (write _test-input-stream "  var b/ebx: int <- copy 0\n")
    11319     (write _test-input-stream "  var c/ecx: (addr int) <- index a, b\n")
    11320     (write _test-input-stream "}\n")
    11321     (write _test-input-stream "type t {\n")  # size 12 is not a power of two
    11322     (write _test-input-stream "  x: int\n")
    11323     (write _test-input-stream "  y: int\n")
    11324     (write _test-input-stream "  z: int\n")
    11325     (write _test-input-stream "}\n")
    11326     # convert
    11327     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    11328     # registers except esp clobbered at this point
    11329     # restore ed
    11330     89/<- %edx 4/r32/esp
    11331     (flush _test-output-buffered-file)
    11332     (flush _test-error-buffered-file)
    11333 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    11339     # check output
    11340     (check-stream-equal _test-output-stream  ""  "F - test-index-needs-offset-type: output should be empty")
    11341     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt index: cannot take an int for array 'a'; create an offset instead. See mu.md for details."  "F - test-index-needs-offset-type: error message")
    11342     # check that stop(1) was called
    11343     (check-ints-equal *(edx+4) 2 "F - test-index-needs-offset-type: exit status")
    11344     # don't restore from ebp
    11345     81 0/subop/add %esp 8/imm32
    11346     # . epilogue
    11347     5d/pop-to-ebp
    11348     c3/return
    11349
    11350 test-index-with-output-not-address:
    11351     # . prologue
    11352     55/push-ebp
    11353     89/<- %ebp 4/r32/esp
    11354     # setup
    11355     (clear-stream _test-input-stream)
    11356     (clear-stream $_test-input-buffered-file->buffer)
    11357     (clear-stream _test-output-stream)
    11358     (clear-stream $_test-output-buffered-file->buffer)
    11359     (clear-stream _test-error-stream)
    11360     (clear-stream $_test-error-buffered-file->buffer)
    11361     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    11362     68/push 0/imm32
    11363     68/push 0/imm32
    11364     89/<- %edx 4/r32/esp
    11365     (tailor-exit-descriptor %edx 0x10)
    11366     #
    11367     (write _test-input-stream "fn foo {\n")
    11368     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
    11369     (write _test-input-stream "  var o/edi: int <- index a, 0\n")
    11370     (write _test-input-stream "}\n")
    11371     # convert
    11372     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    11373     # registers except esp clobbered at this point
    11374     # restore ed
    11375     89/<- %edx 4/r32/esp
    11376     (flush _test-output-buffered-file)
    11377     (flush _test-error-buffered-file)
    11378 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    11384     # check output
    11385     (check-stream-equal _test-output-stream  ""  "F - test-index-with-output-not-address: output should be empty")
    11386     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt index: output 'o' must be an addr"  "F - test-index-with-output-not-address: error message")
    11387     # check that stop(1) was called
    11388     (check-ints-equal *(edx+4) 2 "F - test-index-with-output-not-address: exit status")
    11389     # don't restore from ebp
    11390     81 0/subop/add %esp 8/imm32
    11391     # . epilogue
    11392     5d/pop-to-ebp
    11393     c3/return
    11394
    11395 test-index-with-output-not-address-2:
    11396     # . prologue
    11397     55/push-ebp
    11398     89/<- %ebp 4/r32/esp
    11399     # setup
    11400     (clear-stream _test-input-stream)
    11401     (clear-stream $_test-input-buffered-file->buffer)
    11402     (clear-stream _test-output-stream)
    11403     (clear-stream $_test-output-buffered-file->buffer)
    11404     (clear-stream _test-error-stream)
    11405     (clear-stream $_test-error-buffered-file->buffer)
    11406     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    11407     68/push 0/imm32
    11408     68/push 0/imm32
    11409     89/<- %edx 4/r32/esp
    11410     (tailor-exit-descriptor %edx 0x10)
    11411     #
    11412     (write _test-input-stream "fn foo {\n")
    11413     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
    11414     (write _test-input-stream "  var o/edi: (int) <- index a, 0\n")
    11415     (write _test-input-stream "}\n")
    11416     # convert
    11417     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    11418     # registers except esp clobbered at this point
    11419     # restore ed
    11420     89/<- %edx 4/r32/esp
    11421     (flush _test-output-buffered-file)
    11422     (flush _test-error-buffered-file)
    11423 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    11429     # check output
    11430     (check-stream-equal _test-output-stream  ""  "F - test-index-with-output-not-address-2: output should be empty")
    11431     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt index: output 'o' must be an addr"  "F - test-index-with-output-not-address-2: error message")
    11432     # check that stop(1) was called
    11433     (check-ints-equal *(edx+4) 2 "F - test-index-with-output-not-address-2: exit status")
    11434     # don't restore from ebp
    11435     81 0/subop/add %esp 8/imm32
    11436     # . epilogue
    11437     5d/pop-to-ebp
    11438     c3/return
    11439
    11440 test-index-with-wrong-output-type:
    11441     # . prologue
    11442     55/push-ebp
    11443     89/<- %ebp 4/r32/esp
    11444     # setup
    11445     (clear-stream _test-input-stream)
    11446     (clear-stream $_test-input-buffered-file->buffer)
    11447     (clear-stream _test-output-stream)
    11448     (clear-stream $_test-output-buffered-file->buffer)
    11449     (clear-stream _test-error-stream)
    11450     (clear-stream $_test-error-buffered-file->buffer)
    11451     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    11452     68/push 0/imm32
    11453     68/push 0/imm32
    11454     89/<- %edx 4/r32/esp
    11455     (tailor-exit-descriptor %edx 0x10)
    11456     #
    11457     (write _test-input-stream "fn foo {\n")
    11458     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
    11459     (write _test-input-stream "  var o/edi: (addr int) <- index a, 0\n")
    11460     (write _test-input-stream "}\n")
    11461     # convert
    11462     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    11463     # registers except esp clobbered at this point
    11464     # restore ed
    11465     89/<- %edx 4/r32/esp
    11466     (flush _test-output-buffered-file)
    11467     (flush _test-error-buffered-file)
    11468 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    11474     # check output
    11475     (check-stream-equal _test-output-stream  ""  "F - test-index-with-wrong-output-type: output should be empty")
    11476     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt index: output 'o' does not have the right type"  "F - test-index-with-wrong-output-type: error message")
    11477     # check that stop(1) was called
    11478     (check-ints-equal *(edx+4) 2 "F - test-index-with-wrong-output-type: exit status")
    11479     # don't restore from ebp
    11480     81 0/subop/add %esp 8/imm32
    11481     # . epilogue
    11482     5d/pop-to-ebp
    11483     c3/return
    11484
    11485 test-index-with-wrong-output-compound-type:
    11486     # . prologue
    11487     55/push-ebp
    11488     89/<- %ebp 4/r32/esp
    11489     # setup
    11490     (clear-stream _test-input-stream)
    11491     (clear-stream $_test-input-buffered-file->buffer)
    11492     (clear-stream _test-output-stream)
    11493     (clear-stream $_test-output-buffered-file->buffer)
    11494     (clear-stream _test-error-stream)
    11495     (clear-stream $_test-error-buffered-file->buffer)
    11496     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    11497     68/push 0/imm32
    11498     68/push 0/imm32
    11499     89/<- %edx 4/r32/esp
    11500     (tailor-exit-descriptor %edx 0x10)
    11501     #
    11502     (write _test-input-stream "fn foo {\n")
    11503     (write _test-input-stream "  var a/ebx: (addr array handle boolean) <- copy 0\n")
    11504     (write _test-input-stream "  var o/edi: (addr handle int) <- index a, 0\n")
    11505     (write _test-input-stream "}\n")
    11506     # convert
    11507     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    11508     # registers except esp clobbered at this point
    11509     # restore ed
    11510     89/<- %edx 4/r32/esp
    11511     (flush _test-output-buffered-file)
    11512     (flush _test-error-buffered-file)
    11513 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    11519     # check output
    11520     (check-stream-equal _test-output-stream  ""  "F - test-index-with-wrong-output-compound-type: output should be empty")
    11521     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt index: output 'o' does not have the right type"  "F - test-index-with-wrong-output-compound-type: error message")
    11522     # check that stop(1) was called
    11523     (check-ints-equal *(edx+4) 2 "F - test-index-with-wrong-output-compound-type: exit status")
    11524     # don't restore from ebp
    11525     81 0/subop/add %esp 8/imm32
    11526     # . epilogue
    11527     5d/pop-to-ebp
    11528     c3/return
    11529
    11530 test-index-with-no-inouts:
    11531     # . prologue
    11532     55/push-ebp
    11533     89/<- %ebp 4/r32/esp
    11534     # setup
    11535     (clear-stream _test-input-stream)
    11536     (clear-stream $_test-input-buffered-file->buffer)
    11537     (clear-stream _test-output-stream)
    11538     (clear-stream $_test-output-buffered-file->buffer)
    11539     (clear-stream _test-error-stream)
    11540     (clear-stream $_test-error-buffered-file->buffer)
    11541     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    11542     68/push 0/imm32
    11543     68/push 0/imm32
    11544     89/<- %edx 4/r32/esp
    11545     (tailor-exit-descriptor %edx 0x10)
    11546     #
    11547     (write _test-input-stream "fn foo {\n")
    11548     (write _test-input-stream "  var c/ecx: (addr int) <- index\n")
    11549     (write _test-input-stream "}\n")
    11550     # convert
    11551     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    11552     # registers except esp clobbered at this point
    11553     # restore ed
    11554     89/<- %edx 4/r32/esp
    11555     (flush _test-output-buffered-file)
    11556     (flush _test-error-buffered-file)
    11557 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    11563     # check output
    11564     (check-stream-equal _test-output-stream  ""  "F - test-index-with-no-inouts: output should be empty")
    11565     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt index: too few inouts (2 required)"  "F - test-index-with-no-inouts: error message")
    11566     # check that stop(1) was called
    11567     (check-ints-equal *(edx+4) 2 "F - test-index-with-no-inouts: exit status")
    11568     # don't restore from ebp
    11569     81 0/subop/add %esp 8/imm32
    11570     # . epilogue
    11571     5d/pop-to-ebp
    11572     c3/return
    11573
    11574 test-index-with-too-few-inouts:
    11575     # . prologue
    11576     55/push-ebp
    11577     89/<- %ebp 4/r32/esp
    11578     # setup
    11579     (clear-stream _test-input-stream)
    11580     (clear-stream $_test-input-buffered-file->buffer)
    11581     (clear-stream _test-output-stream)
    11582     (clear-stream $_test-output-buffered-file->buffer)
    11583     (clear-stream _test-error-stream)
    11584     (clear-stream $_test-error-buffered-file->buffer)
    11585     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    11586     68/push 0/imm32
    11587     68/push 0/imm32
    11588     89/<- %edx 4/r32/esp
    11589     (tailor-exit-descriptor %edx 0x10)
    11590     #
    11591     (write _test-input-stream "fn foo {\n")
    11592     (write _test-input-stream "  var a: (array int 3)\n")
    11593     (write _test-input-stream "  var c/ecx: (addr int) <- index a\n")
    11594     (write _test-input-stream "}\n")
    11595     # convert
    11596     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    11597     # registers except esp clobbered at this point
    11598     # restore ed
    11599     89/<- %edx 4/r32/esp
    11600     (flush _test-output-buffered-file)
    11601     (flush _test-error-buffered-file)
    11602 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    11608     # check output
    11609     (check-stream-equal _test-output-stream  ""  "F - test-index-with-too-few-inouts: output should be empty")
    11610     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt index: too few inouts (2 required)"  "F - test-index-with-too-few-inouts: error message")
    11611     # check that stop(1) was called
    11612     (check-ints-equal *(edx+4) 2 "F - test-index-with-too-few-inouts: exit status")
    11613     # don't restore from ebp
    11614     81 0/subop/add %esp 8/imm32
    11615     # . epilogue
    11616     5d/pop-to-ebp
    11617     c3/return
    11618
    11619 test-index-with-too-many-inouts:
    11620     # . prologue
    11621     55/push-ebp
    11622     89/<- %ebp 4/r32/esp
    11623     # setup
    11624     (clear-stream _test-input-stream)
    11625     (clear-stream $_test-input-buffered-file->buffer)
    11626     (clear-stream _test-output-stream)
    11627     (clear-stream $_test-output-buffered-file->buffer)
    11628     (clear-stream _test-error-stream)
    11629     (clear-stream $_test-error-buffered-file->buffer)
    11630     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    11631     68/push 0/imm32
    11632     68/push 0/imm32
    11633     89/<- %edx 4/r32/esp
    11634     (tailor-exit-descriptor %edx 0x10)
    11635     #
    11636     (write _test-input-stream "fn foo {\n")
    11637     (write _test-input-stream "  var a: (array int 3)\n")
    11638     (write _test-input-stream "  var c/ecx: (addr int) <- index a, 0, 0\n")
    11639     (write _test-input-stream "}\n")
    11640     # convert
    11641     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    11642     # registers except esp clobbered at this point
    11643     # restore ed
    11644     89/<- %edx 4/r32/esp
    11645     (flush _test-output-buffered-file)
    11646     (flush _test-error-buffered-file)
    11647 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    11653     # check output
    11654     (check-stream-equal _test-output-stream  ""  "F - test-index-with-too-many-inouts: output should be empty")
    11655     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt index: too many inouts (2 required)"  "F - test-index-with-too-many-inouts: error message")
    11656     # check that stop(1) was called
    11657     (check-ints-equal *(edx+4) 2 "F - test-index-with-too-many-inouts: exit status")
    11658     # don't restore from ebp
    11659     81 0/subop/add %esp 8/imm32
    11660     # . epilogue
    11661     5d/pop-to-ebp
    11662     c3/return
    11663
    11664 test-index-with-no-output:
    11665     # . prologue
    11666     55/push-ebp
    11667     89/<- %ebp 4/r32/esp
    11668     # setup
    11669     (clear-stream _test-input-stream)
    11670     (clear-stream $_test-input-buffered-file->buffer)
    11671     (clear-stream _test-output-stream)
    11672     (clear-stream $_test-output-buffered-file->buffer)
    11673     (clear-stream _test-error-stream)
    11674     (clear-stream $_test-error-buffered-file->buffer)
    11675     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    11676     68/push 0/imm32
    11677     68/push 0/imm32
    11678     89/<- %edx 4/r32/esp
    11679     (tailor-exit-descriptor %edx 0x10)
    11680     #
    11681     (write _test-input-stream "fn foo {\n")
    11682     (write _test-input-stream "  var a: (array int 3)\n")
    11683     (write _test-input-stream "  index a, 0\n")
    11684     (write _test-input-stream "}\n")
    11685     # convert
    11686     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    11687     # registers except esp clobbered at this point
    11688     # restore ed
    11689     89/<- %edx 4/r32/esp
    11690     (flush _test-output-buffered-file)
    11691     (flush _test-error-buffered-file)
    11692 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    11698     # check output
    11699     (check-stream-equal _test-output-stream  ""  "F - test-index-with-no-output: output should be empty")
    11700     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt index: must have an output"  "F - test-index-with-no-output: error message")
    11701     # check that stop(1) was called
    11702     (check-ints-equal *(edx+4) 2 "F - test-index-with-no-output: exit status")
    11703     # don't restore from ebp
    11704     81 0/subop/add %esp 8/imm32
    11705     # . epilogue
    11706     5d/pop-to-ebp
    11707     c3/return
    11708
    11709 test-index-with-too-many-outputs:
    11710     # . prologue
    11711     55/push-ebp
    11712     89/<- %ebp 4/r32/esp
    11713     # setup
    11714     (clear-stream _test-input-stream)
    11715     (clear-stream $_test-input-buffered-file->buffer)
    11716     (clear-stream _test-output-stream)
    11717     (clear-stream $_test-output-buffered-file->buffer)
    11718     (clear-stream _test-error-stream)
    11719     (clear-stream $_test-error-buffered-file->buffer)
    11720     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    11721     68/push 0/imm32
    11722     68/push 0/imm32
    11723     89/<- %edx 4/r32/esp
    11724     (tailor-exit-descriptor %edx 0x10)
    11725     #
    11726     (write _test-input-stream "fn foo {\n")
    11727     (write _test-input-stream "  var a: (array int 3)\n")
    11728     (write _test-input-stream "  var b/eax: (addr int) <- copy 0\n")
    11729     (write _test-input-stream "  var c/ecx: (addr int) <- copy 0\n")
    11730     (write _test-input-stream "  b, c <- index a, 0\n")
    11731     (write _test-input-stream "}\n")
    11732     # convert
    11733     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    11734     # registers except esp clobbered at this point
    11735     # restore ed
    11736     89/<- %edx 4/r32/esp
    11737     (flush _test-output-buffered-file)
    11738     (flush _test-error-buffered-file)
    11739 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    11745     # check output
    11746     (check-stream-equal _test-output-stream  ""  "F - test-index-with-too-many-outputs: output should be empty")
    11747     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt index: too many outputs (1 required)"  "F - test-index-with-too-many-outputs: error message")
    11748     # check that stop(1) was called
    11749     (check-ints-equal *(edx+4) 2 "F - test-index-with-too-many-outputs: exit status")
    11750     # don't restore from ebp
    11751     81 0/subop/add %esp 8/imm32
    11752     # . epilogue
    11753     5d/pop-to-ebp
    11754     c3/return
    11755
    11756 test-compute-offset-with-non-array-atom-base-type:
    11757     # . prologue
    11758     55/push-ebp
    11759     89/<- %ebp 4/r32/esp
    11760     # setup
    11761     (clear-stream _test-input-stream)
    11762     (clear-stream $_test-input-buffered-file->buffer)
    11763     (clear-stream _test-output-stream)
    11764     (clear-stream $_test-output-buffered-file->buffer)
    11765     (clear-stream _test-error-stream)
    11766     (clear-stream $_test-error-buffered-file->buffer)
    11767     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    11768     68/push 0/imm32
    11769     68/push 0/imm32
    11770     89/<- %edx 4/r32/esp
    11771     (tailor-exit-descriptor %edx 0x10)
    11772     #
    11773     (write _test-input-stream "fn foo {\n")
    11774     (write _test-input-stream "  var a: int\n")
    11775     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a, 0\n")
    11776     (write _test-input-stream "}\n")
    11777     # convert
    11778     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    11779     # registers except esp clobbered at this point
    11780     # restore ed
    11781     89/<- %edx 4/r32/esp
    11782     (flush _test-output-buffered-file)
    11783     (flush _test-error-buffered-file)
    11784 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    11790     # check output
    11791     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-non-array-atom-base-type: output should be empty")
    11792     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt compute-offset: var 'a' is not an array"  "F - test-compute-offset-with-non-array-atom-base-type: error message")
    11793     # check that stop(1) was called
    11794     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-non-array-atom-base-type: exit status")
    11795     # don't restore from ebp
    11796     81 0/subop/add %esp 8/imm32
    11797     # . epilogue
    11798     5d/pop-to-ebp
    11799     c3/return
    11800
    11801 test-compute-offset-with-non-array-compound-base-type:
    11802     # . prologue
    11803     55/push-ebp
    11804     89/<- %ebp 4/r32/esp
    11805     # setup
    11806     (clear-stream _test-input-stream)
    11807     (clear-stream $_test-input-buffered-file->buffer)
    11808     (clear-stream _test-output-stream)
    11809     (clear-stream $_test-output-buffered-file->buffer)
    11810     (clear-stream _test-error-stream)
    11811     (clear-stream $_test-error-buffered-file->buffer)
    11812     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    11813     68/push 0/imm32
    11814     68/push 0/imm32
    11815     89/<- %edx 4/r32/esp
    11816     (tailor-exit-descriptor %edx 0x10)
    11817     #
    11818     (write _test-input-stream "fn foo {\n")
    11819     (write _test-input-stream "  var a: (handle int)\n")
    11820     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a, 0\n")
    11821     (write _test-input-stream "}\n")
    11822     # convert
    11823     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    11824     # registers except esp clobbered at this point
    11825     # restore ed
    11826     89/<- %edx 4/r32/esp
    11827     (flush _test-output-buffered-file)
    11828     (flush _test-error-buffered-file)
    11829 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    11835     # check output
    11836     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-non-array-compound-base-type: output should be empty")
    11837     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt compute-offset: var 'a' is not an array"  "F - test-compute-offset-with-non-array-compound-base-type: error message")
    11838     # check that stop(1) was called
    11839     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-non-array-compound-base-type: exit status")
    11840     # don't restore from ebp
    11841     81 0/subop/add %esp 8/imm32
    11842     # . epilogue
    11843     5d/pop-to-ebp
    11844     c3/return
    11845
    11846 test-compute-offset-with-non-array-compound-base-type-2:
    11847     # . prologue
    11848     55/push-ebp
    11849     89/<- %ebp 4/r32/esp
    11850     # setup
    11851     (clear-stream _test-input-stream)
    11852     (clear-stream $_test-input-buffered-file->buffer)
    11853     (clear-stream _test-output-stream)
    11854     (clear-stream $_test-output-buffered-file->buffer)
    11855     (clear-stream _test-error-stream)
    11856     (clear-stream $_test-error-buffered-file->buffer)
    11857     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    11858     68/push 0/imm32
    11859     68/push 0/imm32
    11860     89/<- %edx 4/r32/esp
    11861     (tailor-exit-descriptor %edx 0x10)
    11862     #
    11863     (write _test-input-stream "fn foo {\n")
    11864     (write _test-input-stream "  var a: (addr int)\n")
    11865     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a, 0\n")
    11866     (write _test-input-stream "}\n")
    11867     # convert
    11868     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    11869     # registers except esp clobbered at this point
    11870     # restore ed
    11871     89/<- %edx 4/r32/esp
    11872     (flush _test-output-buffered-file)
    11873     (flush _test-error-buffered-file)
    11874 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    11880     # check output
    11881     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-non-array-compound-base-type-2: output should be empty")
    11882     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt compute-offset: var 'a' is not an array"  "F - test-compute-offset-with-non-array-compound-base-type-2: error message")
    11883     # check that stop(1) was called
    11884     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-non-array-compound-base-type-2: exit status")
    11885     # don't restore from ebp
    11886     81 0/subop/add %esp 8/imm32
    11887     # . epilogue
    11888     5d/pop-to-ebp
    11889     c3/return
    11890
    11891 test-compute-offset-with-array-atom-base-type:
    11892     # . prologue
    11893     55/push-ebp
    11894     89/<- %ebp 4/r32/esp
    11895     # setup
    11896     (clear-stream _test-input-stream)
    11897     (clear-stream $_test-input-buffered-file->buffer)
    11898     (clear-stream _test-output-stream)
    11899     (clear-stream $_test-output-buffered-file->buffer)
    11900     (clear-stream _test-error-stream)
    11901     (clear-stream $_test-error-buffered-file->buffer)
    11902     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    11903     68/push 0/imm32
    11904     68/push 0/imm32
    11905     89/<- %edx 4/r32/esp
    11906     (tailor-exit-descriptor %edx 0x10)
    11907     #
    11908     (write _test-input-stream "fn foo {\n")
    11909     (write _test-input-stream "  var a: array\n")
    11910     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a, 0\n")
    11911     (write _test-input-stream "}\n")
    11912     # convert
    11913     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    11914     # registers except esp clobbered at this point
    11915     # restore ed
    11916     89/<- %edx 4/r32/esp
    11917     (flush _test-output-buffered-file)
    11918     (flush _test-error-buffered-file)
    11919 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    11925     # check output
    11926     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-array-atom-base-type: output should be empty")
    11927     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt compute-offset: array 'a' must specify the type of its elements"  "F - test-compute-offset-with-array-atom-base-type: error message")
    11928     # check that stop(1) was called
    11929     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-array-atom-base-type: exit status")
    11930     # don't restore from ebp
    11931     81 0/subop/add %esp 8/imm32
    11932     # . epilogue
    11933     5d/pop-to-ebp
    11934     c3/return
    11935
    11936 test-compute-offset-with-wrong-index-type:
    11937     # . prologue
    11938     55/push-ebp
    11939     89/<- %ebp 4/r32/esp
    11940     # setup
    11941     (clear-stream _test-input-stream)
    11942     (clear-stream $_test-input-buffered-file->buffer)
    11943     (clear-stream _test-output-stream)
    11944     (clear-stream $_test-output-buffered-file->buffer)
    11945     (clear-stream _test-error-stream)
    11946     (clear-stream $_test-error-buffered-file->buffer)
    11947     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    11948     68/push 0/imm32
    11949     68/push 0/imm32
    11950     89/<- %edx 4/r32/esp
    11951     (tailor-exit-descriptor %edx 0x10)
    11952     #
    11953     (write _test-input-stream "fn foo {\n")
    11954     (write _test-input-stream "  var a/eax: (addr array int) <- copy 0\n")
    11955     (write _test-input-stream "  var b: boolean\n")
    11956     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a, b\n")
    11957     (write _test-input-stream "}\n")
    11958     # convert
    11959     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    11960     # registers except esp clobbered at this point
    11961     # restore ed
    11962     89/<- %edx 4/r32/esp
    11963     (flush _test-output-buffered-file)
    11964     (flush _test-error-buffered-file)
    11965 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    11971     # check output
    11972     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-wrong-index-type: output should be empty")
    11973     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt compute-offset: second argument 'b' must be an int"  "F - test-compute-offset-with-wrong-index-type: error message")
    11974     # check that stop(1) was called
    11975     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-wrong-index-type: exit status")
    11976     # don't restore from ebp
    11977     81 0/subop/add %esp 8/imm32
    11978     # . epilogue
    11979     5d/pop-to-ebp
    11980     c3/return
    11981
    11982 test-compute-offset-with-output-not-offset:
    11983     # . prologue
    11984     55/push-ebp
    11985     89/<- %ebp 4/r32/esp
    11986     # setup
    11987     (clear-stream _test-input-stream)
    11988     (clear-stream $_test-input-buffered-file->buffer)
    11989     (clear-stream _test-output-stream)
    11990     (clear-stream $_test-output-buffered-file->buffer)
    11991     (clear-stream _test-error-stream)
    11992     (clear-stream $_test-error-buffered-file->buffer)
    11993     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    11994     68/push 0/imm32
    11995     68/push 0/imm32
    11996     89/<- %edx 4/r32/esp
    11997     (tailor-exit-descriptor %edx 0x10)
    11998     #
    11999     (write _test-input-stream "fn foo {\n")
    12000     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
    12001     (write _test-input-stream "  var o/edi: int <- compute-offset a, 0\n")
    12002     (write _test-input-stream "}\n")
    12003     # convert
    12004     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    12005     # registers except esp clobbered at this point
    12006     # restore ed
    12007     89/<- %edx 4/r32/esp
    12008     (flush _test-output-buffered-file)
    12009     (flush _test-error-buffered-file)
    12010 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    12016     # check output
    12017     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-output-not-offset: output should be empty")
    12018     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt compute-offset: output 'o' must be an offset"  "F - test-compute-offset-with-output-not-offset: error message")
    12019     # check that stop(1) was called
    12020     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-output-not-offset: exit status")
    12021     # don't restore from ebp
    12022     81 0/subop/add %esp 8/imm32
    12023     # . epilogue
    12024     5d/pop-to-ebp
    12025     c3/return
    12026
    12027 test-compute-offset-with-output-not-address-2:
    12028     # . prologue
    12029     55/push-ebp
    12030     89/<- %ebp 4/r32/esp
    12031     # setup
    12032     (clear-stream _test-input-stream)
    12033     (clear-stream $_test-input-buffered-file->buffer)
    12034     (clear-stream _test-output-stream)
    12035     (clear-stream $_test-output-buffered-file->buffer)
    12036     (clear-stream _test-error-stream)
    12037     (clear-stream $_test-error-buffered-file->buffer)
    12038     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    12039     68/push 0/imm32
    12040     68/push 0/imm32
    12041     89/<- %edx 4/r32/esp
    12042     (tailor-exit-descriptor %edx 0x10)
    12043     #
    12044     (write _test-input-stream "fn foo {\n")
    12045     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
    12046     (write _test-input-stream "  var o/edi: (int) <- compute-offset a, 0\n")
    12047     (write _test-input-stream "}\n")
    12048     # convert
    12049     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    12050     # registers except esp clobbered at this point
    12051     # restore ed
    12052     89/<- %edx 4/r32/esp
    12053     (flush _test-output-buffered-file)
    12054     (flush _test-error-buffered-file)
    12055 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    12061     # check output
    12062     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-output-not-address-2: output should be empty")
    12063     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt compute-offset: output 'o' must be an offset"  "F - test-compute-offset-with-output-not-address-2: error message")
    12064     # check that stop(1) was called
    12065     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-output-not-address-2: exit status")
    12066     # don't restore from ebp
    12067     81 0/subop/add %esp 8/imm32
    12068     # . epilogue
    12069     5d/pop-to-ebp
    12070     c3/return
    12071
    12072 test-compute-offset-with-wrong-output-type:
    12073     # . prologue
    12074     55/push-ebp
    12075     89/<- %ebp 4/r32/esp
    12076     # setup
    12077     (clear-stream _test-input-stream)
    12078     (clear-stream $_test-input-buffered-file->buffer)
    12079     (clear-stream _test-output-stream)
    12080     (clear-stream $_test-output-buffered-file->buffer)
    12081     (clear-stream _test-error-stream)
    12082     (clear-stream $_test-error-buffered-file->buffer)
    12083     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    12084     68/push 0/imm32
    12085     68/push 0/imm32
    12086     89/<- %edx 4/r32/esp
    12087     (tailor-exit-descriptor %edx 0x10)
    12088     #
    12089     (write _test-input-stream "fn foo {\n")
    12090     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
    12091     (write _test-input-stream "  var o/edi: (offset int) <- compute-offset a, 0\n")
    12092     (write _test-input-stream "}\n")
    12093     # convert
    12094     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    12095     # registers except esp clobbered at this point
    12096     # restore ed
    12097     89/<- %edx 4/r32/esp
    12098     (flush _test-output-buffered-file)
    12099     (flush _test-error-buffered-file)
    12100 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    12106     # check output
    12107     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-wrong-output-type: output should be empty")
    12108     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt compute-offset: output 'o' does not have the right type"  "F - test-compute-offset-with-wrong-output-type: error message")
    12109     # check that stop(1) was called
    12110     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-wrong-output-type: exit status")
    12111     # don't restore from ebp
    12112     81 0/subop/add %esp 8/imm32
    12113     # . epilogue
    12114     5d/pop-to-ebp
    12115     c3/return
    12116
    12117 test-compute-offset-with-wrong-output-compound-type:
    12118     # . prologue
    12119     55/push-ebp
    12120     89/<- %ebp 4/r32/esp
    12121     # setup
    12122     (clear-stream _test-input-stream)
    12123     (clear-stream $_test-input-buffered-file->buffer)
    12124     (clear-stream _test-output-stream)
    12125     (clear-stream $_test-output-buffered-file->buffer)
    12126     (clear-stream _test-error-stream)
    12127     (clear-stream $_test-error-buffered-file->buffer)
    12128     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    12129     68/push 0/imm32
    12130     68/push 0/imm32
    12131     89/<- %edx 4/r32/esp
    12132     (tailor-exit-descriptor %edx 0x10)
    12133     #
    12134     (write _test-input-stream "fn foo {\n")
    12135     (write _test-input-stream "  var a/ebx: (addr array handle boolean) <- copy 0\n")
    12136     (write _test-input-stream "  var o/edi: (offset handle int) <- compute-offset a, 0\n")
    12137     (write _test-input-stream "}\n")
    12138     # convert
    12139     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    12140     # registers except esp clobbered at this point
    12141     # restore ed
    12142     89/<- %edx 4/r32/esp
    12143     (flush _test-output-buffered-file)
    12144     (flush _test-error-buffered-file)
    12145 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    12151     # check output
    12152     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-wrong-output-compound-type: output should be empty")
    12153     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt compute-offset: output 'o' does not have the right type"  "F - test-compute-offset-with-wrong-output-compound-type: error message")
    12154     # check that stop(1) was called
    12155     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-wrong-output-compound-type: exit status")
    12156     # don't restore from ebp
    12157     81 0/subop/add %esp 8/imm32
    12158     # . epilogue
    12159     5d/pop-to-ebp
    12160     c3/return
    12161
    12162 test-compute-offset-with-no-inouts:
    12163     # . prologue
    12164     55/push-ebp
    12165     89/<- %ebp 4/r32/esp
    12166     # setup
    12167     (clear-stream _test-input-stream)
    12168     (clear-stream $_test-input-buffered-file->buffer)
    12169     (clear-stream _test-output-stream)
    12170     (clear-stream $_test-output-buffered-file->buffer)
    12171     (clear-stream _test-error-stream)
    12172     (clear-stream $_test-error-buffered-file->buffer)
    12173     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    12174     68/push 0/imm32
    12175     68/push 0/imm32
    12176     89/<- %edx 4/r32/esp
    12177     (tailor-exit-descriptor %edx 0x10)
    12178     #
    12179     (write _test-input-stream "fn foo {\n")
    12180     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset\n")
    12181     (write _test-input-stream "}\n")
    12182     # convert
    12183     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    12184     # registers except esp clobbered at this point
    12185     # restore ed
    12186     89/<- %edx 4/r32/esp
    12187     (flush _test-output-buffered-file)
    12188     (flush _test-error-buffered-file)
    12189 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    12195     # check output
    12196     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-no-inouts: output should be empty")
    12197     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt compute-offset: too few inouts (2 required)"  "F - test-compute-offset-with-no-inouts: error message")
    12198     # check that stop(1) was called
    12199     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-no-inouts: exit status")
    12200     # don't restore from ebp
    12201     81 0/subop/add %esp 8/imm32
    12202     # . epilogue
    12203     5d/pop-to-ebp
    12204     c3/return
    12205
    12206 test-compute-offset-with-too-few-inouts:
    12207     # . prologue
    12208     55/push-ebp
    12209     89/<- %ebp 4/r32/esp
    12210     # setup
    12211     (clear-stream _test-input-stream)
    12212     (clear-stream $_test-input-buffered-file->buffer)
    12213     (clear-stream _test-output-stream)
    12214     (clear-stream $_test-output-buffered-file->buffer)
    12215     (clear-stream _test-error-stream)
    12216     (clear-stream $_test-error-buffered-file->buffer)
    12217     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    12218     68/push 0/imm32
    12219     68/push 0/imm32
    12220     89/<- %edx 4/r32/esp
    12221     (tailor-exit-descriptor %edx 0x10)
    12222     #
    12223     (write _test-input-stream "fn foo {\n")
    12224     (write _test-input-stream "  var a: (array int 3)\n")
    12225     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a\n")
    12226     (write _test-input-stream "}\n")
    12227     # convert
    12228     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    12229     # registers except esp clobbered at this point
    12230     # restore ed
    12231     89/<- %edx 4/r32/esp
    12232     (flush _test-output-buffered-file)
    12233     (flush _test-error-buffered-file)
    12234 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    12240     # check output
    12241     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-too-few-inouts: output should be empty")
    12242     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt compute-offset: too few inouts (2 required)"  "F - test-compute-offset-with-too-few-inouts: error message")
    12243     # check that stop(1) was called
    12244     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-too-few-inouts: exit status")
    12245     # don't restore from ebp
    12246     81 0/subop/add %esp 8/imm32
    12247     # . epilogue
    12248     5d/pop-to-ebp
    12249     c3/return
    12250
    12251 test-compute-offset-with-too-many-inouts:
    12252     # . prologue
    12253     55/push-ebp
    12254     89/<- %ebp 4/r32/esp
    12255     # setup
    12256     (clear-stream _test-input-stream)
    12257     (clear-stream $_test-input-buffered-file->buffer)
    12258     (clear-stream _test-output-stream)
    12259     (clear-stream $_test-output-buffered-file->buffer)
    12260     (clear-stream _test-error-stream)
    12261     (clear-stream $_test-error-buffered-file->buffer)
    12262     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    12263     68/push 0/imm32
    12264     68/push 0/imm32
    12265     89/<- %edx 4/r32/esp
    12266     (tailor-exit-descriptor %edx 0x10)
    12267     #
    12268     (write _test-input-stream "fn foo {\n")
    12269     (write _test-input-stream "  var a: (array int 3)\n")
    12270     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a, 0, 0\n")
    12271     (write _test-input-stream "}\n")
    12272     # convert
    12273     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    12274     # registers except esp clobbered at this point
    12275     # restore ed
    12276     89/<- %edx 4/r32/esp
    12277     (flush _test-output-buffered-file)
    12278     (flush _test-error-buffered-file)
    12279 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    12285     # check output
    12286     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-too-many-inouts: output should be empty")
    12287     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt compute-offset: too many inouts (2 required)"  "F - test-compute-offset-with-too-many-inouts: error message")
    12288     # check that stop(1) was called
    12289     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-too-many-inouts: exit status")
    12290     # don't restore from ebp
    12291     81 0/subop/add %esp 8/imm32
    12292     # . epilogue
    12293     5d/pop-to-ebp
    12294     c3/return
    12295
    12296 test-compute-offset-with-no-output:
    12297     # . prologue
    12298     55/push-ebp
    12299     89/<- %ebp 4/r32/esp
    12300     # setup
    12301     (clear-stream _test-input-stream)
    12302     (clear-stream $_test-input-buffered-file->buffer)
    12303     (clear-stream _test-output-stream)
    12304     (clear-stream $_test-output-buffered-file->buffer)
    12305     (clear-stream _test-error-stream)
    12306     (clear-stream $_test-error-buffered-file->buffer)
    12307     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    12308     68/push 0/imm32
    12309     68/push 0/imm32
    12310     89/<- %edx 4/r32/esp
    12311     (tailor-exit-descriptor %edx 0x10)
    12312     #
    12313     (write _test-input-stream "fn foo {\n")
    12314     (write _test-input-stream "  var a: (array int 3)\n")
    12315     (write _test-input-stream "  compute-offset a, 0\n")
    12316     (write _test-input-stream "}\n")
    12317     # convert
    12318     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    12319     # registers except esp clobbered at this point
    12320     # restore ed
    12321     89/<- %edx 4/r32/esp
    12322     (flush _test-output-buffered-file)
    12323     (flush _test-error-buffered-file)
    12324 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    12330     # check output
    12331     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-no-output: output should be empty")
    12332     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt compute-offset: must have an output"  "F - test-compute-offset-with-no-output: error message")
    12333     # check that stop(1) was called
    12334     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-no-output: exit status")
    12335     # don't restore from ebp
    12336     81 0/subop/add %esp 8/imm32
    12337     # . epilogue
    12338     5d/pop-to-ebp
    12339     c3/return
    12340
    12341 test-compute-offset-with-too-many-outputs:
    12342     # . prologue
    12343     55/push-ebp
    12344     89/<- %ebp 4/r32/esp
    12345     # setup
    12346     (clear-stream _test-input-stream)
    12347     (clear-stream $_test-input-buffered-file->buffer)
    12348     (clear-stream _test-output-stream)
    12349     (clear-stream $_test-output-buffered-file->buffer)
    12350     (clear-stream _test-error-stream)
    12351     (clear-stream $_test-error-buffered-file->buffer)
    12352     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    12353     68/push 0/imm32
    12354     68/push 0/imm32
    12355     89/<- %edx 4/r32/esp
    12356     (tailor-exit-descriptor %edx 0x10)
    12357     #
    12358     (write _test-input-stream "fn foo {\n")
    12359     (write _test-input-stream "  var a: (array int 3)\n")
    12360     (write _test-input-stream "  var b/eax: (offset int) <- compute-offset a, 0\n")
    12361     (write _test-input-stream "  var c/ecx: (addr int) <- copy 0\n")
    12362     (write _test-input-stream "  b, c <- compute-offset a, 0\n")
    12363     (write _test-input-stream "}\n")
    12364     # convert
    12365     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    12366     # registers except esp clobbered at this point
    12367     # restore ed
    12368     89/<- %edx 4/r32/esp
    12369     (flush _test-output-buffered-file)
    12370     (flush _test-error-buffered-file)
    12371 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    12377     # check output
    12378     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-too-many-outputs: output should be empty")
    12379     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt compute-offset: too many outputs (1 required)"  "F - test-compute-offset-with-too-many-outputs: error message")
    12380     # check that stop(1) was called
    12381     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-too-many-outputs: exit status")
    12382     # don't restore from ebp
    12383     81 0/subop/add %esp 8/imm32
    12384     # . epilogue
    12385     5d/pop-to-ebp
    12386     c3/return
    12387
    12388 test-convert-read-from-stream:
    12389     # . prologue
    12390     55/push-ebp
    12391     89/<- %ebp 4/r32/esp
    12392     # setup
    12393     (clear-stream _test-input-stream)
    12394     (clear-stream $_test-input-buffered-file->buffer)
    12395     (clear-stream _test-output-stream)
    12396     (clear-stream $_test-output-buffered-file->buffer)
    12397     #
    12398     (write _test-input-stream "fn foo {\n")
    12399     (write _test-input-stream "  var s/esi: (addr stream int) <- copy 0\n")
    12400     (write _test-input-stream "  var o/ecx: (addr int) <- copy 0\n")
    12401     (write _test-input-stream "  read-from-stream s, o\n")
    12402     (write _test-input-stream "}\n")
    12403     # convert
    12404     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
    12405     # registers except esp clobbered at this point
    12406     # restore ed
    12407     89/<- %edx 4/r32/esp
    12408     (flush _test-output-buffered-file)
    12409     (flush _test-error-buffered-file)
    12410 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
    12416     # check output
    12417     (check-next-stream-line-equal _test-output-stream "foo:"                            "F - test-convert-read-from-stream/0")
    12418     (check-next-stream-line-equal _test-output-stream "  # . prologue"                  "F - test-convert-read-from-stream/1")
    12419     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                   "F - test-convert-read-from-stream/2")
    12420     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"          "F - test-convert-read-from-stream/3")
    12421     (check-next-stream-line-equal _test-output-stream "  {"                             "F - test-convert-read-from-stream/4")
    12422     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"           "F - test-convert-read-from-stream/5")
    12423     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %esi"        "F - test-convert-read-from-stream/6")
    12424     (check-next-stream-line-equal _test-output-stream "    be/copy-to-esi 0/imm32"      "F - test-convert-read-from-stream/7")
    12425     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"        "F - test-convert-read-from-stream/8")
    12426     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"      "F - test-convert-read-from-stream/9")
    12427     (check-next-stream-line-equal _test-output-stream "    (read-from-stream %esi %ecx 0x00000004)"  "F - test-convert-read-from-stream/10")
    12428     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"         "F - test-convert-read-from-stream/11")
    12429     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %esi"         "F - test-convert-read-from-stream/12")
    12430     (check-next-stream-line-equal _test-output-stream "  }"                             "F - test-convert-read-from-stream/13")
    12431     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"          "F - test-convert-read-from-stream/14")
    12432     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                  "F - test-convert-read-from-stream/15")
    12433     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"          "F - test-convert-read-from-stream/16")
    12434     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                 "F - test-convert-read-from-stream/17")
    12435     (check-next-stream-line-equal _test-output-stream "  c3/return"                     "F - test-convert-read-from-stream/18")
    12436     # . epilogue
    12437     89/<- %esp 5/r32/ebp
    12438     5d/pop-to-ebp
    12439     c3/return
    12440
    12441 test-convert-read-from-stream-with-correct-payload-size:
    12442     # . prologue
    12443     55/push-ebp
    12444     89/<- %ebp 4/r32/esp
    12445     # setup
    12446     (clear-stream _test-input-stream)
    12447     (clear-stream $_test-input-buffered-file->buffer)
    12448     (clear-stream _test-output-stream)
    12449     (clear-stream $_test-output-buffered-file->buffer)
    12450     #
    12451     (write _test-input-stream "fn foo {\n")
    12452     (write _test-input-stream "  var s/esi: (addr stream handle int) <- copy 0\n")
    12453     (write _test-input-stream "  var o/ecx: (addr handle int) <- copy 0\n")
    12454     (write _test-input-stream "  read-from-stream s, o\n")
    12455     (write _test-input-stream "}\n")
    12456     # convert
    12457     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
    12458     # registers except esp clobbered at this point
    12459     # restore ed
    12460     89/<- %edx 4/r32/esp
    12461     (flush _test-output-buffered-file)
    12462     (flush _test-error-buffered-file)
    12463 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
    12469     # check output
    12470     (check-next-stream-line-equal _test-output-stream "foo:"                            "F - test-convert-read-from-stream-with-correct-payload-size/0")
    12471     (check-next-stream-line-equal _test-output-stream "  # . prologue"                  "F - test-convert-read-from-stream-with-correct-payload-size/1")
    12472     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                   "F - test-convert-read-from-stream-with-correct-payload-size/2")
    12473     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"          "F - test-convert-read-from-stream-with-correct-payload-size/3")
    12474     (check-next-stream-line-equal _test-output-stream "  {"                             "F - test-convert-read-from-stream-with-correct-payload-size/4")
    12475     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"           "F - test-convert-read-from-stream-with-correct-payload-size/5")
    12476     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %esi"        "F - test-convert-read-from-stream-with-correct-payload-size/6")
    12477     (check-next-stream-line-equal _test-output-stream "    be/copy-to-esi 0/imm32"      "F - test-convert-read-from-stream-with-correct-payload-size/7")
    12478     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"        "F - test-convert-read-from-stream-with-correct-payload-size/8")
    12479     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"      "F - test-convert-read-from-stream-with-correct-payload-size/9")
    12480     (check-next-stream-line-equal _test-output-stream "    (read-from-stream %esi %ecx 0x00000008)"  "F - test-convert-read-from-stream-with-correct-payload-size/10")
    12481     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"         "F - test-convert-read-from-stream-with-correct-payload-size/11")
    12482     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %esi"         "F - test-convert-read-from-stream-with-correct-payload-size/12")
    12483     (check-next-stream-line-equal _test-output-stream "  }"                             "F - test-convert-read-from-stream-with-correct-payload-size/13")
    12484     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"          "F - test-convert-read-from-stream-with-correct-payload-size/14")
    12485     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                  "F - test-convert-read-from-stream-with-correct-payload-size/15")
    12486     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"          "F - test-convert-read-from-stream-with-correct-payload-size/16")
    12487     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                 "F - test-convert-read-from-stream-with-correct-payload-size/17")
    12488     (check-next-stream-line-equal _test-output-stream "  c3/return"                     "F - test-convert-read-from-stream-with-correct-payload-size/18")
    12489     # . epilogue
    12490     89/<- %esp 5/r32/ebp
    12491     5d/pop-to-ebp
    12492     c3/return
    12493
    12494 test-read-from-stream-with-non-stream-atom-base-type:
    12495     # . prologue
    12496     55/push-ebp
    12497     89/<- %ebp 4/r32/esp
    12498     # setup
    12499     (clear-stream _test-input-stream)
    12500     (clear-stream $_test-input-buffered-file->buffer)
    12501     (clear-stream _test-output-stream)
    12502     (clear-stream $_test-output-buffered-file->buffer)
    12503     (clear-stream _test-error-stream)
    12504     (clear-stream $_test-error-buffered-file->buffer)
    12505     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    12506     68/push 0/imm32
    12507     68/push 0/imm32
    12508     89/<- %edx 4/r32/esp
    12509     (tailor-exit-descriptor %edx 0x10)
    12510     #
    12511     (write _test-input-stream "fn foo {\n")
    12512     (write _test-input-stream "  var a: int\n")
    12513     (write _test-input-stream "  read-from-stream a, 0\n")
    12514     (write _test-input-stream "}\n")
    12515     # convert
    12516     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    12517     # registers except esp clobbered at this point
    12518     # restore ed
    12519     89/<- %edx 4/r32/esp
    12520     (flush _test-output-buffered-file)
    12521     (flush _test-error-buffered-file)
    12522 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    12528     # check output
    12529     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-non-stream-atom-base-type: output should be empty")
    12530     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt read-from-stream: var 'a' must be an addr to a stream"  "F - test-read-from-stream-with-non-stream-atom-base-type: error message")
    12531     # check that stop(1) was called
    12532     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-non-stream-atom-base-type: exit status")
    12533     # don't restore from ebp
    12534     81 0/subop/add %esp 8/imm32
    12535     # . epilogue
    12536     5d/pop-to-ebp
    12537     c3/return
    12538
    12539 test-read-from-stream-with-non-stream-compound-base-type:
    12540     # . prologue
    12541     55/push-ebp
    12542     89/<- %ebp 4/r32/esp
    12543     # setup
    12544     (clear-stream _test-input-stream)
    12545     (clear-stream $_test-input-buffered-file->buffer)
    12546     (clear-stream _test-output-stream)
    12547     (clear-stream $_test-output-buffered-file->buffer)
    12548     (clear-stream _test-error-stream)
    12549     (clear-stream $_test-error-buffered-file->buffer)
    12550     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    12551     68/push 0/imm32
    12552     68/push 0/imm32
    12553     89/<- %edx 4/r32/esp
    12554     (tailor-exit-descriptor %edx 0x10)
    12555     #
    12556     (write _test-input-stream "fn foo {\n")
    12557     (write _test-input-stream "  var a: (handle int)\n")
    12558     (write _test-input-stream "  read-from-stream a, 0\n")
    12559     (write _test-input-stream "}\n")
    12560     # convert
    12561     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    12562     # registers except esp clobbered at this point
    12563     # restore ed
    12564     89/<- %edx 4/r32/esp
    12565     (flush _test-output-buffered-file)
    12566     (flush _test-error-buffered-file)
    12567 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    12573     # check output
    12574     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-non-stream-compound-base-type: output should be empty")
    12575     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt read-from-stream: var 'a' must be an addr to a stream"  "F - test-read-from-stream-with-non-stream-compound-base-type: error message")
    12576     # check that stop(1) was called
    12577     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-non-stream-compound-base-type: exit status")
    12578     # don't restore from ebp
    12579     81 0/subop/add %esp 8/imm32
    12580     # . epilogue
    12581     5d/pop-to-ebp
    12582     c3/return
    12583
    12584 test-read-from-stream-with-non-stream-compound-base-type-2:
    12585     # . prologue
    12586     55/push-ebp
    12587     89/<- %ebp 4/r32/esp
    12588     # setup
    12589     (clear-stream _test-input-stream)
    12590     (clear-stream $_test-input-buffered-file->buffer)
    12591     (clear-stream _test-output-stream)
    12592     (clear-stream $_test-output-buffered-file->buffer)
    12593     (clear-stream _test-error-stream)
    12594     (clear-stream $_test-error-buffered-file->buffer)
    12595     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    12596     68/push 0/imm32
    12597     68/push 0/imm32
    12598     89/<- %edx 4/r32/esp
    12599     (tailor-exit-descriptor %edx 0x10)
    12600     #
    12601     (write _test-input-stream "fn foo {\n")
    12602     (write _test-input-stream "  var a: (addr int)\n")
    12603     (write _test-input-stream "  read-from-stream a, 0\n")
    12604     (write _test-input-stream "}\n")
    12605     # convert
    12606     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    12607     # registers except esp clobbered at this point
    12608     # restore ed
    12609     89/<- %edx 4/r32/esp
    12610     (flush _test-output-buffered-file)
    12611     (flush _test-error-buffered-file)
    12612 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    12618     # check output
    12619     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-non-stream-compound-base-type-2: output should be empty")
    12620     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt read-from-stream: var 'a' must be an addr to a stream"  "F - test-read-from-stream-with-non-stream-compound-base-type-2: error message")
    12621     # check that stop(1) was called
    12622     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-non-stream-compound-base-type-2: exit status")
    12623     # don't restore from ebp
    12624     81 0/subop/add %esp 8/imm32
    12625     # . epilogue
    12626     5d/pop-to-ebp
    12627     c3/return
    12628
    12629 test-read-from-stream-with-stream-atom-base-type:
    12630     # . prologue
    12631     55/push-ebp
    12632     89/<- %ebp 4/r32/esp
    12633     # setup
    12634     (clear-stream _test-input-stream)
    12635     (clear-stream $_test-input-buffered-file->buffer)
    12636     (clear-stream _test-output-stream)
    12637     (clear-stream $_test-output-buffered-file->buffer)
    12638     (clear-stream _test-error-stream)
    12639     (clear-stream $_test-error-buffered-file->buffer)
    12640     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    12641     68/push 0/imm32
    12642     68/push 0/imm32
    12643     89/<- %edx 4/r32/esp
    12644     (tailor-exit-descriptor %edx 0x10)
    12645     #
    12646     (write _test-input-stream "fn foo {\n")
    12647     (write _test-input-stream "  var a: stream\n")
    12648     (write _test-input-stream "  read-from-stream a, 0\n")
    12649     (write _test-input-stream "}\n")
    12650     # convert
    12651     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    12652     # registers except esp clobbered at this point
    12653     # restore ed
    12654     89/<- %edx 4/r32/esp
    12655     (flush _test-output-buffered-file)
    12656     (flush _test-error-buffered-file)
    12657 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    12663     # check output
    12664     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-stream-atom-base-type: output should be empty")
    12665     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt read-from-stream: var 'a' must be an addr to a stream"  "F - test-read-from-stream-with-stream-atom-base-type: error message")
    12666     # check that stop(1) was called
    12667     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-stream-atom-base-type: exit status")
    12668     # don't restore from ebp
    12669     81 0/subop/add %esp 8/imm32
    12670     # . epilogue
    12671     5d/pop-to-ebp
    12672     c3/return
    12673
    12674 test-read-from-stream-with-wrong-index-type:
    12675     # . prologue
    12676     55/push-ebp
    12677     89/<- %ebp 4/r32/esp
    12678     # setup
    12679     (clear-stream _test-input-stream)
    12680     (clear-stream $_test-input-buffered-file->buffer)
    12681     (clear-stream _test-output-stream)
    12682     (clear-stream $_test-output-buffered-file->buffer)
    12683     (clear-stream _test-error-stream)
    12684     (clear-stream $_test-error-buffered-file->buffer)
    12685     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    12686     68/push 0/imm32
    12687     68/push 0/imm32
    12688     89/<- %edx 4/r32/esp
    12689     (tailor-exit-descriptor %edx 0x10)
    12690     #
    12691     (write _test-input-stream "fn foo {\n")
    12692     (write _test-input-stream "  var a/eax: (addr stream int) <- copy 0\n")
    12693     (write _test-input-stream "  var b: boolean\n")
    12694     (write _test-input-stream "  read-from-stream a, b\n")
    12695     (write _test-input-stream "}\n")
    12696     # convert
    12697     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    12698     # registers except esp clobbered at this point
    12699     # restore ed
    12700     89/<- %edx 4/r32/esp
    12701     (flush _test-output-buffered-file)
    12702     (flush _test-error-buffered-file)
    12703 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    12709     # check output
    12710     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-wrong-index-type: output should be empty")
    12711     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt read-from-stream: target 'b' must be an addr"  "F - test-read-from-stream-with-wrong-index-type: error message")
    12712     # check that stop(1) was called
    12713     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-wrong-index-type: exit status")
    12714     # don't restore from ebp
    12715     81 0/subop/add %esp 8/imm32
    12716     # . epilogue
    12717     5d/pop-to-ebp
    12718     c3/return
    12719
    12720 test-read-from-stream-with-no-inouts:
    12721     # . prologue
    12722     55/push-ebp
    12723     89/<- %ebp 4/r32/esp
    12724     # setup
    12725     (clear-stream _test-input-stream)
    12726     (clear-stream $_test-input-buffered-file->buffer)
    12727     (clear-stream _test-output-stream)
    12728     (clear-stream $_test-output-buffered-file->buffer)
    12729     (clear-stream _test-error-stream)
    12730     (clear-stream $_test-error-buffered-file->buffer)
    12731     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    12732     68/push 0/imm32
    12733     68/push 0/imm32
    12734     89/<- %edx 4/r32/esp
    12735     (tailor-exit-descriptor %edx 0x10)
    12736     #
    12737     (write _test-input-stream "fn foo {\n")
    12738     (write _test-input-stream "  read-from-stream\n")
    12739     (write _test-input-stream "}\n")
    12740     # convert
    12741     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    12742     # registers except esp clobbered at this point
    12743     # restore ed
    12744     89/<- %edx 4/r32/esp
    12745     (flush _test-output-buffered-file)
    12746     (flush _test-error-buffered-file)
    12747 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    12753     # check output
    12754     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-no-inouts: output should be empty")
    12755     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt read-from-stream: too few inouts (2 required)"  "F - test-read-from-stream-with-no-inouts: error message")
    12756     # check that stop(1) was called
    12757     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-no-inouts: exit status")
    12758     # don't restore from ebp
    12759     81 0/subop/add %esp 8/imm32
    12760     # . epilogue
    12761     5d/pop-to-ebp
    12762     c3/return
    12763
    12764 test-read-from-stream-with-too-few-inouts:
    12765     # . prologue
    12766     55/push-ebp
    12767     89/<- %ebp 4/r32/esp
    12768     # setup
    12769     (clear-stream _test-input-stream)
    12770     (clear-stream $_test-input-buffered-file->buffer)
    12771     (clear-stream _test-output-stream)
    12772     (clear-stream $_test-output-buffered-file->buffer)
    12773     (clear-stream _test-error-stream)
    12774     (clear-stream $_test-error-buffered-file->buffer)
    12775     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    12776     68/push 0/imm32
    12777     68/push 0/imm32
    12778     89/<- %edx 4/r32/esp
    12779     (tailor-exit-descriptor %edx 0x10)
    12780     #
    12781     (write _test-input-stream "fn foo {\n")
    12782     (write _test-input-stream "  var a: (addr stream int)\n")
    12783     (write _test-input-stream "  read-from-stream a\n")
    12784     (write _test-input-stream "}\n")
    12785     # convert
    12786     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    12787     # registers except esp clobbered at this point
    12788     # restore ed
    12789     89/<- %edx 4/r32/esp
    12790     (flush _test-output-buffered-file)
    12791     (flush _test-error-buffered-file)
    12792 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    12798     # check output
    12799     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-too-few-inouts: output should be empty")
    12800     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt read-from-stream: too few inouts (2 required)"  "F - test-read-from-stream-with-too-few-inouts: error message")
    12801     # check that stop(1) was called
    12802     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-too-few-inouts: exit status")
    12803     # don't restore from ebp
    12804     81 0/subop/add %esp 8/imm32
    12805     # . epilogue
    12806     5d/pop-to-ebp
    12807     c3/return
    12808
    12809 test-read-from-stream-with-too-many-inouts:
    12810     # . prologue
    12811     55/push-ebp
    12812     89/<- %ebp 4/r32/esp
    12813     # setup
    12814     (clear-stream _test-input-stream)
    12815     (clear-stream $_test-input-buffered-file->buffer)
    12816     (clear-stream _test-output-stream)
    12817     (clear-stream $_test-output-buffered-file->buffer)
    12818     (clear-stream _test-error-stream)
    12819     (clear-stream $_test-error-buffered-file->buffer)
    12820     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    12821     68/push 0/imm32
    12822     68/push 0/imm32
    12823     89/<- %edx 4/r32/esp
    12824     (tailor-exit-descriptor %edx 0x10)
    12825     #
    12826     (write _test-input-stream "fn foo {\n")
    12827     (write _test-input-stream "  var a: (addr stream int)\n")
    12828     (write _test-input-stream "  var b: (addr int)\n")
    12829     (write _test-input-stream "  read-from-stream a, b, 0\n")
    12830     (write _test-input-stream "}\n")
    12831     # convert
    12832     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    12833     # registers except esp clobbered at this point
    12834     # restore ed
    12835     89/<- %edx 4/r32/esp
    12836     (flush _test-output-buffered-file)
    12837     (flush _test-error-buffered-file)
    12838 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    12844     # check output
    12845     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-too-many-inouts: output should be empty")
    12846     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt read-from-stream: too many inouts (2 required)"  "F - test-read-from-stream-with-too-many-inouts: error message")
    12847     # check that stop(1) was called
    12848     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-too-many-inouts: exit status")
    12849     # don't restore from ebp
    12850     81 0/subop/add %esp 8/imm32
    12851     # . epilogue
    12852     5d/pop-to-ebp
    12853     c3/return
    12854
    12855 test-read-from-stream-with-output:
    12856     # . prologue
    12857     55/push-ebp
    12858     89/<- %ebp 4/r32/esp
    12859     # setup
    12860     (clear-stream _test-input-stream)
    12861     (clear-stream $_test-input-buffered-file->buffer)
    12862     (clear-stream _test-output-stream)
    12863     (clear-stream $_test-output-buffered-file->buffer)
    12864     (clear-stream _test-error-stream)
    12865     (clear-stream $_test-error-buffered-file->buffer)
    12866     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    12867     68/push 0/imm32
    12868     68/push 0/imm32
    12869     89/<- %edx 4/r32/esp
    12870     (tailor-exit-descriptor %edx 0x10)
    12871     #
    12872     (write _test-input-stream "fn foo {\n")
    12873     (write _test-input-stream "  var a: (addr stream int)\n")
    12874     (write _test-input-stream "  var b/eax: (addr int) <- copy 0\n")
    12875     (write _test-input-stream "  b <- read-from-stream a, b\n")
    12876     (write _test-input-stream "}\n")
    12877     # convert
    12878     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    12879     # registers except esp clobbered at this point
    12880     # restore ed
    12881     89/<- %edx 4/r32/esp
    12882     (flush _test-output-buffered-file)
    12883     (flush _test-error-buffered-file)
    12884 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    12890     # check output
    12891     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-output: output should be empty")
    12892     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt read-from-stream: unexpected output"  "F - test-read-from-stream-with-output: error message")
    12893     # check that stop(1) was called
    12894     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-output: exit status")
    12895     # don't restore from ebp
    12896     81 0/subop/add %esp 8/imm32
    12897     # . epilogue
    12898     5d/pop-to-ebp
    12899     c3/return
    12900
    12901 test-convert-write-to-stream:
    12902     # . prologue
    12903     55/push-ebp
    12904     89/<- %ebp 4/r32/esp
    12905     # setup
    12906     (clear-stream _test-input-stream)
    12907     (clear-stream $_test-input-buffered-file->buffer)
    12908     (clear-stream _test-output-stream)
    12909     (clear-stream $_test-output-buffered-file->buffer)
    12910     #
    12911     (write _test-input-stream "fn foo {\n")
    12912     (write _test-input-stream "  var s/esi: (addr stream int) <- copy 0\n")
    12913     (write _test-input-stream "  var o/ecx: (addr int) <- copy 0\n")
    12914     (write _test-input-stream "  write-to-stream s, o\n")
    12915     (write _test-input-stream "}\n")
    12916     # convert
    12917     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
    12918     # registers except esp clobbered at this point
    12919     # restore ed
    12920     89/<- %edx 4/r32/esp
    12921     (flush _test-output-buffered-file)
    12922     (flush _test-error-buffered-file)
    12923 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
    12929     # check output
    12930     (check-next-stream-line-equal _test-output-stream "foo:"                            "F - test-convert-write-to-stream/0")
    12931     (check-next-stream-line-equal _test-output-stream "  # . prologue"                  "F - test-convert-write-to-stream/1")
    12932     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                   "F - test-convert-write-to-stream/2")
    12933     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"          "F - test-convert-write-to-stream/3")
    12934     (check-next-stream-line-equal _test-output-stream "  {"                             "F - test-convert-write-to-stream/4")
    12935     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"           "F - test-convert-write-to-stream/5")
    12936     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %esi"        "F - test-convert-write-to-stream/6")
    12937     (check-next-stream-line-equal _test-output-stream "    be/copy-to-esi 0/imm32"      "F - test-convert-write-to-stream/7")
    12938     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"        "F - test-convert-write-to-stream/8")
    12939     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"      "F - test-convert-write-to-stream/9")
    12940     (check-next-stream-line-equal _test-output-stream "    (write-to-stream %esi %ecx 0x00000004)"  "F - test-convert-write-to-stream/10")
    12941     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"         "F - test-convert-write-to-stream/11")
    12942     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %esi"         "F - test-convert-write-to-stream/12")
    12943     (check-next-stream-line-equal _test-output-stream "  }"                             "F - test-convert-write-to-stream/13")
    12944     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"          "F - test-convert-write-to-stream/14")
    12945     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                  "F - test-convert-write-to-stream/15")
    12946     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"          "F - test-convert-write-to-stream/16")
    12947     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                 "F - test-convert-write-to-stream/17")
    12948     (check-next-stream-line-equal _test-output-stream "  c3/return"                     "F - test-convert-write-to-stream/18")
    12949     # . epilogue
    12950     89/<- %esp 5/r32/ebp
    12951     5d/pop-to-ebp
    12952     c3/return
    12953
    12954 test-convert-write-to-stream-with-correct-payload-size:
    12955     # . prologue
    12956     55/push-ebp
    12957     89/<- %ebp 4/r32/esp
    12958     # setup
    12959     (clear-stream _test-input-stream)
    12960     (clear-stream $_test-input-buffered-file->buffer)
    12961     (clear-stream _test-output-stream)
    12962     (clear-stream $_test-output-buffered-file->buffer)
    12963     #
    12964     (write _test-input-stream "fn foo {\n")
    12965     (write _test-input-stream "  var s/esi: (addr stream handle int) <- copy 0\n")
    12966     (write _test-input-stream "  var o/ecx: (addr handle int) <- copy 0\n")
    12967     (write _test-input-stream "  write-to-stream s, o\n")
    12968     (write _test-input-stream "}\n")
    12969     # convert
    12970     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
    12971     # registers except esp clobbered at this point
    12972     # restore ed
    12973     89/<- %edx 4/r32/esp
    12974     (flush _test-output-buffered-file)
    12975     (flush _test-error-buffered-file)
    12976 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
    12982     # check output
    12983     (check-next-stream-line-equal _test-output-stream "foo:"                            "F - test-convert-write-to-stream-with-correct-payload-size/0")
    12984     (check-next-stream-line-equal _test-output-stream "  # . prologue"                  "F - test-convert-write-to-stream-with-correct-payload-size/1")
    12985     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                   "F - test-convert-write-to-stream-with-correct-payload-size/2")
    12986     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"          "F - test-convert-write-to-stream-with-correct-payload-size/3")
    12987     (check-next-stream-line-equal _test-output-stream "  {"                             "F - test-convert-write-to-stream-with-correct-payload-size/4")
    12988     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"           "F - test-convert-write-to-stream-with-correct-payload-size/5")
    12989     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %esi"        "F - test-convert-write-to-stream-with-correct-payload-size/6")
    12990     (check-next-stream-line-equal _test-output-stream "    be/copy-to-esi 0/imm32"      "F - test-convert-write-to-stream-with-correct-payload-size/7")
    12991     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"        "F - test-convert-write-to-stream-with-correct-payload-size/8")
    12992     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"      "F - test-convert-write-to-stream-with-correct-payload-size/9")
    12993     (check-next-stream-line-equal _test-output-stream "    (write-to-stream %esi %ecx 0x00000008)"  "F - test-convert-write-to-stream-with-correct-payload-size/10")
    12994     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"         "F - test-convert-write-to-stream-with-correct-payload-size/11")
    12995     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %esi"         "F - test-convert-write-to-stream-with-correct-payload-size/12")
    12996     (check-next-stream-line-equal _test-output-stream "  }"                             "F - test-convert-write-to-stream-with-correct-payload-size/13")
    12997     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"          "F - test-convert-write-to-stream-with-correct-payload-size/14")
    12998     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                  "F - test-convert-write-to-stream-with-correct-payload-size/15")
    12999     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"          "F - test-convert-write-to-stream-with-correct-payload-size/16")
    13000     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                 "F - test-convert-write-to-stream-with-correct-payload-size/17")
    13001     (check-next-stream-line-equal _test-output-stream "  c3/return"                     "F - test-convert-write-to-stream-with-correct-payload-size/18")
    13002     # . epilogue
    13003     89/<- %esp 5/r32/ebp
    13004     5d/pop-to-ebp
    13005     c3/return
    13006
    13007 test-write-to-stream-with-non-stream-atom-base-type:
    13008     # . prologue
    13009     55/push-ebp
    13010     89/<- %ebp 4/r32/esp
    13011     # setup
    13012     (clear-stream _test-input-stream)
    13013     (clear-stream $_test-input-buffered-file->buffer)
    13014     (clear-stream _test-output-stream)
    13015     (clear-stream $_test-output-buffered-file->buffer)
    13016     (clear-stream _test-error-stream)
    13017     (clear-stream $_test-error-buffered-file->buffer)
    13018     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    13019     68/push 0/imm32
    13020     68/push 0/imm32
    13021     89/<- %edx 4/r32/esp
    13022     (tailor-exit-descriptor %edx 0x10)
    13023     #
    13024     (write _test-input-stream "fn foo {\n")
    13025     (write _test-input-stream "  var a: int\n")
    13026     (write _test-input-stream "  write-to-stream a, 0\n")
    13027     (write _test-input-stream "}\n")
    13028     # convert
    13029     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    13030     # registers except esp clobbered at this point
    13031     # restore ed
    13032     89/<- %edx 4/r32/esp
    13033     (flush _test-output-buffered-file)
    13034     (flush _test-error-buffered-file)
    13035 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    13041     # check output
    13042     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-non-stream-atom-base-type: output should be empty")
    13043     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt write-to-stream: var 'a' must be an addr to a stream"  "F - test-write-to-stream-with-non-stream-atom-base-type: error message")
    13044     # check that stop(1) was called
    13045     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-non-stream-atom-base-type: exit status")
    13046     # don't restore from ebp
    13047     81 0/subop/add %esp 8/imm32
    13048     # . epilogue
    13049     5d/pop-to-ebp
    13050     c3/return
    13051
    13052 test-write-to-stream-with-non-stream-compound-base-type:
    13053     # . prologue
    13054     55/push-ebp
    13055     89/<- %ebp 4/r32/esp
    13056     # setup
    13057     (clear-stream _test-input-stream)
    13058     (clear-stream $_test-input-buffered-file->buffer)
    13059     (clear-stream _test-output-stream)
    13060     (clear-stream $_test-output-buffered-file->buffer)
    13061     (clear-stream _test-error-stream)
    13062     (clear-stream $_test-error-buffered-file->buffer)
    13063     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    13064     68/push 0/imm32
    13065     68/push 0/imm32
    13066     89/<- %edx 4/r32/esp
    13067     (tailor-exit-descriptor %edx 0x10)
    13068     #
    13069     (write _test-input-stream "fn foo {\n")
    13070     (write _test-input-stream "  var a: (handle int)\n")
    13071     (write _test-input-stream "  write-to-stream a, 0\n")
    13072     (write _test-input-stream "}\n")
    13073     # convert
    13074     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    13075     # registers except esp clobbered at this point
    13076     # restore ed
    13077     89/<- %edx 4/r32/esp
    13078     (flush _test-output-buffered-file)
    13079     (flush _test-error-buffered-file)
    13080 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    13086     # check output
    13087     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-non-stream-compound-base-type: output should be empty")
    13088     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt write-to-stream: var 'a' must be an addr to a stream"  "F - test-write-to-stream-with-non-stream-compound-base-type: error message")
    13089     # check that stop(1) was called
    13090     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-non-stream-compound-base-type: exit status")
    13091     # don't restore from ebp
    13092     81 0/subop/add %esp 8/imm32
    13093     # . epilogue
    13094     5d/pop-to-ebp
    13095     c3/return
    13096
    13097 test-write-to-stream-with-non-stream-compound-base-type-2:
    13098     # . prologue
    13099     55/push-ebp
    13100     89/<- %ebp 4/r32/esp
    13101     # setup
    13102     (clear-stream _test-input-stream)
    13103     (clear-stream $_test-input-buffered-file->buffer)
    13104     (clear-stream _test-output-stream)
    13105     (clear-stream $_test-output-buffered-file->buffer)
    13106     (clear-stream _test-error-stream)
    13107     (clear-stream $_test-error-buffered-file->buffer)
    13108     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    13109     68/push 0/imm32
    13110     68/push 0/imm32
    13111     89/<- %edx 4/r32/esp
    13112     (tailor-exit-descriptor %edx 0x10)
    13113     #
    13114     (write _test-input-stream "fn foo {\n")
    13115     (write _test-input-stream "  var a: (addr int)\n")
    13116     (write _test-input-stream "  write-to-stream a, 0\n")
    13117     (write _test-input-stream "}\n")
    13118     # convert
    13119     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    13120     # registers except esp clobbered at this point
    13121     # restore ed
    13122     89/<- %edx 4/r32/esp
    13123     (flush _test-output-buffered-file)
    13124     (flush _test-error-buffered-file)
    13125 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    13131     # check output
    13132     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-non-stream-compound-base-type-2: output should be empty")
    13133     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt write-to-stream: var 'a' must be an addr to a stream"  "F - test-write-to-stream-with-non-stream-compound-base-type-2: error message")
    13134     # check that stop(1) was called
    13135     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-non-stream-compound-base-type-2: exit status")
    13136     # don't restore from ebp
    13137     81 0/subop/add %esp 8/imm32
    13138     # . epilogue
    13139     5d/pop-to-ebp
    13140     c3/return
    13141
    13142 test-write-to-stream-with-stream-atom-base-type:
    13143     # . prologue
    13144     55/push-ebp
    13145     89/<- %ebp 4/r32/esp
    13146     # setup
    13147     (clear-stream _test-input-stream)
    13148     (clear-stream $_test-input-buffered-file->buffer)
    13149     (clear-stream _test-output-stream)
    13150     (clear-stream $_test-output-buffered-file->buffer)
    13151     (clear-stream _test-error-stream)
    13152     (clear-stream $_test-error-buffered-file->buffer)
    13153     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    13154     68/push 0/imm32
    13155     68/push 0/imm32
    13156     89/<- %edx 4/r32/esp
    13157     (tailor-exit-descriptor %edx 0x10)
    13158     #
    13159     (write _test-input-stream "fn foo {\n")
    13160     (write _test-input-stream "  var a: stream\n")
    13161     (write _test-input-stream "  write-to-stream a, 0\n")
    13162     (write _test-input-stream "}\n")
    13163     # convert
    13164     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    13165     # registers except esp clobbered at this point
    13166     # restore ed
    13167     89/<- %edx 4/r32/esp
    13168     (flush _test-output-buffered-file)
    13169     (flush _test-error-buffered-file)
    13170 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    13176     # check output
    13177     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-stream-atom-base-type: output should be empty")
    13178     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt write-to-stream: var 'a' must be an addr to a stream"  "F - test-write-to-stream-with-stream-atom-base-type: error message")
    13179     # check that stop(1) was called
    13180     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-stream-atom-base-type: exit status")
    13181     # don't restore from ebp
    13182     81 0/subop/add %esp 8/imm32
    13183     # . epilogue
    13184     5d/pop-to-ebp
    13185     c3/return
    13186
    13187 test-write-to-stream-with-wrong-index-type:
    13188     # . prologue
    13189     55/push-ebp
    13190     89/<- %ebp 4/r32/esp
    13191     # setup
    13192     (clear-stream _test-input-stream)
    13193     (clear-stream $_test-input-buffered-file->buffer)
    13194     (clear-stream _test-output-stream)
    13195     (clear-stream $_test-output-buffered-file->buffer)
    13196     (clear-stream _test-error-stream)
    13197     (clear-stream $_test-error-buffered-file->buffer)
    13198     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    13199     68/push 0/imm32
    13200     68/push 0/imm32
    13201     89/<- %edx 4/r32/esp
    13202     (tailor-exit-descriptor %edx 0x10)
    13203     #
    13204     (write _test-input-stream "fn foo {\n")
    13205     (write _test-input-stream "  var a/eax: (addr stream int) <- copy 0\n")
    13206     (write _test-input-stream "  var b: boolean\n")
    13207     (write _test-input-stream "  write-to-stream a, b\n")
    13208     (write _test-input-stream "}\n")
    13209     # convert
    13210     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    13211     # registers except esp clobbered at this point
    13212     # restore ed
    13213     89/<- %edx 4/r32/esp
    13214     (flush _test-output-buffered-file)
    13215     (flush _test-error-buffered-file)
    13216 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    13222     # check output
    13223     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-wrong-index-type: output should be empty")
    13224     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt write-to-stream: target 'b' must be an addr"  "F - test-write-to-stream-with-wrong-index-type: error message")
    13225     # check that stop(1) was called
    13226     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-wrong-index-type: exit status")
    13227     # don't restore from ebp
    13228     81 0/subop/add %esp 8/imm32
    13229     # . epilogue
    13230     5d/pop-to-ebp
    13231     c3/return
    13232
    13233 test-write-to-stream-with-no-inouts:
    13234     # . prologue
    13235     55/push-ebp
    13236     89/<- %ebp 4/r32/esp
    13237     # setup
    13238     (clear-stream _test-input-stream)
    13239     (clear-stream $_test-input-buffered-file->buffer)
    13240     (clear-stream _test-output-stream)
    13241     (clear-stream $_test-output-buffered-file->buffer)
    13242     (clear-stream _test-error-stream)
    13243     (clear-stream $_test-error-buffered-file->buffer)
    13244     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    13245     68/push 0/imm32
    13246     68/push 0/imm32
    13247     89/<- %edx 4/r32/esp
    13248     (tailor-exit-descriptor %edx 0x10)
    13249     #
    13250     (write _test-input-stream "fn foo {\n")
    13251     (write _test-input-stream "  write-to-stream\n")
    13252     (write _test-input-stream "}\n")
    13253     # convert
    13254     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    13255     # registers except esp clobbered at this point
    13256     # restore ed
    13257     89/<- %edx 4/r32/esp
    13258     (flush _test-output-buffered-file)
    13259     (flush _test-error-buffered-file)
    13260 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    13266     # check output
    13267     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-no-inouts: output should be empty")
    13268     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt write-to-stream: too few inouts (2 required)"  "F - test-write-to-stream-with-no-inouts: error message")
    13269     # check that stop(1) was called
    13270     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-no-inouts: exit status")
    13271     # don't restore from ebp
    13272     81 0/subop/add %esp 8/imm32
    13273     # . epilogue
    13274     5d/pop-to-ebp
    13275     c3/return
    13276
    13277 test-write-to-stream-with-too-few-inouts:
    13278     # . prologue
    13279     55/push-ebp
    13280     89/<- %ebp 4/r32/esp
    13281     # setup
    13282     (clear-stream _test-input-stream)
    13283     (clear-stream $_test-input-buffered-file->buffer)
    13284     (clear-stream _test-output-stream)
    13285     (clear-stream $_test-output-buffered-file->buffer)
    13286     (clear-stream _test-error-stream)
    13287     (clear-stream $_test-error-buffered-file->buffer)
    13288     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    13289     68/push 0/imm32
    13290     68/push 0/imm32
    13291     89/<- %edx 4/r32/esp
    13292     (tailor-exit-descriptor %edx 0x10)
    13293     #
    13294     (write _test-input-stream "fn foo {\n")
    13295     (write _test-input-stream "  var a: (addr stream int)\n")
    13296     (write _test-input-stream "  write-to-stream a\n")
    13297     (write _test-input-stream "}\n")
    13298     # convert
    13299     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    13300     # registers except esp clobbered at this point
    13301     # restore ed
    13302     89/<- %edx 4/r32/esp
    13303     (flush _test-output-buffered-file)
    13304     (flush _test-error-buffered-file)
    13305 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    13311     # check output
    13312     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-too-few-inouts: output should be empty")
    13313     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt write-to-stream: too few inouts (2 required)"  "F - test-write-to-stream-with-too-few-inouts: error message")
    13314     # check that stop(1) was called
    13315     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-too-few-inouts: exit status")
    13316     # don't restore from ebp
    13317     81 0/subop/add %esp 8/imm32
    13318     # . epilogue
    13319     5d/pop-to-ebp
    13320     c3/return
    13321
    13322 test-write-to-stream-with-too-many-inouts:
    13323     # . prologue
    13324     55/push-ebp
    13325     89/<- %ebp 4/r32/esp
    13326     # setup
    13327     (clear-stream _test-input-stream)
    13328     (clear-stream $_test-input-buffered-file->buffer)
    13329     (clear-stream _test-output-stream)
    13330     (clear-stream $_test-output-buffered-file->buffer)
    13331     (clear-stream _test-error-stream)
    13332     (clear-stream $_test-error-buffered-file->buffer)
    13333     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    13334     68/push 0/imm32
    13335     68/push 0/imm32
    13336     89/<- %edx 4/r32/esp
    13337     (tailor-exit-descriptor %edx 0x10)
    13338     #
    13339     (write _test-input-stream "fn foo {\n")
    13340     (write _test-input-stream "  var a: (addr stream int)\n")
    13341     (write _test-input-stream "  var b: (addr int)\n")
    13342     (write _test-input-stream "  write-to-stream a, b, 0\n")
    13343     (write _test-input-stream "}\n")
    13344     # convert
    13345     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    13346     # registers except esp clobbered at this point
    13347     # restore ed
    13348     89/<- %edx 4/r32/esp
    13349     (flush _test-output-buffered-file)
    13350     (flush _test-error-buffered-file)
    13351 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    13357     # check output
    13358     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-too-many-inouts: output should be empty")
    13359     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt write-to-stream: too many inouts (2 required)"  "F - test-write-to-stream-with-too-many-inouts: error message")
    13360     # check that stop(1) was called
    13361     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-too-many-inouts: exit status")
    13362     # don't restore from ebp
    13363     81 0/subop/add %esp 8/imm32
    13364     # . epilogue
    13365     5d/pop-to-ebp
    13366     c3/return
    13367
    13368 test-write-to-stream-with-output:
    13369     # . prologue
    13370     55/push-ebp
    13371     89/<- %ebp 4/r32/esp
    13372     # setup
    13373     (clear-stream _test-input-stream)
    13374     (clear-stream $_test-input-buffered-file->buffer)
    13375     (clear-stream _test-output-stream)
    13376     (clear-stream $_test-output-buffered-file->buffer)
    13377     (clear-stream _test-error-stream)
    13378     (clear-stream $_test-error-buffered-file->buffer)
    13379     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    13380     68/push 0/imm32
    13381     68/push 0/imm32
    13382     89/<- %edx 4/r32/esp
    13383     (tailor-exit-descriptor %edx 0x10)
    13384     #
    13385     (write _test-input-stream "fn foo {\n")
    13386     (write _test-input-stream "  var a: (addr stream int)\n")
    13387     (write _test-input-stream "  var b/eax: (addr int) <- copy 0\n")
    13388     (write _test-input-stream "  b <- write-to-stream a, b\n")
    13389     (write _test-input-stream "}\n")
    13390     # convert
    13391     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    13392     # registers except esp clobbered at this point
    13393     # restore ed
    13394     89/<- %edx 4/r32/esp
    13395     (flush _test-output-buffered-file)
    13396     (flush _test-error-buffered-file)
    13397 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    13403     # check output
    13404     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-output: output should be empty")
    13405     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt write-to-stream: unexpected output"  "F - test-write-to-stream-with-output: error message")
    13406     # check that stop(1) was called
    13407     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-output: exit status")
    13408     # don't restore from ebp
    13409     81 0/subop/add %esp 8/imm32
    13410     # . epilogue
    13411     5d/pop-to-ebp
    13412     c3/return
    13413
    13414 test-length-with-non-array-atom-base-type:
    13415     # . prologue
    13416     55/push-ebp
    13417     89/<- %ebp 4/r32/esp
    13418     # setup
    13419     (clear-stream _test-input-stream)
    13420     (clear-stream $_test-input-buffered-file->buffer)
    13421     (clear-stream _test-output-stream)
    13422     (clear-stream $_test-output-buffered-file->buffer)
    13423     (clear-stream _test-error-stream)
    13424     (clear-stream $_test-error-buffered-file->buffer)
    13425     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    13426     68/push 0/imm32
    13427     68/push 0/imm32
    13428     89/<- %edx 4/r32/esp
    13429     (tailor-exit-descriptor %edx 0x10)
    13430     #
    13431     (write _test-input-stream "fn foo {\n")
    13432     (write _test-input-stream "  var a: int\n")
    13433     (write _test-input-stream "  var c/ecx: int <- length a\n")
    13434     (write _test-input-stream "}\n")
    13435     # convert
    13436     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    13437     # registers except esp clobbered at this point
    13438     # restore ed
    13439     89/<- %edx 4/r32/esp
    13440     (flush _test-output-buffered-file)
    13441     (flush _test-error-buffered-file)
    13442 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    13448     # check output
    13449     (check-stream-equal _test-output-stream  ""  "F - test-length-with-non-array-atom-base-type: output should be empty")
    13450     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt length: var 'a' is not an array"  "F - test-length-with-non-array-atom-base-type: error message")
    13451     # check that stop(1) was called
    13452     (check-ints-equal *(edx+4) 2 "F - test-length-with-non-array-atom-base-type: exit status")
    13453     # don't restore from ebp
    13454     81 0/subop/add %esp 8/imm32
    13455     # . epilogue
    13456     5d/pop-to-ebp
    13457     c3/return
    13458
    13459 test-length-with-non-array-compound-base-type:
    13460     # . prologue
    13461     55/push-ebp
    13462     89/<- %ebp 4/r32/esp
    13463     # setup
    13464     (clear-stream _test-input-stream)
    13465     (clear-stream $_test-input-buffered-file->buffer)
    13466     (clear-stream _test-output-stream)
    13467     (clear-stream $_test-output-buffered-file->buffer)
    13468     (clear-stream _test-error-stream)
    13469     (clear-stream $_test-error-buffered-file->buffer)
    13470     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    13471     68/push 0/imm32
    13472     68/push 0/imm32
    13473     89/<- %edx 4/r32/esp
    13474     (tailor-exit-descriptor %edx 0x10)
    13475     #
    13476     (write _test-input-stream "fn foo {\n")
    13477     (write _test-input-stream "  var a: (handle int)\n")
    13478     (write _test-input-stream "  var c/ecx: (addr int) <- length a, 0\n")
    13479     (write _test-input-stream "}\n")
    13480     # convert
    13481     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    13482     # registers except esp clobbered at this point
    13483     # restore ed
    13484     89/<- %edx 4/r32/esp
    13485     (flush _test-output-buffered-file)
    13486     (flush _test-error-buffered-file)
    13487 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    13493     # check output
    13494     (check-stream-equal _test-output-stream  ""  "F - test-length-with-non-array-compound-base-type: output should be empty")
    13495     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt length: var 'a' is not an array"  "F - test-length-with-non-array-compound-base-type: error message")
    13496     # check that stop(1) was called
    13497     (check-ints-equal *(edx+4) 2 "F - test-length-with-non-array-compound-base-type: exit status")
    13498     # don't restore from ebp
    13499     81 0/subop/add %esp 8/imm32
    13500     # . epilogue
    13501     5d/pop-to-ebp
    13502     c3/return
    13503
    13504 test-length-with-non-array-compound-base-type-2:
    13505     # . prologue
    13506     55/push-ebp
    13507     89/<- %ebp 4/r32/esp
    13508     # setup
    13509     (clear-stream _test-input-stream)
    13510     (clear-stream $_test-input-buffered-file->buffer)
    13511     (clear-stream _test-output-stream)
    13512     (clear-stream $_test-output-buffered-file->buffer)
    13513     (clear-stream _test-error-stream)
    13514     (clear-stream $_test-error-buffered-file->buffer)
    13515     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    13516     68/push 0/imm32
    13517     68/push 0/imm32
    13518     89/<- %edx 4/r32/esp
    13519     (tailor-exit-descriptor %edx 0x10)
    13520     #
    13521     (write _test-input-stream "fn foo {\n")
    13522     (write _test-input-stream "  var a: (addr int)\n")
    13523     (write _test-input-stream "  var c/ecx: (addr int) <- length a, 0\n")
    13524     (write _test-input-stream "}\n")
    13525     # convert
    13526     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    13527     # registers except esp clobbered at this point
    13528     # restore ed
    13529     89/<- %edx 4/r32/esp
    13530     (flush _test-output-buffered-file)
    13531     (flush _test-error-buffered-file)
    13532 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    13538     # check output
    13539     (check-stream-equal _test-output-stream  ""  "F - test-length-with-non-array-compound-base-type-2: output should be empty")
    13540     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt length: var 'a' is not an array"  "F - test-length-with-non-array-compound-base-type-2: error message")
    13541     # check that stop(1) was called
    13542     (check-ints-equal *(edx+4) 2 "F - test-length-with-non-array-compound-base-type-2: exit status")
    13543     # don't restore from ebp
    13544     81 0/subop/add %esp 8/imm32
    13545     # . epilogue
    13546     5d/pop-to-ebp
    13547     c3/return
    13548
    13549 test-length-with-array-atom-base-type:
    13550     # . prologue
    13551     55/push-ebp
    13552     89/<- %ebp 4/r32/esp
    13553     # setup
    13554     (clear-stream _test-input-stream)
    13555     (clear-stream $_test-input-buffered-file->buffer)
    13556     (clear-stream _test-output-stream)
    13557     (clear-stream $_test-output-buffered-file->buffer)
    13558     (clear-stream _test-error-stream)
    13559     (clear-stream $_test-error-buffered-file->buffer)
    13560     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    13561     68/push 0/imm32
    13562     68/push 0/imm32
    13563     89/<- %edx 4/r32/esp
    13564     (tailor-exit-descriptor %edx 0x10)
    13565     #
    13566     (write _test-input-stream "fn foo {\n")
    13567     (write _test-input-stream "  var a: array\n")
    13568     (write _test-input-stream "  var c/ecx: (addr int) <- length a\n")
    13569     (write _test-input-stream "}\n")
    13570     # convert
    13571     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    13572     # registers except esp clobbered at this point
    13573     # restore ed
    13574     89/<- %edx 4/r32/esp
    13575     (flush _test-output-buffered-file)
    13576     (flush _test-error-buffered-file)
    13577 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    13583     # check output
    13584     (check-stream-equal _test-output-stream  ""  "F - test-length-with-array-atom-base-type: output should be empty")
    13585     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt length: array 'a' must specify the type of its elements"  "F - test-length-with-array-atom-base-type: error message")
    13586     # check that stop(1) was called
    13587     (check-ints-equal *(edx+4) 2 "F - test-length-with-array-atom-base-type: exit status")
    13588     # don't restore from ebp
    13589     81 0/subop/add %esp 8/imm32
    13590     # . epilogue
    13591     5d/pop-to-ebp
    13592     c3/return
    13593
    13594 test-length-with-addr-base-on-stack:
    13595     # . prologue
    13596     55/push-ebp
    13597     89/<- %ebp 4/r32/esp
    13598     # setup
    13599     (clear-stream _test-input-stream)
    13600     (clear-stream $_test-input-buffered-file->buffer)
    13601     (clear-stream _test-output-stream)
    13602     (clear-stream $_test-output-buffered-file->buffer)
    13603     (clear-stream _test-error-stream)
    13604     (clear-stream $_test-error-buffered-file->buffer)
    13605     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    13606     68/push 0/imm32
    13607     68/push 0/imm32
    13608     89/<- %edx 4/r32/esp
    13609     (tailor-exit-descriptor %edx 0x10)
    13610     #
    13611     (write _test-input-stream "fn foo {\n")
    13612     (write _test-input-stream "  var a: (addr array int)\n")
    13613     (write _test-input-stream "  var c/ecx: (addr int) <- length a\n")
    13614     (write _test-input-stream "}\n")
    13615     # convert
    13616     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    13617     # registers except esp clobbered at this point
    13618     # restore ed
    13619     89/<- %edx 4/r32/esp
    13620     (flush _test-output-buffered-file)
    13621     (flush _test-error-buffered-file)
    13622 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    13628     # check output
    13629     (check-stream-equal _test-output-stream  ""  "F - test-length-with-addr-base-on-stack: output should be empty")
    13630     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt length: var 'a' is an addr to an array, and so must live in a register"  "F - test-length-with-addr-base-on-stack: error message")
    13631     # check that stop(1) was called
    13632     (check-ints-equal *(edx+4) 2 "F - test-length-with-addr-base-on-stack: exit status")
    13633     # don't restore from ebp
    13634     81 0/subop/add %esp 8/imm32
    13635     # . epilogue
    13636     5d/pop-to-ebp
    13637     c3/return
    13638
    13639 test-length-with-wrong-output-type:
    13640     # . prologue
    13641     55/push-ebp
    13642     89/<- %ebp 4/r32/esp
    13643     # setup
    13644     (clear-stream _test-input-stream)
    13645     (clear-stream $_test-input-buffered-file->buffer)
    13646     (clear-stream _test-output-stream)
    13647     (clear-stream $_test-output-buffered-file->buffer)
    13648     (clear-stream _test-error-stream)
    13649     (clear-stream $_test-error-buffered-file->buffer)
    13650     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    13651     68/push 0/imm32
    13652     68/push 0/imm32
    13653     89/<- %edx 4/r32/esp
    13654     (tailor-exit-descriptor %edx 0x10)
    13655     #
    13656     (write _test-input-stream "fn foo {\n")
    13657     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
    13658     (write _test-input-stream "  var o/edi: (addr int) <- length a\n")
    13659     (write _test-input-stream "}\n")
    13660     # convert
    13661     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    13662     # registers except esp clobbered at this point
    13663     # restore ed
    13664     89/<- %edx 4/r32/esp
    13665     (flush _test-output-buffered-file)
    13666     (flush _test-error-buffered-file)
    13667 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    13673     # check output
    13674     (check-stream-equal _test-output-stream  ""  "F - test-length-with-wrong-output-type: output should be empty")
    13675     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt length: output 'o' does not have the right type"  "F - test-length-with-wrong-output-type: error message")
    13676     # check that stop(1) was called
    13677     (check-ints-equal *(edx+4) 2 "F - test-length-with-wrong-output-type: exit status")
    13678     # don't restore from ebp
    13679     81 0/subop/add %esp 8/imm32
    13680     # . epilogue
    13681     5d/pop-to-ebp
    13682     c3/return
    13683
    13684 test-length-with-wrong-output-compound-type:
    13685     # . prologue
    13686     55/push-ebp
    13687     89/<- %ebp 4/r32/esp
    13688     # setup
    13689     (clear-stream _test-input-stream)
    13690     (clear-stream $_test-input-buffered-file->buffer)
    13691     (clear-stream _test-output-stream)
    13692     (clear-stream $_test-output-buffered-file->buffer)
    13693     (clear-stream _test-error-stream)
    13694     (clear-stream $_test-error-buffered-file->buffer)
    13695     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    13696     68/push 0/imm32
    13697     68/push 0/imm32
    13698     89/<- %edx 4/r32/esp
    13699     (tailor-exit-descriptor %edx 0x10)
    13700     #
    13701     (write _test-input-stream "fn foo {\n")
    13702     (write _test-input-stream "  var a/ebx: (addr array handle boolean) <- copy 0\n")
    13703     (write _test-input-stream "  var o/edi: (addr handle int) <- length a\n")
    13704     (write _test-input-stream "}\n")
    13705     # convert
    13706     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    13707     # registers except esp clobbered at this point
    13708     # restore ed
    13709     89/<- %edx 4/r32/esp
    13710     (flush _test-output-buffered-file)
    13711     (flush _test-error-buffered-file)
    13712 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    13718     # check output
    13719     (check-stream-equal _test-output-stream  ""  "F - test-length-with-wrong-output-compound-type: output should be empty")
    13720     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt length: output 'o' does not have the right type"  "F - test-length-with-wrong-output-compound-type: error message")
    13721     # check that stop(1) was called
    13722     (check-ints-equal *(edx+4) 2 "F - test-length-with-wrong-output-compound-type: exit status")
    13723     # don't restore from ebp
    13724     81 0/subop/add %esp 8/imm32
    13725     # . epilogue
    13726     5d/pop-to-ebp
    13727     c3/return
    13728
    13729 test-length-with-no-inouts:
    13730     # . prologue
    13731     55/push-ebp
    13732     89/<- %ebp 4/r32/esp
    13733     # setup
    13734     (clear-stream _test-input-stream)
    13735     (clear-stream $_test-input-buffered-file->buffer)
    13736     (clear-stream _test-output-stream)
    13737     (clear-stream $_test-output-buffered-file->buffer)
    13738     (clear-stream _test-error-stream)
    13739     (clear-stream $_test-error-buffered-file->buffer)
    13740     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    13741     68/push 0/imm32
    13742     68/push 0/imm32
    13743     89/<- %edx 4/r32/esp
    13744     (tailor-exit-descriptor %edx 0x10)
    13745     #
    13746     (write _test-input-stream "fn foo {\n")
    13747     (write _test-input-stream "  var c/ecx: int <- length\n")
    13748     (write _test-input-stream "}\n")
    13749     # convert
    13750     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    13751     # registers except esp clobbered at this point
    13752     # restore ed
    13753     89/<- %edx 4/r32/esp
    13754     (flush _test-output-buffered-file)
    13755     (flush _test-error-buffered-file)
    13756 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    13762     # check output
    13763     (check-stream-equal _test-output-stream  ""  "F - test-length-with-no-inouts: output should be empty")
    13764     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt length: too few inouts (1 required)"  "F - test-length-with-no-inouts: error message")
    13765     # check that stop(1) was called
    13766     (check-ints-equal *(edx+4) 2 "F - test-length-with-no-inouts: exit status")
    13767     # don't restore from ebp
    13768     81 0/subop/add %esp 8/imm32
    13769     # . epilogue
    13770     5d/pop-to-ebp
    13771     c3/return
    13772
    13773 test-length-with-too-many-inouts:
    13774     # . prologue
    13775     55/push-ebp
    13776     89/<- %ebp 4/r32/esp
    13777     # setup
    13778     (clear-stream _test-input-stream)
    13779     (clear-stream $_test-input-buffered-file->buffer)
    13780     (clear-stream _test-output-stream)
    13781     (clear-stream $_test-output-buffered-file->buffer)
    13782     (clear-stream _test-error-stream)
    13783     (clear-stream $_test-error-buffered-file->buffer)
    13784     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    13785     68/push 0/imm32
    13786     68/push 0/imm32
    13787     89/<- %edx 4/r32/esp
    13788     (tailor-exit-descriptor %edx 0x10)
    13789     #
    13790     (write _test-input-stream "fn foo {\n")
    13791     (write _test-input-stream "  var a: (array int 3)\n")
    13792     (write _test-input-stream "  var c/ecx: int <- length a, 0, 0\n")
    13793     (write _test-input-stream "}\n")
    13794     # convert
    13795     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    13796     # registers except esp clobbered at this point
    13797     # restore ed
    13798     89/<- %edx 4/r32/esp
    13799     (flush _test-output-buffered-file)
    13800     (flush _test-error-buffered-file)
    13801 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    13807     # check output
    13808     (check-stream-equal _test-output-stream  ""  "F - test-length-with-too-many-inouts: output should be empty")
    13809     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt length: too many inouts (1 required)"  "F - test-length-with-too-many-inouts: error message")
    13810     # check that stop(1) was called
    13811     (check-ints-equal *(edx+4) 2 "F - test-length-with-too-many-inouts: exit status")
    13812     # don't restore from ebp
    13813     81 0/subop/add %esp 8/imm32
    13814     # . epilogue
    13815     5d/pop-to-ebp
    13816     c3/return
    13817
    13818 test-length-with-no-output:
    13819     # . prologue
    13820     55/push-ebp
    13821     89/<- %ebp 4/r32/esp
    13822     # setup
    13823     (clear-stream _test-input-stream)
    13824     (clear-stream $_test-input-buffered-file->buffer)
    13825     (clear-stream _test-output-stream)
    13826     (clear-stream $_test-output-buffered-file->buffer)
    13827     (clear-stream _test-error-stream)
    13828     (clear-stream $_test-error-buffered-file->buffer)
    13829     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    13830     68/push 0/imm32
    13831     68/push 0/imm32
    13832     89/<- %edx 4/r32/esp
    13833     (tailor-exit-descriptor %edx 0x10)
    13834     #
    13835     (write _test-input-stream "fn foo {\n")
    13836     (write _test-input-stream "  var a: (array int 3)\n")
    13837     (write _test-input-stream "  length a\n")
    13838     (write _test-input-stream "}\n")
    13839     # convert
    13840     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    13841     # registers except esp clobbered at this point
    13842     # restore ed
    13843     89/<- %edx 4/r32/esp
    13844     (flush _test-output-buffered-file)
    13845     (flush _test-error-buffered-file)
    13846 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    13852     # check output
    13853     (check-stream-equal _test-output-stream  ""  "F - test-length-with-no-output: output should be empty")
    13854     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt length: must have an output"  "F - test-length-with-no-output: error message")
    13855     # check that stop(1) was called
    13856     (check-ints-equal *(edx+4) 2 "F - test-length-with-no-output: exit status")
    13857     # don't restore from ebp
    13858     81 0/subop/add %esp 8/imm32
    13859     # . epilogue
    13860     5d/pop-to-ebp
    13861     c3/return
    13862
    13863 test-length-with-too-many-outputs:
    13864     # . prologue
    13865     55/push-ebp
    13866     89/<- %ebp 4/r32/esp
    13867     # setup
    13868     (clear-stream _test-input-stream)
    13869     (clear-stream $_test-input-buffered-file->buffer)
    13870     (clear-stream _test-output-stream)
    13871     (clear-stream $_test-output-buffered-file->buffer)
    13872     (clear-stream _test-error-stream)
    13873     (clear-stream $_test-error-buffered-file->buffer)
    13874     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    13875     68/push 0/imm32
    13876     68/push 0/imm32
    13877     89/<- %edx 4/r32/esp
    13878     (tailor-exit-descriptor %edx 0x10)
    13879     #
    13880     (write _test-input-stream "fn foo {\n")
    13881     (write _test-input-stream "  var a: (array int 3)\n")
    13882     (write _test-input-stream "  var b/eax: int <- copy 0\n")
    13883     (write _test-input-stream "  var c/ecx: int <- copy 0\n")
    13884     (write _test-input-stream "  b, c <- length a\n")
    13885     (write _test-input-stream "}\n")
    13886     # convert
    13887     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    13888     # registers except esp clobbered at this point
    13889     # restore ed
    13890     89/<- %edx 4/r32/esp
    13891     (flush _test-output-buffered-file)
    13892     (flush _test-error-buffered-file)
    13893 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    13899     # check output
    13900     (check-stream-equal _test-output-stream  ""  "F - test-length-with-too-many-outputs: output should be empty")
    13901     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt length: too many outputs (1 required)"  "F - test-length-with-too-many-outputs: error message")
    13902     # check that stop(1) was called
    13903     (check-ints-equal *(edx+4) 2 "F - test-length-with-too-many-outputs: exit status")
    13904     # don't restore from ebp
    13905     81 0/subop/add %esp 8/imm32
    13906     # . epilogue
    13907     5d/pop-to-ebp
    13908     c3/return
    13909
    13910 test-convert-function-with-return-register-and-local:
    13911     # . prologue
    13912     55/push-ebp
    13913     89/<- %ebp 4/r32/esp
    13914     # setup
    13915     (clear-stream _test-input-stream)
    13916     (clear-stream $_test-input-buffered-file->buffer)
    13917     (clear-stream _test-output-stream)
    13918     (clear-stream $_test-output-buffered-file->buffer)
    13919     #
    13920     (write _test-input-stream "fn foo -> _/eax: int {\n")
    13921     (write _test-input-stream "  var y/eax: int <- copy 3\n")
    13922     (write _test-input-stream "  var z/ecx: int <- copy 4\n")
    13923     (write _test-input-stream "  return y\n")
    13924     (write _test-input-stream "}\n")
    13925     # convert
    13926     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
    13927     (flush _test-output-buffered-file)
    13928 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
    13934     # check output
    13935     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return-register-and-local/0")
    13936     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return-register-and-local/1")
    13937     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return-register-and-local/2")
    13938     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return-register-and-local/3")
    13939     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return-register-and-local/4")
    13940     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return-register-and-local/5")
    13941     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-with-return-register-and-local/6")
    13942     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 3/imm32"  "F - test-convert-function-with-return-register-and-local/7")
    13943     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-return-register-and-local/8")
    13944     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 4/imm32"  "F - test-convert-function-with-return-register-and-local/9")
    13945     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000000/r32" "F - test-convert-function-with-return-register-and-local/10")
    13946     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"         "F - test-convert-function-with-return-register-and-local/11")
    13947     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-function-with-return-register-and-local/12")
    13948     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-return-register-and-local/13")
    13949     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return-register-and-local/14")
    13950     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return-register-and-local/15")
    13951     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return-register-and-local/16")
    13952     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return-register-and-local/17")
    13953     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return-register-and-local/18")
    13954     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return-register-and-local/19")
    13955     # . epilogue
    13956     89/<- %esp 5/r32/ebp
    13957     5d/pop-to-ebp
    13958     c3/return
    13959
    13960 test-convert-function-with-return-register-and-local-2:
    13961     # . prologue
    13962     55/push-ebp
    13963     89/<- %ebp 4/r32/esp
    13964     # setup
    13965     (clear-stream _test-input-stream)
    13966     (clear-stream $_test-input-buffered-file->buffer)
    13967     (clear-stream _test-output-stream)
    13968     (clear-stream $_test-output-buffered-file->buffer)
    13969     #
    13970     (write _test-input-stream "fn foo -> _/eax: int {\n")
    13971     (write _test-input-stream "  var y/eax: int <- copy 3\n")
    13972     (write _test-input-stream "  var z/ecx: int <- copy 4\n")
    13973     (write _test-input-stream "  return z\n")
    13974     (write _test-input-stream "}\n")
    13975     # convert
    13976     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
    13977     (flush _test-output-buffered-file)
    13978 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
    13984     # check output
    13985     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return-register-and-local-2/0")
    13986     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return-register-and-local-2/1")
    13987     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return-register-and-local-2/2")
    13988     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return-register-and-local-2/3")
    13989     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return-register-and-local-2/4")
    13990     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return-register-and-local-2/5")
    13991     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-with-return-register-and-local-2/6")
    13992     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 3/imm32"  "F - test-convert-function-with-return-register-and-local-2/7")
    13993     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-return-register-and-local-2/8")
    13994     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 4/imm32"  "F - test-convert-function-with-return-register-and-local-2/9")
    13995     (check-next-stream-line-equal _test-output-stream "    8b/-> %ecx 0x00000000/r32" "F - test-convert-function-with-return-register-and-local-2/10")
    13996     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"         "F - test-convert-function-with-return-register-and-local-2/11")
    13997     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-function-with-return-register-and-local-2/12")
    13998     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-return-register-and-local-2/13")
    13999     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return-register-and-local-2/14")
    14000     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return-register-and-local-2/15")
    14001     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return-register-and-local-2/16")
    14002     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return-register-and-local-2/17")
    14003     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return-register-and-local-2/18")
    14004     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return-register-and-local-2/19")
    14005     # . epilogue
    14006     89/<- %esp 5/r32/ebp
    14007     5d/pop-to-ebp
    14008     c3/return
    14009
    14010 test-convert-function-with-return-float-register-and-local:
    14011     # . prologue
    14012     55/push-ebp
    14013     89/<- %ebp 4/r32/esp
    14014     # setup
    14015     (clear-stream _test-input-stream)
    14016     (clear-stream $_test-input-buffered-file->buffer)
    14017     (clear-stream _test-output-stream)
    14018     (clear-stream $_test-output-buffered-file->buffer)
    14019     #
    14020     (write _test-input-stream "fn foo -> _/xmm1: float {\n")
    14021     (write _test-input-stream "  var y/eax: int <- copy 3\n")
    14022     (write _test-input-stream "  var g/xmm0: float <- convert y\n")
    14023     (write _test-input-stream "  var h/xmm1: float <- convert y\n")
    14024     (write _test-input-stream "  return g\n")
    14025     (write _test-input-stream "}\n")
    14026     # convert
    14027     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
    14028     (flush _test-output-buffered-file)
    14029 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
    14035     # check output
    14036     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return-float-register-and-local/0")
    14037     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return-float-register-and-local/1")
    14038     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return-float-register-and-local/2")
    14039     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return-float-register-and-local/3")
    14040     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return-float-register-and-local/4")
    14041     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return-float-register-and-local/5")
    14042     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-with-return-float-register-and-local/6")  # var y
    14043     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 3/imm32"  "F - test-convert-function-with-return-float-register-and-local/7")
    14044     (check-next-stream-line-equal _test-output-stream "    81 5/subop/subtract %esp 4/imm32"  "F - test-convert-function-with-return-float-register-and-local/8")  # var g
    14045     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/<- *esp 0/x32"  "F - test-convert-function-with-return-float-register-and-local/9")
    14046     (check-next-stream-line-equal _test-output-stream "    f3 0f 2a/convert-to-float %eax 0x00000000/x32"  "F - test-convert-function-with-return-float-register-and-local/10")
    14047     (check-next-stream-line-equal _test-output-stream "    81 5/subop/subtract %esp 4/imm32"  "F - test-convert-function-with-return-float-register-and-local/11")  # var h
    14048     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/<- *esp 1/x32"  "F - test-convert-function-with-return-float-register-and-local/12")
    14049     (check-next-stream-line-equal _test-output-stream "    f3 0f 2a/convert-to-float %eax 0x00000001/x32"  "F - test-convert-function-with-return-float-register-and-local/13")
    14050     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/-> %xmm0 0x00000001/x32"  "F - test-convert-function-with-return-float-register-and-local/14")  # return g
    14051     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-floating-point-dereferenced/15")  # reclaim h
    14052     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/-> *esp 0/x32"  "F - test-convert-floating-point-dereferenced/16")  # reclaim g
    14053     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-floating-point-dereferenced/17")
    14054     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"         "F - test-convert-function-with-return-float-register-and-local/18")  # reclaim y
    14055     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-return-float-register-and-local/19")
    14056     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return-float-register-and-local/20")
    14057     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return-float-register-and-local/21")
    14058     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return-float-register-and-local/22")
    14059     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return-float-register-and-local/23")
    14060     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return-float-register-and-local/24")
    14061     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return-float-register-and-local/25")
    14062     # . epilogue
    14063     89/<- %esp 5/r32/ebp
    14064     5d/pop-to-ebp
    14065     c3/return
    14066
    14067 test-convert-function-with-return-and-local-vars:
    14068     # . prologue
    14069     55/push-ebp
    14070     89/<- %ebp 4/r32/esp
    14071     # setup
    14072     (clear-stream _test-input-stream)
    14073     (clear-stream $_test-input-buffered-file->buffer)
    14074     (clear-stream _test-output-stream)
    14075     (clear-stream $_test-output-buffered-file->buffer)
    14076     #
    14077     (write _test-input-stream "fn foo -> _/eax: int {\n")
    14078     (write _test-input-stream "  {\n")
    14079     (write _test-input-stream "    var x: int\n")
    14080     (write _test-input-stream "    {\n")
    14081     (write _test-input-stream "      var y: int\n")
    14082     (write _test-input-stream "      return y\n")
    14083     (write _test-input-stream "      increment x\n")
    14084     (write _test-input-stream "    }\n")
    14085     (write _test-input-stream "  }\n")
    14086     (write _test-input-stream "  return 0\n")
    14087     (write _test-input-stream "}\n")
    14088     # convert
    14089     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
    14090     (flush _test-output-buffered-file)
    14091 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
    14097     # check output
    14098     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return-and-local-vars/0")
    14099     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return-and-local-vars/1")
    14100     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return-and-local-vars/2")
    14101     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return-and-local-vars/3")
    14102     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return-and-local-vars/4")
    14103     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return-and-local-vars/5")
    14104     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-return-and-local-vars/6")
    14105     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-return-and-local-vars/7")
    14106     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-return-and-local-vars/8")  # var x
    14107     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-return-and-local-vars/9")
    14108     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-return-and-local-vars/10")
    14109     (check-next-stream-line-equal _test-output-stream "        68/push 0/imm32" "F - test-convert-function-with-return-and-local-vars/11")  # var y
    14110     (check-next-stream-line-equal _test-output-stream "        8b/-> *(ebp+0xfffffff8) 0x00000000/r32" "F - test-convert-function-with-return-and-local-vars/12")
    14111     (check-next-stream-line-equal _test-output-stream "        81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-return-and-local-vars/13")
    14112     (check-next-stream-line-equal _test-output-stream "        81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-return-and-local-vars/14")
    14113     (check-next-stream-line-equal _test-output-stream "        e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-return-and-local-vars/15")
    14114     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-return-and-local-vars/16")
    14115     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-return-and-local-vars/17")
    14116     (check-next-stream-line-equal _test-output-stream "      81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-function-with-return-and-local-vars/18")
    14117     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-return-and-local-vars/19")
    14118     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-return-and-local-vars/20")
    14119     (check-next-stream-line-equal _test-output-stream "    c7 0/subop/copy %eax 0/imm32"  "F - test-convert-function-with-return-and-local-vars/21")
    14120     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-return-and-local-vars/21")
    14121     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return-and-local-vars/21")
    14122     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return-and-local-vars/22")
    14123     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return-and-local-vars/23")
    14124     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return-and-local-vars/24")
    14125     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return-and-local-vars/25")
    14126     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return-and-local-vars/26")
    14127     # . epilogue
    14128     89/<- %esp 5/r32/ebp
    14129     5d/pop-to-ebp
    14130     c3/return
    14131
    14132 test-copy-object-with-no-inout:
    14133     # . prologue
    14134     55/push-ebp
    14135     89/<- %ebp 4/r32/esp
    14136     # setup
    14137     (clear-stream _test-input-stream)
    14138     (clear-stream $_test-input-buffered-file->buffer)
    14139     (clear-stream _test-output-stream)
    14140     (clear-stream $_test-output-buffered-file->buffer)
    14141     (clear-stream _test-error-stream)
    14142     (clear-stream $_test-error-buffered-file->buffer)
    14143     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    14144     68/push 0/imm32
    14145     68/push 0/imm32
    14146     89/<- %edx 4/r32/esp
    14147     (tailor-exit-descriptor %edx 0x10)
    14148     #
    14149     (write _test-input-stream "fn foo {\n")
    14150     (write _test-input-stream "  copy-object\n")
    14151     (write _test-input-stream "}\n")
    14152     # convert
    14153     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    14154     # registers except esp clobbered at this point
    14155     # restore ed
    14156     89/<- %edx 4/r32/esp
    14157     (flush _test-output-buffered-file)
    14158     (flush _test-error-buffered-file)
    14159 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    14165     # check output
    14166     (check-stream-equal _test-output-stream  ""  "F - test-copy-object-with-no-inout: output should be empty")
    14167     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy-object' must have two inouts"  "F - test-copy-object-with-no-inout: error message")
    14168     # check that stop(1) was called
    14169     (check-ints-equal *(edx+4) 2 "F - test-copy-object-with-no-inout: exit status")
    14170     # don't restore from ebp
    14171     81 0/subop/add %esp 8/imm32
    14172     # . epilogue
    14173     5d/pop-to-ebp
    14174     c3/return
    14175
    14176 test-copy-object-with-no-source:
    14177     # . prologue
    14178     55/push-ebp
    14179     89/<- %ebp 4/r32/esp
    14180     # setup
    14181     (clear-stream _test-input-stream)
    14182     (clear-stream $_test-input-buffered-file->buffer)
    14183     (clear-stream _test-output-stream)
    14184     (clear-stream $_test-output-buffered-file->buffer)
    14185     (clear-stream _test-error-stream)
    14186     (clear-stream $_test-error-buffered-file->buffer)
    14187     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    14188     68/push 0/imm32
    14189     68/push 0/imm32
    14190     89/<- %edx 4/r32/esp
    14191     (tailor-exit-descriptor %edx 0x10)
    14192     #
    14193     (write _test-input-stream "fn foo {\n")
    14194     (write _test-input-stream "  var x: (addr int)\n")
    14195     (write _test-input-stream "  copy-object x\n")
    14196     (write _test-input-stream "}\n")
    14197     # convert
    14198     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    14199     # registers except esp clobbered at this point
    14200     # restore ed
    14201     89/<- %edx 4/r32/esp
    14202     (flush _test-output-buffered-file)
    14203     (flush _test-error-buffered-file)
    14204 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    14210     # check output
    14211     (check-stream-equal _test-output-stream  ""  "F - test-copy-object-with-no-source: output should be empty")
    14212     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy-object' must have two inouts"  "F - test-copy-object-with-no-source: error message")
    14213     # check that stop(1) was called
    14214     (check-ints-equal *(edx+4) 2 "F - test-copy-object-with-no-source: exit status")
    14215     # don't restore from ebp
    14216     81 0/subop/add %esp 8/imm32
    14217     # . epilogue
    14218     5d/pop-to-ebp
    14219     c3/return
    14220
    14221 test-copy-object-with-too-many-inouts:
    14222     # . prologue
    14223     55/push-ebp
    14224     89/<- %ebp 4/r32/esp
    14225     # setup
    14226     (clear-stream _test-input-stream)
    14227     (clear-stream $_test-input-buffered-file->buffer)
    14228     (clear-stream _test-output-stream)
    14229     (clear-stream $_test-output-buffered-file->buffer)
    14230     (clear-stream _test-error-stream)
    14231     (clear-stream $_test-error-buffered-file->buffer)
    14232     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    14233     68/push 0/imm32
    14234     68/push 0/imm32
    14235     89/<- %edx 4/r32/esp
    14236     (tailor-exit-descriptor %edx 0x10)
    14237     #
    14238     (write _test-input-stream "fn foo {\n")
    14239     (write _test-input-stream "  var x: (addr boolean)\n")
    14240     (write _test-input-stream "  copy-object x, x, x\n")
    14241     (write _test-input-stream "}\n")
    14242     # convert
    14243     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    14244     # registers except esp clobbered at this point
    14245     # restore ed
    14246     89/<- %edx 4/r32/esp
    14247     (flush _test-output-buffered-file)
    14248     (flush _test-error-buffered-file)
    14249 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    14255     # check output
    14256     (check-stream-equal _test-output-stream  ""  "F - test-copy-object-with-too-many-inouts: output should be empty")
    14257     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy-object' must have two inouts"  "F - test-copy-object-with-too-many-inouts: error message")
    14258     # check that stop(1) was called
    14259     (check-ints-equal *(edx+4) 2 "F - test-copy-object-with-too-many-inouts: exit status")
    14260     # don't restore from ebp
    14261     81 0/subop/add %esp 8/imm32
    14262     # . epilogue
    14263     5d/pop-to-ebp
    14264     c3/return
    14265
    14266 test-copy-object-with-output:
    14267     # . prologue
    14268     55/push-ebp
    14269     89/<- %ebp 4/r32/esp
    14270     # setup
    14271     (clear-stream _test-input-stream)
    14272     (clear-stream $_test-input-buffered-file->buffer)
    14273     (clear-stream _test-output-stream)
    14274     (clear-stream $_test-output-buffered-file->buffer)
    14275     (clear-stream _test-error-stream)
    14276     (clear-stream $_test-error-buffered-file->buffer)
    14277     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    14278     68/push 0/imm32
    14279     68/push 0/imm32
    14280     89/<- %edx 4/r32/esp
    14281     (tailor-exit-descriptor %edx 0x10)
    14282     #
    14283     (write _test-input-stream "fn foo {\n")
    14284     (write _test-input-stream "  var x/eax: (addr boolean) <- copy 0\n")
    14285     (write _test-input-stream "  var y/ecx: (addr boolean) <- copy 0\n")
    14286     (write _test-input-stream "  x <- copy-object x, y\n")
    14287     (write _test-input-stream "}\n")
    14288     # convert
    14289     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    14290     # registers except esp clobbered at this point
    14291     # restore ed
    14292     89/<- %edx 4/r32/esp
    14293     (flush _test-output-buffered-file)
    14294     (flush _test-error-buffered-file)
    14295 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    14301     # check output
    14302     (check-stream-equal _test-output-stream  ""  "F - test-copy-object-with-output: output should be empty")
    14303     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy-object' must not have any outputs"  "F - test-copy-object-with-output: error message")
    14304     # check that stop(1) was called
    14305     (check-ints-equal *(edx+4) 2 "F - test-copy-object-with-output: exit status")
    14306     # don't restore from ebp
    14307     81 0/subop/add %esp 8/imm32
    14308     # . epilogue
    14309     5d/pop-to-ebp
    14310     c3/return
    14311
    14312 test-copy-object-deref-address:
    14313     # . prologue
    14314     55/push-ebp
    14315     89/<- %ebp 4/r32/esp
    14316     # setup
    14317     (clear-stream _test-input-stream)
    14318     (clear-stream $_test-input-buffered-file->buffer)
    14319     (clear-stream _test-output-stream)
    14320     (clear-stream $_test-output-buffered-file->buffer)
    14321     #
    14322     (write _test-input-stream "fn foo {\n")
    14323     (write _test-input-stream "  var x/eax: (addr int) <- copy 0\n")
    14324     (write _test-input-stream "  var y/ecx: (addr addr int) <- copy 0\n")
    14325     (write _test-input-stream "  copy-object *y, x\n")
    14326     (write _test-input-stream "}\n")
    14327     # convert
    14328     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
    14329     (flush _test-output-buffered-file)
    14330     # no errors
    14331     # . epilogue
    14332     5d/pop-to-ebp
    14333     c3/return
    14334
    14335 test-copy-object-non-addr:
    14336     # . prologue
    14337     55/push-ebp
    14338     89/<- %ebp 4/r32/esp
    14339     # setup
    14340     (clear-stream _test-input-stream)
    14341     (clear-stream $_test-input-buffered-file->buffer)
    14342     (clear-stream _test-output-stream)
    14343     (clear-stream $_test-output-buffered-file->buffer)
    14344     (clear-stream _test-error-stream)
    14345     (clear-stream $_test-error-buffered-file->buffer)
    14346     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    14347     68/push 0/imm32
    14348     68/push 0/imm32
    14349     89/<- %edx 4/r32/esp
    14350     (tailor-exit-descriptor %edx 0x10)
    14351     #
    14352     (write _test-input-stream "fn foo {\n")
    14353     (write _test-input-stream "  var x: int\n")
    14354     (write _test-input-stream "  var y: int\n")
    14355     (write _test-input-stream "  copy-object y, x\n")
    14356     (write _test-input-stream "}\n")
    14357     # convert
    14358     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    14359     # registers except esp clobbered at this point
    14360     # restore ed
    14361     89/<- %edx 4/r32/esp
    14362     (flush _test-output-buffered-file)
    14363     (flush _test-error-buffered-file)
    14364 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    14370     # check output
    14371     (check-stream-equal _test-output-stream  ""  "F - test-copy-object-non-addr: output should be empty")
    14372     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt copy-object: two inouts with identical addr types expected"  "F - test-copy-object-non-addr: error message")
    14373     # check that stop(1) was called
    14374     (check-ints-equal *(edx+4) 2 "F - test-copy-object-non-addr: exit status")
    14375     # don't restore from ebp
    14376     81 0/subop/add %esp 8/imm32
    14377     # . epilogue
    14378     5d/pop-to-ebp
    14379     c3/return
    14380
    14381 test-copy-object-non-equal:
    14382     # . prologue
    14383     55/push-ebp
    14384     89/<- %ebp 4/r32/esp
    14385     # setup
    14386     (clear-stream _test-input-stream)
    14387     (clear-stream $_test-input-buffered-file->buffer)
    14388     (clear-stream _test-output-stream)
    14389     (clear-stream $_test-output-buffered-file->buffer)
    14390     (clear-stream _test-error-stream)
    14391     (clear-stream $_test-error-buffered-file->buffer)
    14392     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    14393     68/push 0/imm32
    14394     68/push 0/imm32
    14395     89/<- %edx 4/r32/esp
    14396     (tailor-exit-descriptor %edx 0x10)
    14397     #
    14398     (write _test-input-stream "fn foo {\n")
    14399     (write _test-input-stream "  var x: (addr int)\n")
    14400     (write _test-input-stream "  var y: (addr boolean)\n")
    14401     (write _test-input-stream "  copy-object y, x\n")
    14402     (write _test-input-stream "}\n")
    14403     # convert
    14404     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    14405     # registers except esp clobbered at this point
    14406     # restore ed
    14407     89/<- %edx 4/r32/esp
    14408     (flush _test-output-buffered-file)
    14409     (flush _test-error-buffered-file)
    14410 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    14416     # check output
    14417     (check-stream-equal _test-output-stream  ""  "F - test-copy-object-non-equal: output should be empty")
    14418     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt copy-object: two inouts with identical addr types expected"  "F - test-copy-object-non-equal: error message")
    14419     # check that stop(1) was called
    14420     (check-ints-equal *(edx+4) 2 "F - test-copy-object-non-equal: exit status")
    14421     # don't restore from ebp
    14422     81 0/subop/add %esp 8/imm32
    14423     # . epilogue
    14424     5d/pop-to-ebp
    14425     c3/return
    14426
    14427 test-allocate-with-no-inout:
    14428     # . prologue
    14429     55/push-ebp
    14430     89/<- %ebp 4/r32/esp
    14431     # setup
    14432     (clear-stream _test-input-stream)
    14433     (clear-stream $_test-input-buffered-file->buffer)
    14434     (clear-stream _test-output-stream)
    14435     (clear-stream $_test-output-buffered-file->buffer)
    14436     (clear-stream _test-error-stream)
    14437     (clear-stream $_test-error-buffered-file->buffer)
    14438     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    14439     68/push 0/imm32
    14440     68/push 0/imm32
    14441     89/<- %edx 4/r32/esp
    14442     (tailor-exit-descriptor %edx 0x10)
    14443     #
    14444     (write _test-input-stream "fn foo {\n")
    14445     (write _test-input-stream "  allocate\n")
    14446     (write _test-input-stream "}\n")
    14447     # convert
    14448     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    14449     # registers except esp clobbered at this point
    14450     # restore ed
    14451     89/<- %edx 4/r32/esp
    14452     (flush _test-output-buffered-file)
    14453     (flush _test-error-buffered-file)
    14454 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    14460     # check output
    14461     (check-stream-equal _test-output-stream  ""  "F - test-allocate-with-no-inout: output should be empty")
    14462     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'allocate' must have a single inout"  "F - test-allocate-with-no-inout: error message")
    14463     # check that stop(1) was called
    14464     (check-ints-equal *(edx+4) 2 "F - test-allocate-with-no-inout: exit status")
    14465     # don't restore from ebp
    14466     81 0/subop/add %esp 8/imm32
    14467     # . epilogue
    14468     5d/pop-to-ebp
    14469     c3/return
    14470
    14471 test-allocate-with-too-many-inouts:
    14472     # . prologue
    14473     55/push-ebp
    14474     89/<- %ebp 4/r32/esp
    14475     # setup
    14476     (clear-stream _test-input-stream)
    14477     (clear-stream $_test-input-buffered-file->buffer)
    14478     (clear-stream _test-output-stream)
    14479     (clear-stream $_test-output-buffered-file->buffer)
    14480     (clear-stream _test-error-stream)
    14481     (clear-stream $_test-error-buffered-file->buffer)
    14482     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    14483     68/push 0/imm32
    14484     68/push 0/imm32
    14485     89/<- %edx 4/r32/esp
    14486     (tailor-exit-descriptor %edx 0x10)
    14487     #
    14488     (write _test-input-stream "fn foo {\n")
    14489     (write _test-input-stream "  var x: (addr handle int)\n")
    14490     (write _test-input-stream "  allocate x, 0\n")
    14491     (write _test-input-stream "}\n")
    14492     # convert
    14493     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    14494     # registers except esp clobbered at this point
    14495     # restore ed
    14496     89/<- %edx 4/r32/esp
    14497     (flush _test-output-buffered-file)
    14498     (flush _test-error-buffered-file)
    14499 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    14505     # check output
    14506     (check-stream-equal _test-output-stream  ""  "F - test-allocate-with-too-many-inouts: output should be empty")
    14507     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'allocate' must have a single inout"  "F - test-allocate-with-too-many-inouts: error message")
    14508     # check that stop(1) was called
    14509     (check-ints-equal *(edx+4) 2 "F - test-allocate-with-too-many-inouts: exit status")
    14510     # don't restore from ebp
    14511     81 0/subop/add %esp 8/imm32
    14512     # . epilogue
    14513     5d/pop-to-ebp
    14514     c3/return
    14515
    14516 test-allocate-with-output:
    14517     # . prologue
    14518     55/push-ebp
    14519     89/<- %ebp 4/r32/esp
    14520     # setup
    14521     (clear-stream _test-input-stream)
    14522     (clear-stream $_test-input-buffered-file->buffer)
    14523     (clear-stream _test-output-stream)
    14524     (clear-stream $_test-output-buffered-file->buffer)
    14525     (clear-stream _test-error-stream)
    14526     (clear-stream $_test-error-buffered-file->buffer)
    14527     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    14528     68/push 0/imm32
    14529     68/push 0/imm32
    14530     89/<- %edx 4/r32/esp
    14531     (tailor-exit-descriptor %edx 0x10)
    14532     #
    14533     (write _test-input-stream "fn foo {\n")
    14534     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
    14535     (write _test-input-stream "  var y/ecx: (addr handle int) <- copy 0\n")
    14536     (write _test-input-stream "  x <- allocate y\n")
    14537     (write _test-input-stream "}\n")
    14538     # convert
    14539     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    14540     # registers except esp clobbered at this point
    14541     # restore ed
    14542     89/<- %edx 4/r32/esp
    14543     (flush _test-output-buffered-file)
    14544     (flush _test-error-buffered-file)
    14545 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    14551     # check output
    14552     (check-stream-equal _test-output-stream  ""  "F - test-allocate-with-output: output should be empty")
    14553     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'allocate' must not have any outputs"  "F - test-allocate-with-output: error message")
    14554     # check that stop(1) was called
    14555     (check-ints-equal *(edx+4) 2 "F - test-allocate-with-output: exit status")
    14556     # don't restore from ebp
    14557     81 0/subop/add %esp 8/imm32
    14558     # . epilogue
    14559     5d/pop-to-ebp
    14560     c3/return
    14561
    14562 test-allocate-non-addr:
    14563     # . prologue
    14564     55/push-ebp
    14565     89/<- %ebp 4/r32/esp
    14566     # setup
    14567     (clear-stream _test-input-stream)
    14568     (clear-stream $_test-input-buffered-file->buffer)
    14569     (clear-stream _test-output-stream)
    14570     (clear-stream $_test-output-buffered-file->buffer)
    14571     (clear-stream _test-error-stream)
    14572     (clear-stream $_test-error-buffered-file->buffer)
    14573     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    14574     68/push 0/imm32
    14575     68/push 0/imm32
    14576     89/<- %edx 4/r32/esp
    14577     (tailor-exit-descriptor %edx 0x10)
    14578     #
    14579     (write _test-input-stream "fn foo {\n")
    14580     (write _test-input-stream "  var y: (handle int)\n")
    14581     (write _test-input-stream "  allocate y\n")
    14582     (write _test-input-stream "}\n")
    14583     # convert
    14584     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    14585     # registers except esp clobbered at this point
    14586     # restore ed
    14587     89/<- %edx 4/r32/esp
    14588     (flush _test-output-buffered-file)
    14589     (flush _test-error-buffered-file)
    14590 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    14596     # check output
    14597     (check-stream-equal _test-output-stream  ""  "F - test-allocate-non-addr: output must be empty")
    14598     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt allocate: inout 'y' must have type (addr handle ...)"  "F - test-allocate-non-addr: error message")
    14599     # check that stop(1) was called
    14600     (check-ints-equal *(edx+4) 2 "F - test-allocate-non-addr: exit status")
    14601     # don't restore from ebp
    14602     81 0/subop/add %esp 8/imm32
    14603     # . epilogue
    14604     5d/pop-to-ebp
    14605     c3/return
    14606
    14607 test-allocate-non-addr-handle:
    14608     # . prologue
    14609     55/push-ebp
    14610     89/<- %ebp 4/r32/esp
    14611     # setup
    14612     (clear-stream _test-input-stream)
    14613     (clear-stream $_test-input-buffered-file->buffer)
    14614     (clear-stream _test-output-stream)
    14615     (clear-stream $_test-output-buffered-file->buffer)
    14616     (clear-stream _test-error-stream)
    14617     (clear-stream $_test-error-buffered-file->buffer)
    14618     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    14619     68/push 0/imm32
    14620     68/push 0/imm32
    14621     89/<- %edx 4/r32/esp
    14622     (tailor-exit-descriptor %edx 0x10)
    14623     #
    14624     (write _test-input-stream "fn foo {\n")
    14625     (write _test-input-stream "  var y/ecx: (addr int) <- copy 0\n")
    14626     (write _test-input-stream "  allocate y\n")
    14627     (write _test-input-stream "}\n")
    14628     # convert
    14629     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    14630     # registers except esp clobbered at this point
    14631     # restore ed
    14632     89/<- %edx 4/r32/esp
    14633     (flush _test-output-buffered-file)
    14634     (flush _test-error-buffered-file)
    14635 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    14641     # check output
    14642     (check-stream-equal _test-output-stream  ""  "F - test-allocate-non-addr-handle: output should be empty")
    14643     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt allocate: inout 'y' must have type (addr handle ...)"  "F - test-allocate-non-addr-handle: error message")
    14644     # check that stop(1) was called
    14645     (check-ints-equal *(edx+4) 2 "F - test-allocate-non-addr-handle: exit status")
    14646     # don't restore from ebp
    14647     81 0/subop/add %esp 8/imm32
    14648     # . epilogue
    14649     5d/pop-to-ebp
    14650     c3/return
    14651
    14652 test-allocate-deref-address:
    14653     # . prologue
    14654     55/push-ebp
    14655     89/<- %ebp 4/r32/esp
    14656     # setup
    14657     (clear-stream _test-input-stream)
    14658     (clear-stream $_test-input-buffered-file->buffer)
    14659     (clear-stream _test-output-stream)
    14660     (clear-stream $_test-output-buffered-file->buffer)
    14661     #
    14662     (write _test-input-stream "fn foo {\n")
    14663     (write _test-input-stream "  var y/ecx: (addr addr handle int) <- copy 0\n")
    14664     (write _test-input-stream "  allocate *y\n")
    14665     (write _test-input-stream "}\n")
    14666     # convert
    14667     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
    14668     (flush _test-output-buffered-file)
    14669     # no errors
    14670     # . epilogue
    14671     5d/pop-to-ebp
    14672     c3/return
    14673
    14674 test-populate-with-no-inout:
    14675     # . prologue
    14676     55/push-ebp
    14677     89/<- %ebp 4/r32/esp
    14678     # setup
    14679     (clear-stream _test-input-stream)
    14680     (clear-stream $_test-input-buffered-file->buffer)
    14681     (clear-stream _test-output-stream)
    14682     (clear-stream $_test-output-buffered-file->buffer)
    14683     (clear-stream _test-error-stream)
    14684     (clear-stream $_test-error-buffered-file->buffer)
    14685     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    14686     68/push 0/imm32
    14687     68/push 0/imm32
    14688     89/<- %edx 4/r32/esp
    14689     (tailor-exit-descriptor %edx 0x10)
    14690     #
    14691     (write _test-input-stream "fn foo {\n")
    14692     (write _test-input-stream "  populate\n")
    14693     (write _test-input-stream "}\n")
    14694     # convert
    14695     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    14696     # registers except esp clobbered at this point
    14697     # restore ed
    14698     89/<- %edx 4/r32/esp
    14699     (flush _test-output-buffered-file)
    14700     (flush _test-error-buffered-file)
    14701 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    14707     # check output
    14708     (check-stream-equal _test-output-stream  ""  "F - test-populate-with-no-inout: output should be empty")
    14709     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'populate' must have two inouts"  "F - test-populate-with-no-inout: error message")
    14710     # check that stop(1) was called
    14711     (check-ints-equal *(edx+4) 2 "F - test-populate-with-no-inout: exit status")
    14712     # don't restore from ebp
    14713     81 0/subop/add %esp 8/imm32
    14714     # . epilogue
    14715     5d/pop-to-ebp
    14716     c3/return
    14717
    14718 test-populate-with-too-many-inouts:
    14719     # . prologue
    14720     55/push-ebp
    14721     89/<- %ebp 4/r32/esp
    14722     # setup
    14723     (clear-stream _test-input-stream)
    14724     (clear-stream $_test-input-buffered-file->buffer)
    14725     (clear-stream _test-output-stream)
    14726     (clear-stream $_test-output-buffered-file->buffer)
    14727     (clear-stream _test-error-stream)
    14728     (clear-stream $_test-error-buffered-file->buffer)
    14729     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    14730     68/push 0/imm32
    14731     68/push 0/imm32
    14732     89/<- %edx 4/r32/esp
    14733     (tailor-exit-descriptor %edx 0x10)
    14734     #
    14735     (write _test-input-stream "fn foo {\n")
    14736     (write _test-input-stream "  var x: (addr handle int)\n")
    14737     (write _test-input-stream "  populate x, 3, 0\n")
    14738     (write _test-input-stream "}\n")
    14739     # convert
    14740     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    14741     # registers except esp clobbered at this point
    14742     # restore ed
    14743     89/<- %edx 4/r32/esp
    14744     (flush _test-output-buffered-file)
    14745     (flush _test-error-buffered-file)
    14746 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    14752     # check output
    14753     (check-stream-equal _test-output-stream  ""  "F - test-populate-with-too-many-inouts: output should be empty")
    14754     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'populate' must have two inouts"  "F - test-populate-with-too-many-inouts: error message")
    14755     # check that stop(1) was called
    14756     (check-ints-equal *(edx+4) 2 "F - test-populate-with-too-many-inouts: exit status")
    14757     # don't restore from ebp
    14758     81 0/subop/add %esp 8/imm32
    14759     # . epilogue
    14760     5d/pop-to-ebp
    14761     c3/return
    14762
    14763 test-populate-with-output:
    14764     # . prologue
    14765     55/push-ebp
    14766     89/<- %ebp 4/r32/esp
    14767     # setup
    14768     (clear-stream _test-input-stream)
    14769     (clear-stream $_test-input-buffered-file->buffer)
    14770     (clear-stream _test-output-stream)
    14771     (clear-stream $_test-output-buffered-file->buffer)
    14772     (clear-stream _test-error-stream)
    14773     (clear-stream $_test-error-buffered-file->buffer)
    14774     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    14775     68/push 0/imm32
    14776     68/push 0/imm32
    14777     89/<- %edx 4/r32/esp
    14778     (tailor-exit-descriptor %edx 0x10)
    14779     #
    14780     (write _test-input-stream "fn foo {\n")
    14781     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
    14782     (write _test-input-stream "  var y/ecx: (addr handle int) <- copy 0\n")
    14783     (write _test-input-stream "  x <- populate y\n")
    14784     (write _test-input-stream "}\n")
    14785     # convert
    14786     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    14787     # registers except esp clobbered at this point
    14788     # restore ed
    14789     89/<- %edx 4/r32/esp
    14790     (flush _test-output-buffered-file)
    14791     (flush _test-error-buffered-file)
    14792 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    14798     # check output
    14799     (check-stream-equal _test-output-stream  ""  "F - test-populate-with-output: output should be empty")
    14800     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'populate' must not have any outputs"  "F - test-populate-with-output: error message")
    14801     # check that stop(1) was called
    14802     (check-ints-equal *(edx+4) 2 "F - test-populate-with-output: exit status")
    14803     # don't restore from ebp
    14804     81 0/subop/add %esp 8/imm32
    14805     # . epilogue
    14806     5d/pop-to-ebp
    14807     c3/return
    14808
    14809 test-populate-non-addr:
    14810     # . prologue
    14811     55/push-ebp
    14812     89/<- %ebp 4/r32/esp
    14813     # setup
    14814     (clear-stream _test-input-stream)
    14815     (clear-stream $_test-input-buffered-file->buffer)
    14816     (clear-stream _test-output-stream)
    14817     (clear-stream $_test-output-buffered-file->buffer)
    14818     (clear-stream _test-error-stream)
    14819     (clear-stream $_test-error-buffered-file->buffer)
    14820     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    14821     68/push 0/imm32
    14822     68/push 0/imm32
    14823     89/<- %edx 4/r32/esp
    14824     (tailor-exit-descriptor %edx 0x10)
    14825     #
    14826     (write _test-input-stream "fn foo {\n")
    14827     (write _test-input-stream "  var y: (handle int)\n")
    14828     (write _test-input-stream "  populate y, 3\n")
    14829     (write _test-input-stream "}\n")
    14830     # convert
    14831     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    14832     # registers except esp clobbered at this point
    14833     # restore ed
    14834     89/<- %edx 4/r32/esp
    14835     (flush _test-output-buffered-file)
    14836     (flush _test-error-buffered-file)
    14837 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    14843     # check output
    14844     (check-stream-equal _test-output-stream  ""  "F - test-populate-non-addr: output must be empty")
    14845     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt populate: first inout 'y' must have type (addr handle array ...)"  "F - test-populate-non-addr: error message")
    14846     # check that stop(1) was called
    14847     (check-ints-equal *(edx+4) 2 "F - test-populate-non-addr: exit status")
    14848     # don't restore from ebp
    14849     81 0/subop/add %esp 8/imm32
    14850     # . epilogue
    14851     5d/pop-to-ebp
    14852     c3/return
    14853
    14854 test-populate-non-addr-handle:
    14855     # . prologue
    14856     55/push-ebp
    14857     89/<- %ebp 4/r32/esp
    14858     # setup
    14859     (clear-stream _test-input-stream)
    14860     (clear-stream $_test-input-buffered-file->buffer)
    14861     (clear-stream _test-output-stream)
    14862     (clear-stream $_test-output-buffered-file->buffer)
    14863     (clear-stream _test-error-stream)
    14864     (clear-stream $_test-error-buffered-file->buffer)
    14865     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    14866     68/push 0/imm32
    14867     68/push 0/imm32
    14868     89/<- %edx 4/r32/esp
    14869     (tailor-exit-descriptor %edx 0x10)
    14870     #
    14871     (write _test-input-stream "fn foo {\n")
    14872     (write _test-input-stream "  var y/ecx: (addr int) <- copy 0\n")
    14873     (write _test-input-stream "  populate y, 3\n")
    14874     (write _test-input-stream "}\n")
    14875     # convert
    14876     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    14877     # registers except esp clobbered at this point
    14878     # restore ed
    14879     89/<- %edx 4/r32/esp
    14880     (flush _test-output-buffered-file)
    14881     (flush _test-error-buffered-file)
    14882 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    14888     # check output
    14889     (check-stream-equal _test-output-stream  ""  "F - test-populate-non-addr-handle: output should be empty")
    14890     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt populate: first inout 'y' must have type (addr handle array ...)"  "F - test-populate-non-addr-handle: error message")
    14891     # check that stop(1) was called
    14892     (check-ints-equal *(edx+4) 2 "F - test-populate-non-addr-handle: exit status")
    14893     # don't restore from ebp
    14894     81 0/subop/add %esp 8/imm32
    14895     # . epilogue
    14896     5d/pop-to-ebp
    14897     c3/return
    14898
    14899 test-populate-non-addr-handle-array:
    14900     # . prologue
    14901     55/push-ebp
    14902     89/<- %ebp 4/r32/esp
    14903     # setup
    14904     (clear-stream _test-input-stream)
    14905     (clear-stream $_test-input-buffered-file->buffer)
    14906     (clear-stream _test-output-stream)
    14907     (clear-stream $_test-output-buffered-file->buffer)
    14908     (clear-stream _test-error-stream)
    14909     (clear-stream $_test-error-buffered-file->buffer)
    14910     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    14911     68/push 0/imm32
    14912     68/push 0/imm32
    14913     89/<- %edx 4/r32/esp
    14914     (tailor-exit-descriptor %edx 0x10)
    14915     #
    14916     (write _test-input-stream "fn foo {\n")
    14917     (write _test-input-stream "  var y/ecx: (addr handle int) <- copy 0\n")
    14918     (write _test-input-stream "  populate y, 3\n")
    14919     (write _test-input-stream "}\n")
    14920     # convert
    14921     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    14922     # registers except esp clobbered at this point
    14923     # restore ed
    14924     89/<- %edx 4/r32/esp
    14925     (flush _test-output-buffered-file)
    14926     (flush _test-error-buffered-file)
    14927 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    14933     # check output
    14934     (check-stream-equal _test-output-stream  ""  "F - test-populate-non-addr-handle-array: output should be empty")
    14935     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt populate: first inout 'y' must have type (addr handle array ...)"  "F - test-populate-non-addr-handle-array: error message")
    14936     # check that stop(1) was called
    14937     (check-ints-equal *(edx+4) 2 "F - test-populate-non-addr-handle-array: exit status")
    14938     # don't restore from ebp
    14939     81 0/subop/add %esp 8/imm32
    14940     # . epilogue
    14941     5d/pop-to-ebp
    14942     c3/return
    14943
    14944 test-populate-deref-address:
    14945     # . prologue
    14946     55/push-ebp
    14947     89/<- %ebp 4/r32/esp
    14948     # setup
    14949     (clear-stream _test-input-stream)
    14950     (clear-stream $_test-input-buffered-file->buffer)
    14951     (clear-stream _test-output-stream)
    14952     (clear-stream $_test-output-buffered-file->buffer)
    14953     #
    14954     (write _test-input-stream "fn foo {\n")
    14955     (write _test-input-stream "  var y/ecx: (addr addr handle array int) <- copy 0\n")
    14956     (write _test-input-stream "  populate *y, 3\n")
    14957     (write _test-input-stream "}\n")
    14958     # convert
    14959     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
    14960     (flush _test-output-buffered-file)
    14961     # no errors
    14962     # . epilogue
    14963     5d/pop-to-ebp
    14964     c3/return
    14965
    14966 test-populate-stream-with-no-inout:
    14967     # . prologue
    14968     55/push-ebp
    14969     89/<- %ebp 4/r32/esp
    14970     # setup
    14971     (clear-stream _test-input-stream)
    14972     (clear-stream $_test-input-buffered-file->buffer)
    14973     (clear-stream _test-output-stream)
    14974     (clear-stream $_test-output-buffered-file->buffer)
    14975     (clear-stream _test-error-stream)
    14976     (clear-stream $_test-error-buffered-file->buffer)
    14977     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    14978     68/push 0/imm32
    14979     68/push 0/imm32
    14980     89/<- %edx 4/r32/esp
    14981     (tailor-exit-descriptor %edx 0x10)
    14982     #
    14983     (write _test-input-stream "fn foo {\n")
    14984     (write _test-input-stream "  populate-stream\n")
    14985     (write _test-input-stream "}\n")
    14986     # convert
    14987     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    14988     # registers except esp clobbered at this point
    14989     # restore ed
    14990     89/<- %edx 4/r32/esp
    14991     (flush _test-output-buffered-file)
    14992     (flush _test-error-buffered-file)
    14993 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    14999     # check output
    15000     (check-stream-equal _test-output-stream  ""  "F - test-populate-stream-with-no-inout: output should be empty")
    15001     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'populate-stream' must have two inouts"  "F - test-populate-stream-with-no-inout: error message")
    15002     # check that stop(1) was called
    15003     (check-ints-equal *(edx+4) 2 "F - test-populate-stream-with-no-inout: exit status")
    15004     # don't restore from ebp
    15005     81 0/subop/add %esp 8/imm32
    15006     # . epilogue
    15007     5d/pop-to-ebp
    15008     c3/return
    15009
    15010 test-populate-stream-with-too-many-inouts:
    15011     # . prologue
    15012     55/push-ebp
    15013     89/<- %ebp 4/r32/esp
    15014     # setup
    15015     (clear-stream _test-input-stream)
    15016     (clear-stream $_test-input-buffered-file->buffer)
    15017     (clear-stream _test-output-stream)
    15018     (clear-stream $_test-output-buffered-file->buffer)
    15019     (clear-stream _test-error-stream)
    15020     (clear-stream $_test-error-buffered-file->buffer)
    15021     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    15022     68/push 0/imm32
    15023     68/push 0/imm32
    15024     89/<- %edx 4/r32/esp
    15025     (tailor-exit-descriptor %edx 0x10)
    15026     #
    15027     (write _test-input-stream "fn foo {\n")
    15028     (write _test-input-stream "  var x: (addr handle int)\n")
    15029     (write _test-input-stream "  populate-stream x, 3, 0\n")
    15030     (write _test-input-stream "}\n")
    15031     # convert
    15032     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    15033     # registers except esp clobbered at this point
    15034     # restore ed
    15035     89/<- %edx 4/r32/esp
    15036     (flush _test-output-buffered-file)
    15037     (flush _test-error-buffered-file)
    15038 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    15044     # check output
    15045     (check-stream-equal _test-output-stream  ""  "F - test-populate-stream-with-too-many-inouts: output should be empty")
    15046     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'populate-stream' must have two inouts"  "F - test-populate-stream-with-too-many-inouts: error message")
    15047     # check that stop(1) was called
    15048     (check-ints-equal *(edx+4) 2 "F - test-populate-stream-with-too-many-inouts: exit status")
    15049     # don't restore from ebp
    15050     81 0/subop/add %esp 8/imm32
    15051     # . epilogue
    15052     5d/pop-to-ebp
    15053     c3/return
    15054
    15055 test-populate-stream-with-output:
    15056     # . prologue
    15057     55/push-ebp
    15058     89/<- %ebp 4/r32/esp
    15059     # setup
    15060     (clear-stream _test-input-stream)
    15061     (clear-stream $_test-input-buffered-file->buffer)
    15062     (clear-stream _test-output-stream)
    15063     (clear-stream $_test-output-buffered-file->buffer)
    15064     (clear-stream _test-error-stream)
    15065     (clear-stream $_test-error-buffered-file->buffer)
    15066     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    15067     68/push 0/imm32
    15068     68/push 0/imm32
    15069     89/<- %edx 4/r32/esp
    15070     (tailor-exit-descriptor %edx 0x10)
    15071     #
    15072     (write _test-input-stream "fn foo {\n")
    15073     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
    15074     (write _test-input-stream "  var y/ecx: (addr handle int) <- copy 0\n")
    15075     (write _test-input-stream "  x <- populate-stream y\n")
    15076     (write _test-input-stream "}\n")
    15077     # convert
    15078     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    15079     # registers except esp clobbered at this point
    15080     # restore ed
    15081     89/<- %edx 4/r32/esp
    15082     (flush _test-output-buffered-file)
    15083     (flush _test-error-buffered-file)
    15084 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    15090     # check output
    15091     (check-stream-equal _test-output-stream  ""  "F - test-populate-stream-with-output: output should be empty")
    15092     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'populate-stream' must not have any outputs"  "F - test-populate-stream-with-output: error message")
    15093     # check that stop(1) was called
    15094     (check-ints-equal *(edx+4) 2 "F - test-populate-stream-with-output: exit status")
    15095     # don't restore from ebp
    15096     81 0/subop/add %esp 8/imm32
    15097     # . epilogue
    15098     5d/pop-to-ebp
    15099     c3/return
    15100
    15101 test-populate-stream-non-addr:
    15102     # . prologue
    15103     55/push-ebp
    15104     89/<- %ebp 4/r32/esp
    15105     # setup
    15106     (clear-stream _test-input-stream)
    15107     (clear-stream $_test-input-buffered-file->buffer)
    15108     (clear-stream _test-output-stream)
    15109     (clear-stream $_test-output-buffered-file->buffer)
    15110     (clear-stream _test-error-stream)
    15111     (clear-stream $_test-error-buffered-file->buffer)
    15112     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    15113     68/push 0/imm32
    15114     68/push 0/imm32
    15115     89/<- %edx 4/r32/esp
    15116     (tailor-exit-descriptor %edx 0x10)
    15117     #
    15118     (write _test-input-stream "fn foo {\n")
    15119     (write _test-input-stream "  var y: (handle int)\n")
    15120     (write _test-input-stream "  populate-stream y, 3\n")
    15121     (write _test-input-stream "}\n")
    15122     # convert
    15123     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    15124     # registers except esp clobbered at this point
    15125     # restore ed
    15126     89/<- %edx 4/r32/esp
    15127     (flush _test-output-buffered-file)
    15128     (flush _test-error-buffered-file)
    15129 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    15135     # check output
    15136     (check-stream-equal _test-output-stream  ""  "F - test-populate-stream-non-addr: output must be empty")
    15137     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt populate-stream: first inout 'y' must have type (addr handle stream ...)"  "F - test-populate-stream-non-addr: error message")
    15138     # check that stop(1) was called
    15139     (check-ints-equal *(edx+4) 2 "F - test-populate-stream-non-addr: exit status")
    15140     # don't restore from ebp
    15141     81 0/subop/add %esp 8/imm32
    15142     # . epilogue
    15143     5d/pop-to-ebp
    15144     c3/return
    15145
    15146 test-populate-stream-non-addr-handle:
    15147     # . prologue
    15148     55/push-ebp
    15149     89/<- %ebp 4/r32/esp
    15150     # setup
    15151     (clear-stream _test-input-stream)
    15152     (clear-stream $_test-input-buffered-file->buffer)
    15153     (clear-stream _test-output-stream)
    15154     (clear-stream $_test-output-buffered-file->buffer)
    15155     (clear-stream _test-error-stream)
    15156     (clear-stream $_test-error-buffered-file->buffer)
    15157     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    15158     68/push 0/imm32
    15159     68/push 0/imm32
    15160     89/<- %edx 4/r32/esp
    15161     (tailor-exit-descriptor %edx 0x10)
    15162     #
    15163     (write _test-input-stream "fn foo {\n")
    15164     (write _test-input-stream "  var y/ecx: (addr int) <- copy 0\n")
    15165     (write _test-input-stream "  populate-stream y, 3\n")
    15166     (write _test-input-stream "}\n")
    15167     # convert
    15168     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    15169     # registers except esp clobbered at this point
    15170     # restore ed
    15171     89/<- %edx 4/r32/esp
    15172     (flush _test-output-buffered-file)
    15173     (flush _test-error-buffered-file)
    15174 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    15180     # check output
    15181     (check-stream-equal _test-output-stream  ""  "F - test-populate-stream-non-addr-handle: output should be empty")
    15182     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt populate-stream: first inout 'y' must have type (addr handle stream ...)"  "F - test-populate-stream-non-addr-handle: error message")
    15183     # check that stop(1) was called
    15184     (check-ints-equal *(edx+4) 2 "F - test-populate-stream-non-addr-handle: exit status")
    15185     # don't restore from ebp
    15186     81 0/subop/add %esp 8/imm32
    15187     # . epilogue
    15188     5d/pop-to-ebp
    15189     c3/return
    15190
    15191 test-populate-stream-non-addr-handle-stream:
    15192     # . prologue
    15193     55/push-ebp
    15194     89/<- %ebp 4/r32/esp
    15195     # setup
    15196     (clear-stream _test-input-stream)
    15197     (clear-stream $_test-input-buffered-file->buffer)
    15198     (clear-stream _test-output-stream)
    15199     (clear-stream $_test-output-buffered-file->buffer)
    15200     (clear-stream _test-error-stream)
    15201     (clear-stream $_test-error-buffered-file->buffer)
    15202     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    15203     68/push 0/imm32
    15204     68/push 0/imm32
    15205     89/<- %edx 4/r32/esp
    15206     (tailor-exit-descriptor %edx 0x10)
    15207     #
    15208     (write _test-input-stream "fn foo {\n")
    15209     (write _test-input-stream "  var y/ecx: (addr handle int) <- copy 0\n")
    15210     (write _test-input-stream "  populate-stream y, 3\n")
    15211     (write _test-input-stream "}\n")
    15212     # convert
    15213     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    15214     # registers except esp clobbered at this point
    15215     # restore ed
    15216     89/<- %edx 4/r32/esp
    15217     (flush _test-output-buffered-file)
    15218     (flush _test-error-buffered-file)
    15219 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    15225     # check output
    15226     (check-stream-equal _test-output-stream  ""  "F - test-populate-stream-non-addr-handle-stream: output should be empty")
    15227     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt populate-stream: first inout 'y' must have type (addr handle stream ...)"  "F - test-populate-stream-non-addr-handle-stream: error message")
    15228     # check that stop(1) was called
    15229     (check-ints-equal *(edx+4) 2 "F - test-populate-stream-non-addr-handle-stream: exit status")
    15230     # don't restore from ebp
    15231     81 0/subop/add %esp 8/imm32
    15232     # . epilogue
    15233     5d/pop-to-ebp
    15234     c3/return
    15235
    15236 test-populate-stream-deref-address:
    15237     # . prologue
    15238     55/push-ebp
    15239     89/<- %ebp 4/r32/esp
    15240     # setup
    15241     (clear-stream _test-input-stream)
    15242     (clear-stream $_test-input-buffered-file->buffer)
    15243     (clear-stream _test-output-stream)
    15244     (clear-stream $_test-output-buffered-file->buffer)
    15245     #
    15246     (write _test-input-stream "fn foo {\n")
    15247     (write _test-input-stream "  var y/ecx: (addr addr handle stream int) <- copy 0\n")
    15248     (write _test-input-stream "  populate-stream *y, 3\n")
    15249     (write _test-input-stream "}\n")
    15250     # convert
    15251     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
    15252     (flush _test-output-buffered-file)
    15253     # no errors
    15254     # . epilogue
    15255     5d/pop-to-ebp
    15256     c3/return
    15257
    15258 test-convert-with-no-inout:
    15259     # . prologue
    15260     55/push-ebp
    15261     89/<- %ebp 4/r32/esp
    15262     # setup
    15263     (clear-stream _test-input-stream)
    15264     (clear-stream $_test-input-buffered-file->buffer)
    15265     (clear-stream _test-output-stream)
    15266     (clear-stream $_test-output-buffered-file->buffer)
    15267     (clear-stream _test-error-stream)
    15268     (clear-stream $_test-error-buffered-file->buffer)
    15269     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    15270     68/push 0/imm32
    15271     68/push 0/imm32
    15272     89/<- %edx 4/r32/esp
    15273     (tailor-exit-descriptor %edx 0x10)
    15274     #
    15275     (write _test-input-stream "fn foo {\n")
    15276     (write _test-input-stream "  var x/eax: int <- convert\n")
    15277     (write _test-input-stream "}\n")
    15278     # convert
    15279     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    15280     # registers except esp clobbered at this point
    15281     # restore ed
    15282     89/<- %edx 4/r32/esp
    15283     (flush _test-output-buffered-file)
    15284     (flush _test-error-buffered-file)
    15285 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    15291     # check output
    15292     (check-stream-equal _test-output-stream  ""  "F - test-convert-with-no-inout: output should be empty")
    15293     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'convert' expects an inout"  "F - test-convert-with-no-inout: error message")
    15294     # check that stop(1) was called
    15295     (check-ints-equal *(edx+4) 2 "F - test-convert-with-no-inout: exit status")
    15296     # don't restore from ebp
    15297     81 0/subop/add %esp 8/imm32
    15298     # . epilogue
    15299     5d/pop-to-ebp
    15300     c3/return
    15301
    15302 test-convert-with-multiple-inouts:
    15303     # . prologue
    15304     55/push-ebp
    15305     89/<- %ebp 4/r32/esp
    15306     # setup
    15307     (clear-stream _test-input-stream)
    15308     (clear-stream $_test-input-buffered-file->buffer)
    15309     (clear-stream _test-output-stream)
    15310     (clear-stream $_test-output-buffered-file->buffer)
    15311     (clear-stream _test-error-stream)
    15312     (clear-stream $_test-error-buffered-file->buffer)
    15313     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    15314     68/push 0/imm32
    15315     68/push 0/imm32
    15316     89/<- %edx 4/r32/esp
    15317     (tailor-exit-descriptor %edx 0x10)
    15318     #
    15319     (write _test-input-stream "fn foo {\n")
    15320     (write _test-input-stream "  var x/eax: int <- convert 0, 0\n")
    15321     (write _test-input-stream "}\n")
    15322     # convert
    15323     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    15324     # registers except esp clobbered at this point
    15325     # restore ed
    15326     89/<- %edx 4/r32/esp
    15327     (flush _test-output-buffered-file)
    15328     (flush _test-error-buffered-file)
    15329 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    15335     # check output
    15336     (check-stream-equal _test-output-stream  ""  "F - test-convert-with-multiple-inouts: output should be empty")
    15337     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'convert' must have just one inout"  "F - test-convert-with-multiple-inouts: error message")
    15338     # check that stop(1) was called
    15339     (check-ints-equal *(edx+4) 2 "F - test-convert-with-multiple-inouts: exit status")
    15340     # don't restore from ebp
    15341     81 0/subop/add %esp 8/imm32
    15342     # . epilogue
    15343     5d/pop-to-ebp
    15344     c3/return
    15345
    15346 test-convert-with-no-output:
    15347     # . prologue
    15348     55/push-ebp
    15349     89/<- %ebp 4/r32/esp
    15350     # setup
    15351     (clear-stream _test-input-stream)
    15352     (clear-stream $_test-input-buffered-file->buffer)
    15353     (clear-stream _test-output-stream)
    15354     (clear-stream $_test-output-buffered-file->buffer)
    15355     (clear-stream _test-error-stream)
    15356     (clear-stream $_test-error-buffered-file->buffer)
    15357     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    15358     68/push 0/imm32
    15359     68/push 0/imm32
    15360     89/<- %edx 4/r32/esp
    15361     (tailor-exit-descriptor %edx 0x10)
    15362     #
    15363     (write _test-input-stream "fn foo {\n")
    15364     (write _test-input-stream "  convert 0\n")
    15365     (write _test-input-stream "}\n")
    15366     # convert
    15367     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    15368     # registers except esp clobbered at this point
    15369     # restore ed
    15370     89/<- %edx 4/r32/esp
    15371     (flush _test-output-buffered-file)
    15372     (flush _test-error-buffered-file)
    15373 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    15379     # check output
    15380     (check-stream-equal _test-output-stream  ""  "F - test-convert-with-no-output: output should be empty")
    15381     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'convert' expects an output"  "F - test-convert-with-no-output: error message")
    15382     # check that stop(1) was called
    15383     (check-ints-equal *(edx+4) 2 "F - test-convert-with-no-output: exit status")
    15384     # don't restore from ebp
    15385     81 0/subop/add %esp 8/imm32
    15386     # . epilogue
    15387     5d/pop-to-ebp
    15388     c3/return
    15389
    15390 test-convert-with-multiple-outputs:
    15391     # . prologue
    15392     55/push-ebp
    15393     89/<- %ebp 4/r32/esp
    15394     # setup
    15395     (clear-stream _test-input-stream)
    15396     (clear-stream $_test-input-buffered-file->buffer)
    15397     (clear-stream _test-output-stream)
    15398     (clear-stream $_test-output-buffered-file->buffer)
    15399     (clear-stream _test-error-stream)
    15400     (clear-stream $_test-error-buffered-file->buffer)
    15401     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    15402     68/push 0/imm32
    15403     68/push 0/imm32
    15404     89/<- %edx 4/r32/esp
    15405     (tailor-exit-descriptor %edx 0x10)
    15406     #
    15407     (write _test-input-stream "fn foo {\n")
    15408     (write _test-input-stream "  var x/eax: int <- copy 0\n")
    15409     (write _test-input-stream "  var y/ecx: int <- copy 0\n")
    15410     (write _test-input-stream "  x, y <- convert 0\n")
    15411     (write _test-input-stream "}\n")
    15412     # convert
    15413     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    15414     # registers except esp clobbered at this point
    15415     # restore ed
    15416     89/<- %edx 4/r32/esp
    15417     (flush _test-output-buffered-file)
    15418     (flush _test-error-buffered-file)
    15419 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    15425     # check output
    15426     (check-stream-equal _test-output-stream  ""  "F - test-convert-with-multiple-outputs: output should be empty")
    15427     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'convert' must have just one output"  "F - test-convert-with-multiple-outputs: error message")
    15428     # check that stop(1) was called
    15429     (check-ints-equal *(edx+4) 2 "F - test-convert-with-multiple-outputs: exit status")
    15430     # don't restore from ebp
    15431     81 0/subop/add %esp 8/imm32
    15432     # . epilogue
    15433     5d/pop-to-ebp
    15434     c3/return
    15435
    15436 test-convert-deref-address:
    15437     # . prologue
    15438     55/push-ebp
    15439     89/<- %ebp 4/r32/esp
    15440     # setup
    15441     (clear-stream _test-input-stream)
    15442     (clear-stream $_test-input-buffered-file->buffer)
    15443     (clear-stream _test-output-stream)
    15444     (clear-stream $_test-output-buffered-file->buffer)
    15445     #
    15446     (write _test-input-stream "fn foo {\n")
    15447     (write _test-input-stream "  var x/eax: (addr int) <- copy 0\n")
    15448     (write _test-input-stream "  var y/xmm4: float <- convert *x\n")
    15449     (write _test-input-stream "}\n")
    15450     # convert
    15451     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
    15452     (flush _test-output-buffered-file)
    15453     # no errors
    15454     # . epilogue
    15455     5d/pop-to-ebp
    15456     c3/return
    15457
    15458 test-convert-to-non-register:
    15459     # . prologue
    15460     55/push-ebp
    15461     89/<- %ebp 4/r32/esp
    15462     # setup
    15463     (clear-stream _test-input-stream)
    15464     (clear-stream $_test-input-buffered-file->buffer)
    15465     (clear-stream _test-output-stream)
    15466     (clear-stream $_test-output-buffered-file->buffer)
    15467     (clear-stream _test-error-stream)
    15468     (clear-stream $_test-error-buffered-file->buffer)
    15469     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    15470     68/push 0/imm32
    15471     68/push 0/imm32
    15472     89/<- %edx 4/r32/esp
    15473     (tailor-exit-descriptor %edx 0x10)
    15474     #
    15475     (write _test-input-stream "fn foo {\n")
    15476     (write _test-input-stream "  var x: float\n")
    15477     (write _test-input-stream "  var y: int\n")
    15478     (write _test-input-stream "  x <- convert y\n")
    15479     (write _test-input-stream "}\n")
    15480     # convert
    15481     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    15482     # registers except esp clobbered at this point
    15483     # restore ed
    15484     89/<- %edx 4/r32/esp
    15485     (flush _test-output-buffered-file)
    15486     (flush _test-error-buffered-file)
    15487 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    15493     # check output
    15494     (check-stream-equal _test-output-stream  ""  "F - test-convert-to-non-register: output should be empty")
    15495     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt convert: output 'x' not in a register"  "F - test-convert-to-non-register: error message")
    15496     # check that stop(1) was called
    15497     (check-ints-equal *(edx+4) 2 "F - test-convert-to-non-register: exit status")
    15498     # don't restore from ebp
    15499     81 0/subop/add %esp 8/imm32
    15500     # . epilogue
    15501     5d/pop-to-ebp
    15502     c3/return
    15503
    15504 test-convert-invalid-inout-type:
    15505     # . prologue
    15506     55/push-ebp
    15507     89/<- %ebp 4/r32/esp
    15508     # setup
    15509     (clear-stream _test-input-stream)
    15510     (clear-stream $_test-input-buffered-file->buffer)
    15511     (clear-stream _test-output-stream)
    15512     (clear-stream $_test-output-buffered-file->buffer)
    15513     (clear-stream _test-error-stream)
    15514     (clear-stream $_test-error-buffered-file->buffer)
    15515     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    15516     68/push 0/imm32
    15517     68/push 0/imm32
    15518     89/<- %edx 4/r32/esp
    15519     (tailor-exit-descriptor %edx 0x10)
    15520     #
    15521     (write _test-input-stream "fn foo {\n")
    15522     (write _test-input-stream "  var x: boolean\n")
    15523     (write _test-input-stream "  var y/xmm1: float <- convert x\n")
    15524     (write _test-input-stream "}\n")
    15525     # convert
    15526     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    15527     # registers except esp clobbered at this point
    15528     # restore ed
    15529     89/<- %edx 4/r32/esp
    15530     (flush _test-output-buffered-file)
    15531     (flush _test-error-buffered-file)
    15532 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    15538     # check output
    15539     (check-stream-equal _test-output-stream  ""  "F - test-convert-invalid-inout-type: output should be empty")
    15540     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt convert: inout 'x' must be an int or float"  "F - test-convert-invalid-inout-type: error message")
    15541     # check that stop(1) was called
    15542     (check-ints-equal *(edx+4) 2 "F - test-convert-invalid-inout-type: exit status")
    15543     # don't restore from ebp
    15544     81 0/subop/add %esp 8/imm32
    15545     # . epilogue
    15546     5d/pop-to-ebp
    15547     c3/return
    15548
    15549 test-convert-invalid-output-type:
    15550     # . prologue
    15551     55/push-ebp
    15552     89/<- %ebp 4/r32/esp
    15553     # setup
    15554     (clear-stream _test-input-stream)
    15555     (clear-stream $_test-input-buffered-file->buffer)
    15556     (clear-stream _test-output-stream)
    15557     (clear-stream $_test-output-buffered-file->buffer)
    15558     (clear-stream _test-error-stream)
    15559     (clear-stream $_test-error-buffered-file->buffer)
    15560     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    15561     68/push 0/imm32
    15562     68/push 0/imm32
    15563     89/<- %edx 4/r32/esp
    15564     (tailor-exit-descriptor %edx 0x10)
    15565     #
    15566     (write _test-input-stream "fn foo {\n")
    15567     (write _test-input-stream "  var x: float\n")
    15568     (write _test-input-stream "  var y/eax: boolean <- convert x\n")
    15569     (write _test-input-stream "}\n")
    15570     # convert
    15571     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    15572     # registers except esp clobbered at this point
    15573     # restore ed
    15574     89/<- %edx 4/r32/esp
    15575     (flush _test-output-buffered-file)
    15576     (flush _test-error-buffered-file)
    15577 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    15583     # check output
    15584     (check-stream-equal _test-output-stream  ""  "F - test-convert-invalid-output-type: output should be empty")
    15585     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt convert: output 'y' must be an int or float"  "F - test-convert-invalid-output-type: error message")
    15586     # check that stop(1) was called
    15587     (check-ints-equal *(edx+4) 2 "F - test-convert-invalid-output-type: exit status")
    15588     # don't restore from ebp
    15589     81 0/subop/add %esp 8/imm32
    15590     # . epilogue
    15591     5d/pop-to-ebp
    15592     c3/return
    15593
    15594 test-convert-int-to-int:
    15595     # . prologue
    15596     55/push-ebp
    15597     89/<- %ebp 4/r32/esp
    15598     # setup
    15599     (clear-stream _test-input-stream)
    15600     (clear-stream $_test-input-buffered-file->buffer)
    15601     (clear-stream _test-output-stream)
    15602     (clear-stream $_test-output-buffered-file->buffer)
    15603     (clear-stream _test-error-stream)
    15604     (clear-stream $_test-error-buffered-file->buffer)
    15605     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    15606     68/push 0/imm32
    15607     68/push 0/imm32
    15608     89/<- %edx 4/r32/esp
    15609     (tailor-exit-descriptor %edx 0x10)
    15610     #
    15611     (write _test-input-stream "fn foo {\n")
    15612     (write _test-input-stream "  var x: int\n")
    15613     (write _test-input-stream "  var y/eax: int <- convert x\n")
    15614     (write _test-input-stream "}\n")
    15615     # convert
    15616     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    15617     # registers except esp clobbered at this point
    15618     # restore ed
    15619     89/<- %edx 4/r32/esp
    15620     (flush _test-output-buffered-file)
    15621     (flush _test-error-buffered-file)
    15622 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    15628     # check output
    15629     (check-stream-equal _test-output-stream  ""  "F - test-convert-int-to-int: output should be empty")
    15630     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt convert: no need to convert int to int"  "F - test-convert-int-to-int: error message")
    15631     # check that stop(1) was called
    15632     (check-ints-equal *(edx+4) 2 "F - test-convert-int-to-int: exit status")
    15633     # don't restore from ebp
    15634     81 0/subop/add %esp 8/imm32
    15635     # . epilogue
    15636     5d/pop-to-ebp
    15637     c3/return
    15638
    15639 test-convert-float-to-float:
    15640     # . prologue
    15641     55/push-ebp
    15642     89/<- %ebp 4/r32/esp
    15643     # setup
    15644     (clear-stream _test-input-stream)
    15645     (clear-stream $_test-input-buffered-file->buffer)
    15646     (clear-stream _test-output-stream)
    15647     (clear-stream $_test-output-buffered-file->buffer)
    15648     (clear-stream _test-error-stream)
    15649     (clear-stream $_test-error-buffered-file->buffer)
    15650     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    15651     68/push 0/imm32
    15652     68/push 0/imm32
    15653     89/<- %edx 4/r32/esp
    15654     (tailor-exit-descriptor %edx 0x10)
    15655     #
    15656     (write _test-input-stream "fn foo {\n")
    15657     (write _test-input-stream "  var x: float\n")
    15658     (write _test-input-stream "  var y/xmm6: float <- convert x\n")
    15659     (write _test-input-stream "}\n")
    15660     # convert
    15661     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    15662     # registers except esp clobbered at this point
    15663     # restore ed
    15664     89/<- %edx 4/r32/esp
    15665     (flush _test-output-buffered-file)
    15666     (flush _test-error-buffered-file)
    15667 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    15673     # check output
    15674     (check-stream-equal _test-output-stream  ""  "F - test-convert-float-to-float: output should be empty")
    15675     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt convert: no need to convert float to float"  "F - test-convert-float-to-float: error message")
    15676     # check that stop(1) was called
    15677     (check-ints-equal *(edx+4) 2 "F - test-convert-float-to-float: exit status")
    15678     # don't restore from ebp
    15679     81 0/subop/add %esp 8/imm32
    15680     # . epilogue
    15681     5d/pop-to-ebp
    15682     c3/return
    15683
    15684 #######################################################
    15685 # Parsing
    15686 #######################################################
    15687
    15688 == data
    15689
    15690 # Global state added to each var record when parsing a function
    15691 Next-block-index:  # (addr int)
    15692     1/imm32
    15693
    15694 Curr-block-depth:  # (addr int)
    15695     1/imm32
    15696
    15697 == code
    15698
    15699 parse-mu:  # in: (addr buffered-file), err: (addr buffered-file), ed: (addr exit-descriptor)
    15700     # pseudocode
    15701     #   var curr-function: (addr handle function) = Program->functions
    15702     #   var curr-signature: (addr handle function) = Program->signatures
    15703     #   var curr-type: (addr handle typeinfo) = Program->types
    15704     #   var line: (stream byte 512)
    15705     #   var word-slice: slice
    15706     #   while true                                  # line loop
    15707     #     clear-stream(line)
    15708     #     read-line-buffered(in, line)
    15709     #     if (line->write == 0) break               # end of file
    15710     #     word-slice = next-mu-token(line)
    15711     #     if slice-empty?(word-slice)               # end of line
    15712     #       continue
    15713     #     else if slice-starts-with?(word-slice, "#")  # comment
    15714     #       continue                                # end of line
    15715     #     else if slice-equal?(word-slice, "fn")
    15716     #       var new-function: (handle function) = allocate(function)
    15717     #       var vars: (stack live-var 256)
    15718     #       populate-mu-function-header(line, new-function, vars)
    15719     #       populate-mu-function-body(in, new-function, vars)
    15720     #       assert(vars->top == 0)
    15721     #       *curr-function = new-function
    15722     #       curr-function = &new-function->next
    15723     #     else if slice-equal?(word-slice, "sig")
    15724     #       var new-function: (handle function) = allocate(function)
    15725     #       populate-mu-function-signature(line, new-function)
    15726     #       *curr-signature = new-function
    15727     #       curr-signature = &new-function->next
    15728     #     else if slice-equal?(word-slice, "type")
    15729     #       word-slice = next-mu-token(line)
    15730     #       type-id = pos-or-insert-slice(Type-id, word-slice)
    15731     #       var new-type: (handle typeinfo) = find-or-create-typeinfo(type-id)
    15732     #       assert(next-word(line) == "{")
    15733     #       populate-mu-type(in, new-type)
    15734     #     else
    15735     #       abort()
    15736     #
    15737     # . prologue
    15738     55/push-ebp
    15739     89/<- %ebp 4/r32/esp
    15740     # var curr-signature: (addr handle function) at *(ebp-4)
    15741     68/push _Program-signatures/imm32
    15742     # . save registers
    15743     50/push-eax
    15744     51/push-ecx
    15745     52/push-edx
    15746     53/push-ebx
    15747     56/push-esi
    15748     57/push-edi
    15749     # var line/ecx: (stream byte 512)
    15750     81 5/subop/subtract %esp 0x200/imm32
    15751     68/push 0x200/imm32/size
    15752     68/push 0/imm32/read
    15753     68/push 0/imm32/write
    15754     89/<- %ecx 4/r32/esp
    15755     # var word-slice/edx: slice
    15756     68/push 0/imm32/end
    15757     68/push 0/imm32/start
    15758     89/<- %edx 4/r32/esp
    15759     # var curr-function/edi: (addr handle function)
    15760     bf/copy-to-edi _Program-functions/imm32
    15761     # var vars/ebx: (stack live-var 256)
    15762     81 5/subop/subtract %esp 0xc00/imm32
    15763     68/push 0xc00/imm32/size
    15764     68/push 0/imm32/top
    15765     89/<- %ebx 4/r32/esp
    15766     {
    15767 $parse-mu:line-loop:
    15768       (clear-stream %ecx)
    15769       (read-line-buffered *(ebp+8) %ecx)
    15770       # if (line->write == 0) break
    15771       81 7/subop/compare *ecx 0/imm32
    15772       0f 84/jump-if-= break/disp32
    15773 +--  6 lines: #?       # dump line ------------------------------------------------------------------------------------------------------------------------------------------------------
    15779       (next-mu-token %ecx %edx)
    15780       # if slice-empty?(word-slice) continue
    15781       (slice-empty? %edx)  # => eax
    15782       3d/compare-eax-and 0/imm32/false
    15783       0f 85/jump-if-!= loop/disp32
    15784       # if (*word-slice->start == "#") continue
    15785       # . eax = *word-slice->start
    15786       8b/-> *edx 0/r32/eax
    15787       8a/copy-byte *eax 0/r32/AL
    15788       81 4/subop/and %eax 0xff/imm32
    15789       # . if (eax == '#') continue
    15790       3d/compare-eax-and 0x23/imm32/hash
    15791       0f 84/jump-if-= loop/disp32
    15792       # if (slice-equal?(word-slice, "fn")) parse a function
    15793       {
    15794 $parse-mu:fn:
    15795         (slice-equal? %edx "fn")  # => eax
    15796         3d/compare-eax-and 0/imm32/false
    15797         0f 84/jump-if-= break/disp32
    15798         # var new-function/esi: (handle function)
    15799         68/push 0/imm32
    15800         68/push 0/imm32
    15801         89/<- %esi 4/r32/esp
    15802         # populate-mu-function(line, in, vars, new-function)
    15803         (allocate Heap *Function-size %esi)
    15804         # var new-function-addr/eax: (addr function)
    15805         (lookup *esi *(esi+4))  # => eax
    15806         # initialize vars
    15807         (clear-stack %ebx)
    15808         #
    15809         (populate-mu-function-header %ecx %eax %ebx *(ebp+0xc) *(ebp+0x10))
    15810         (populate-mu-function-body *(ebp+8) %eax %ebx *(ebp+0xc) *(ebp+0x10))
    15811         # *curr-function = new-function
    15812         8b/-> *esi 0/r32/eax
    15813         89/<- *edi 0/r32/eax
    15814         8b/-> *(esi+4) 0/r32/eax
    15815         89/<- *(edi+4) 0/r32/eax
    15816         # curr-function = &new-function->next
    15817         # . var tmp/eax: (addr function) = lookup(new-function)
    15818         (lookup *esi *(esi+4))  # => eax
    15819         # . curr-function = &tmp->next
    15820         8d/copy-address *(eax+0x20) 7/r32/edi  # Function-next
    15821         # reclaim new-function
    15822         81 0/subop/add %esp 8/imm32
    15823         #
    15824         e9/jump $parse-mu:line-loop/disp32
    15825       }
    15826       # if (slice-equal?(word-slice, "sig")) parse a function signature
    15827       # Function signatures are for providing types to SubX functions.
    15828       {
    15829 $parse-mu:sig:
    15830         (slice-equal? %edx "sig")  # => eax
    15831         3d/compare-eax-and 0/imm32/false
    15832         0f 84/jump-if-= break/disp32
    15833         # edi = curr-function
    15834         57/push-edi
    15835         8b/-> *(ebp-4) 7/r32/edi
    15836         # var new-function/esi: (handle function)
    15837         68/push 0/imm32
    15838         68/push 0/imm32
    15839         89/<- %esi 4/r32/esp
    15840         # populate-mu-function(line, in, vars, new-function)
    15841         (allocate Heap *Function-size %esi)
    15842         # var new-function-addr/eax: (addr function)
    15843         (lookup *esi *(esi+4))  # => eax
    15844         #
    15845         (populate-mu-function-signature %ecx %eax *(ebp+0xc) *(ebp+0x10))
    15846         # *curr-signature = new-function
    15847         8b/-> *esi 0/r32/eax
    15848         89/<- *edi 0/r32/eax
    15849         8b/-> *(esi+4) 0/r32/eax
    15850         89/<- *(edi+4) 0/r32/eax
    15851         # curr-signature = &new-function->next
    15852         # . var tmp/eax: (addr function) = lookup(new-function)
    15853         (lookup *esi *(esi+4))  # => eax
    15854         # . curr-function = &tmp->next
    15855         8d/copy-address *(eax+0x20) 7/r32/edi  # Function-next
    15856         # reclaim new-function
    15857         81 0/subop/add %esp 8/imm32
    15858         # save curr-function
    15859         89/<- *(ebp-4) 7/r32/edi
    15860         # restore edi
    15861         5f/pop-to-edi
    15862         #
    15863         e9/jump $parse-mu:line-loop/disp32
    15864       }
    15865       # if (slice-equal?(word-slice, "type")) parse a type (struct/record) definition
    15866       {
    15867 $parse-mu:type:
    15868         (slice-equal? %edx "type")  # => eax
    15869         3d/compare-eax-and 0/imm32
    15870         0f 84/jump-if-= break/disp32
    15871         (next-mu-token %ecx %edx)
    15872         # var type-id/eax: int
    15873         (pos-or-insert-slice Type-id %edx)  # => eax
    15874         # spill
    15875         51/push-ecx
    15876         # var new-type/ecx: (handle typeinfo)
    15877         68/push 0/imm32
    15878         68/push 0/imm32
    15879         89/<- %ecx 4/r32/esp
    15880         (find-or-create-typeinfo %eax %ecx)
    15881         #
    15882         (lookup *ecx *(ecx+4))  # => eax
    15883         # TODO: ensure that 'line' has nothing else but '{'
    15884 #? (dump-typeinfos "=== aaa\n")
    15885         (populate-mu-type *(ebp+8) %eax *(ebp+0xc) *(ebp+0x10))  # => eax
    15886 #? (dump-typeinfos "=== zzz\n")
    15887         # reclaim new-type
    15888         81 0/subop/add %esp 8/imm32
    15889         # restore
    15890         59/pop-to-ecx
    15891         e9/jump $parse-mu:line-loop/disp32
    15892       }
    15893       # otherwise abort
    15894       e9/jump $parse-mu:error1/disp32
    15895     } # end line loop
    15896 $parse-mu:end:
    15897     # . reclaim locals
    15898     81 0/subop/add %esp 0x20c/imm32  # line
    15899     81 0/subop/add %esp 0xc08/imm32  # vars
    15900     81 0/subop/add %esp 8/imm32
    15901     # . restore registers
    15902     5f/pop-to-edi
    15903     5e/pop-to-esi
    15904     5b/pop-to-ebx
    15905     5a/pop-to-edx
    15906     59/pop-to-ecx
    15907     58/pop-to-eax
    15908     # . reclaim local
    15909     81 0/subop/add %esp 4/imm32
    15910     # . epilogue
    15911     89/<- %esp 5/r32/ebp
    15912     5d/pop-to-ebp
    15913     c3/return
    15914
    15915 $parse-mu:error1:
    15916     # error("unexpected top-level command: " word-slice "\n")
    15917     (write-buffered *(ebp+0xc) "unexpected top-level command: ")
    15918     (write-slice-buffered *(ebp+0xc) %edx)
    15919     (write-buffered *(ebp+0xc) "\n")
    15920     (flush *(ebp+0xc))
    15921     (stop *(ebp+0x10) 1)
    15922     # never gets here
    15923
    15924 $parse-mu:error2:
    15925     # error(vars->top " vars not reclaimed after fn '" new-function->name "'\n")
    15926     (write-int32-hex-buffered *(ebp+0xc) *ebx)
    15927     (write-buffered *(ebp+0xc) " vars not reclaimed after fn '")
    15928     (write-slice-buffered *(ebp+0xc) *eax)  # Function-name
    15929     (write-buffered *(ebp+0xc) "'\n")
    15930     (flush *(ebp+0xc))
    15931     (stop *(ebp+0x10) 1)
    15932     # never gets here
    15933
    15934 # scenarios considered:
    15935 # ✗ fn foo  # no block
    15936 # ✓ fn foo {
    15937 # ✗ fn foo { {
    15938 # ✗ fn foo { }
    15939 # ✗ fn foo { } {
    15940 # ✗ fn foo x {
    15941 # ✗ fn foo x: {
    15942 # ✓ fn foo x: int {
    15943 # ✓ fn foo x: int {
    15944 # ✓ fn foo x: int -> _/eax: int {
    15945 # TODO:
    15946 #   disallow outputs of type `(... addr ...)`
    15947 #   disallow inputs of type `(... addr ... addr ...)`
    15948 populate-mu-function-header:  # first-line: (addr stream byte), out: (addr function), vars: (addr stack live-var), err: (addr buffered-file), ed: (addr exit-descriptor)
    15949     # pseudocode:
    15950     #   var word-slice: slice
    15951     #   next-mu-token(first-line, word-slice)
    15952     #   if slice-empty?(word-slice) abort
    15953     #   assert(word-slice not in '{' '}' '->')
    15954     #   out->name = slice-to-string(word-slice)
    15955     #   ## inouts
    15956     #   while true
    15957     #     word-slice = next-mu-token(first-line)
    15958     #     if slice-empty?(word-slice) abort
    15959     #     if (word-slice == '{') goto done
    15960     #     if (word-slice == '->') break
    15961     #     assert(word-slice != '}')
    15962     #     var v: (handle var) = parse-var-with-type(word-slice, first-line)
    15963     #     assert(v->register == null)
    15964     #     # v->block-depth is implicitly 0
    15965     #     out->inouts = append(v, out->inouts)
    15966     #     push(vars, {v, false})
    15967     #   ## outputs
    15968     #   while true
    15969     #     word-slice = next-mu-token(first-line)
    15970     #     if slice-empty?(word-slice) abort
    15971     #     if (word-slice == '{') break
    15972     #     assert(word-slice not in '}' '->')
    15973     #     var v: (handle var) = parse-var-with-type(word-slice, first-line)
    15974     #     assert(v->register != null)
    15975     #     assert(v->name == "_")
    15976     #     out->outputs = append(v, out->outputs)
    15977     #   done:
    15978     #
    15979     # . prologue
    15980     55/push-ebp
    15981     89/<- %ebp 4/r32/esp
    15982     # . save registers
    15983     50/push-eax
    15984     51/push-ecx
    15985     52/push-edx
    15986     53/push-ebx
    15987     57/push-edi
    15988     # edi = out
    15989     8b/-> *(ebp+0xc) 7/r32/edi
    15990     # var word-slice/ecx: slice
    15991     68/push 0/imm32/end
    15992     68/push 0/imm32/start
    15993     89/<- %ecx 4/r32/esp
    15994     # var v/ebx: (handle var)
    15995     68/push 0/imm32
    15996     68/push 0/imm32
    15997     89/<- %ebx 4/r32/esp
    15998     # read function name
    15999     (next-mu-token *(ebp+8) %ecx)
    16000     # error checking
    16001     # if slice-empty?(word-slice) abort
    16002     (slice-empty? %ecx)  # => eax
    16003     3d/compare-eax-and 0/imm32/false
    16004     0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
    16005     # if (word-slice == '{') abort
    16006     (slice-equal? %ecx "{")   # => eax
    16007     3d/compare-eax-and 0/imm32/false
    16008     0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
    16009     # if (word-slice == '->') abort
    16010     (slice-equal? %ecx "->")   # => eax
    16011     3d/compare-eax-and 0/imm32/false
    16012     0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
    16013     # if (word-slice == '}') abort
    16014     (slice-equal? %ecx "}")   # => eax
    16015     3d/compare-eax-and 0/imm32/false
    16016     0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
    16017     # if word-slice already defined, abort
    16018     (function-exists? %ecx)  # => eax
    16019     3d/compare-eax-and 0/imm32/false
    16020     0f 85/jump-if-!= $populate-mu-function-header:error-duplicate/disp32
    16021     #
    16022     (slice-starts-with? %ecx "break")  # => eax
    16023     3d/compare-eax-and 0/imm32/false
    16024     0f 85/jump-if-!= $populate-mu-function-header:error-break/disp32
    16025     (slice-starts-with? %ecx "loop")  # => eax
    16026     3d/compare-eax-and 0/imm32/false
    16027     0f 85/jump-if-!= $populate-mu-function-header:error-loop/disp32
    16028     (slice-equal? %ecx "lookup")  # => eax
    16029     3d/compare-eax-and 0/imm32/false
    16030     0f 85/jump-if-!= $populate-mu-function-header:error-lookup/disp32
    16031     # save function name
    16032     (slice-to-string Heap %ecx %edi)  # Function-name
    16033     # save function inouts
    16034     {
    16035 $populate-mu-function-header:check-for-inout:
    16036       (next-mu-token *(ebp+8) %ecx)
    16037       # if slice-empty?(word-slice) abort
    16038       (slice-empty? %ecx)  # => eax
    16039       3d/compare-eax-and 0/imm32/false
    16040       0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
    16041       # if (word-slice == '{') goto done
    16042       (slice-equal? %ecx "{")   # => eax
    16043       3d/compare-eax-and 0/imm32/false
    16044       0f 85/jump-if-!= $populate-mu-function-header:done/disp32
    16045       # if (word-slice == '->') break
    16046       (slice-equal? %ecx "->")   # => eax
    16047       3d/compare-eax-and 0/imm32/false
    16048       0f 85/jump-if-!= break/disp32
    16049       # if (word-slice == '}') abort
    16050       (slice-equal? %ecx "}")   # => eax
    16051       3d/compare-eax-and 0/imm32/false
    16052       0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
    16053       # v = parse-var-with-type(word-slice, first-line)
    16054       (lookup *edi *(edi+4))  # Function-name Function-name => eax
    16055       (parse-var-with-type %ecx *(ebp+8) %ebx %eax *(ebp+0x14) *(ebp+0x18))
    16056       # if (v->register != null) abort
    16057       # . eax: (addr var) = lookup(v)
    16058       (lookup *ebx *(ebx+4))  # => eax
    16059       81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
    16060       0f 85/jump-if-!= $populate-mu-function-header:error2/disp32
    16061       # if function name is not "main"
    16062       #    and v->type contains an 'addr' anywhere except the start, abort
    16063       {
    16064         (lookup *edi *(edi+4))  # Function-name Function-name => eax
    16065         (string-equal? %eax "main")  # => eax
    16066         3d/compare-eax-and 0/imm32/false
    16067         75/jump-if-!= break/disp8
    16068         (lookup *ebx *(ebx+4))  # => eax
    16069         (addr-payload-contains-addr? %eax)  # => eax
    16070         3d/compare-eax-and 0/imm32/false
    16071         0f 85/jump-if-!= $populate-mu-function-header:error-nested-addr-inout/disp32
    16072       }
    16073       # v->block-depth is implicitly 0
    16074       #
    16075       # out->inouts = append(v, out->inouts)
    16076       8d/copy-address *(edi+8) 0/r32/eax  # Function-inouts
    16077       (append-list Heap  *ebx *(ebx+4)  *(edi+8) *(edi+0xc)  %eax)  # Function-inouts, Function-inouts
    16078       # push(vars, {v, false})
    16079       (push *(ebp+0x10) *ebx)
    16080       (push *(ebp+0x10) *(ebx+4))
    16081       (push *(ebp+0x10) 0)  # false
    16082       #
    16083       e9/jump loop/disp32
    16084     }
    16085     # save function outputs
    16086     {
    16087 $populate-mu-function-header:check-for-out:
    16088       (next-mu-token *(ebp+8) %ecx)
    16089       # if slice-empty?(word-slice) abort
    16090       (slice-empty? %ecx)  # => eax
    16091       3d/compare-eax-and 0/imm32/false
    16092       0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
    16093       # if (word-slice == '{') break
    16094       (slice-equal? %ecx "{")   # => eax
    16095       3d/compare-eax-and 0/imm32/false
    16096       0f 85/jump-if-!= break/disp32
    16097       # if (word-slice == '->') abort
    16098       (slice-equal? %ecx "->")   # => eax
    16099       3d/compare-eax-and 0/imm32/false
    16100       0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
    16101       # if (word-slice == '}') abort
    16102       (slice-equal? %ecx "}")   # => eax
    16103       3d/compare-eax-and 0/imm32/false
    16104       0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
    16105       # v = parse-var-with-type(word-slice, first-line)
    16106       (lookup *edi *(edi+4))  # Function-name Function-name => eax
    16107       (parse-var-with-type %ecx *(ebp+8) %ebx %eax *(ebp+0x14) *(ebp+0x18))
    16108       # assert(var->register != null)
    16109       # . eax: (addr var) = lookup(v)
    16110       (lookup *ebx *(ebx+4))  # => eax
    16111       81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
    16112       0f 84/jump-if-= $populate-mu-function-header:error3/disp32
    16113       # if (var->name != "_") abort
    16114       (lookup *eax *(eax+4))  # Var-name Var-name => eax
    16115       (string-equal? %eax "_")  # => eax
    16116       3d/compare-eax-and 0/imm32/false
    16117       0f 84/jump-if-= $populate-mu-function-header:error4/disp32
    16118       # if v->type is an addr, abort
    16119       (lookup *ebx *(ebx+4))  # => eax
    16120       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    16121       (mu-addr-type? %eax)  # => eax
    16122       3d/compare-eax-and 0/imm32/false
    16123       0f 85/jump-if-!= $populate-mu-function-header:error-addr-output/disp32
    16124       # out->outputs = append(v, out->outputs)
    16125       8d/copy-address *(edi+0x10) 0/r32/eax  # Function-outputs
    16126       (append-list Heap  *ebx *(ebx+4)  *(edi+0x10) *(edi+0x14)  %eax)  # Function-outputs, Function-outputs
    16127       #
    16128       e9/jump loop/disp32
    16129     }
    16130 $populate-mu-function-header:done:
    16131     (check-no-tokens-left *(ebp+8))
    16132 $populate-mu-function-header:end:
    16133     # . reclaim locals
    16134     81 0/subop/add %esp 0x10/imm32
    16135     # . restore registers
    16136     5f/pop-to-edi
    16137     5b/pop-to-ebx
    16138     5a/pop-to-edx
    16139     59/pop-to-ecx
    16140     58/pop-to-eax
    16141     # . epilogue
    16142     89/<- %esp 5/r32/ebp
    16143     5d/pop-to-ebp
    16144     c3/return
    16145
    16146 $populate-mu-function-header:error1:
    16147     # error("function header not in form 'fn <name> {'")
    16148     (write-buffered *(ebp+0x14) "function header not in form 'fn <name> [inouts] [-> outputs] {' -- '")
    16149     (flush *(ebp+0x14))
    16150     (rewind-stream *(ebp+8))
    16151     (write-stream-data *(ebp+0x14) *(ebp+8))
    16152     (write-buffered *(ebp+0x14) "'\n")
    16153     (flush *(ebp+0x14))
    16154     (stop *(ebp+0x18) 1)
    16155     # never gets here
    16156
    16157 $populate-mu-function-header:error2:
    16158     # error("fn " fn ": function inout '" var "' cannot be in a register")
    16159     (write-buffered *(ebp+0x14) "fn ")
    16160     50/push-eax
    16161     (lookup *edi *(edi+4))  # Function-name Function-name => eax
    16162     (write-buffered *(ebp+0x14) %eax)
    16163     58/pop-to-eax
    16164     (write-buffered *(ebp+0x14) ": function inout '")
    16165     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    16166     (write-buffered *(ebp+0x14) %eax)
    16167     (write-buffered *(ebp+0x14) "' cannot be in a register")
    16168     (flush *(ebp+0x14))
    16169     (stop *(ebp+0x18) 1)
    16170     # never gets here
    16171
    16172 $populate-mu-function-header:error3:
    16173     # error("fn " fn ": function output '" var "' must be in a register")
    16174     (write-buffered *(ebp+0x14) "fn ")
    16175     50/push-eax
    16176     (lookup *edi *(edi+4))  # Function-name Function-name => eax
    16177     (write-buffered *(ebp+0x14) %eax)
    16178     58/pop-to-eax
    16179     (write-buffered *(ebp+0x14) ": function output '")
    16180     (lookup *ebx *(ebx+4))  # => eax
    16181     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    16182     (write-buffered *(ebp+0x14) %eax)
    16183     (write-buffered *(ebp+0x14) "' must be in a register, in instruction '")
    16184     (rewind-stream *(ebp+8))
    16185     (write-stream-data *(ebp+0x14) *(ebp+8))
    16186     (write-buffered *(ebp+0x14) "'\n")
    16187     (flush *(ebp+0x14))
    16188     (stop *(ebp+0x18) 1)
    16189     # never gets here
    16190
    16191 $populate-mu-function-header:error4:
    16192     # error("fn " fn ": function outputs cannot be named; rename '" var "' in the header to '_'")
    16193     (write-buffered *(ebp+0x14) "fn ")
    16194     50/push-eax
    16195     (lookup *edi *(edi+4))  # Function-name Function-name => eax
    16196     (write-buffered *(ebp+0x14) %eax)
    16197     58/pop-to-eax
    16198     (write-buffered *(ebp+0x14) ": function outputs cannot be named; rename '")
    16199     (lookup *ebx *(ebx+4))  # => eax
    16200     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    16201     (write-buffered *(ebp+0x14) %eax)
    16202     (write-buffered *(ebp+0x14) "' in the header to '_'\n")
    16203     (flush *(ebp+0x14))
    16204     (stop *(ebp+0x18) 1)
    16205     # never gets here
    16206
    16207 $populate-mu-function-header:error-duplicate:
    16208     (write-buffered *(ebp+0x14) "fn ")
    16209     (write-slice-buffered *(ebp+0x14) %ecx)
    16210     (write-buffered *(ebp+0x14) " defined more than once\n")
    16211     (flush *(ebp+0x14))
    16212     (stop *(ebp+0x18) 1)
    16213     # never gets here
    16214
    16215 $populate-mu-function-header:error-break:
    16216     (write-buffered *(ebp+0x14) "Sorry, I've reserved all function names starting with 'break' for now. Please contact mu@akkartik.com.\n")
    16217     (flush *(ebp+0x14))
    16218     (stop *(ebp+0x18) 1)
    16219     # never gets here
    16220
    16221 $populate-mu-function-header:error-loop:
    16222     (write-buffered *(ebp+0x14) "Sorry, I've reserved all function names starting with 'loop' for now. Please contact mu@akkartik.com.\n")
    16223     (flush *(ebp+0x14))
    16224     (stop *(ebp+0x18) 1)
    16225     # never gets here
    16226
    16227 $populate-mu-function-header:error-lookup:
    16228     (write-buffered *(ebp+0x14) "cannot define a function called 'lookup'\n")
    16229     (flush *(ebp+0x14))
    16230     (stop *(ebp+0x18) 1)
    16231     # never gets here
    16232
    16233 $populate-mu-function-header:error-addr-output:
    16234     # error("fn " fn ": output cannot have an addr type; that could allow unsafe addresses to escape the function")
    16235     (write-buffered *(ebp+0x14) "fn ")
    16236     50/push-eax
    16237     (lookup *edi *(edi+4))  # Function-name Function-name => eax
    16238     (write-buffered *(ebp+0x14) %eax)
    16239     58/pop-to-eax
    16240     (write-buffered *(ebp+0x14) ": output cannot have an addr type; that could allow unsafe addresses to escape the function\n")
    16241     (flush *(ebp+0x14))
    16242     (stop *(ebp+0x18) 1)
    16243     # never gets here
    16244
    16245 $populate-mu-function-header:error-nested-addr-inout:
    16246     # error("fn " fn ": inout '" var "' cannot contain 'addr' anywhere in the type except the first word; that could allow unsafe addresses to escape the function")
    16247     (write-buffered *(ebp+0x14) "fn ")
    16248     (lookup *edi *(edi+4))  # Function-name Function-name => eax
    16249     (write-buffered *(ebp+0x14) %eax)
    16250     (write-buffered *(ebp+0x14) ": inout '")
    16251     (lookup *ebx *(ebx+4))  # => eax
    16252     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    16253     (write-buffered *(ebp+0x14) %eax)
    16254     (write-buffered *(ebp+0x14) "' cannot contain 'addr' anywhere in the type except the first word; that could allow unsafe addresses to escape the function\n")
    16255     (flush *(ebp+0x14))
    16256     (stop *(ebp+0x18) 1)
    16257     # never gets here
    16258
    16259 # scenarios considered:
    16260 # ✓ fn foo
    16261 # ✗ fn foo {
    16262 # ✓ fn foo x
    16263 # ✓ fn foo x: int
    16264 # ✓ fn foo x: int -> _/eax: int
    16265 # TODO:
    16266 #   disallow outputs of type `(... addr ...)`
    16267 #   disallow inputs of type `(... addr ... addr ...)`
    16268 populate-mu-function-signature:  # first-line: (addr stream byte), out: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    16269     # pseudocode:
    16270     #   var word-slice: slice
    16271     #   next-mu-token(first-line, word-slice)
    16272     #   assert(word-slice not in '{' '}' '->')
    16273     #   out->name = slice-to-string(word-slice)
    16274     #   ## inouts
    16275     #   while true
    16276     #     word-slice = next-mu-token(first-line)
    16277     #     if slice-empty?(word-slice) break
    16278     #     if (word-slice == '->') break
    16279     #     assert(word-slice not in '{' '}')
    16280     #     var v: (handle var) = parse-var-with-type(word-slice, first-line)
    16281     #     assert(v->register == null)
    16282     #     # v->block-depth is implicitly 0
    16283     #     out->inouts = append(v, out->inouts)
    16284     #   ## outputs
    16285     #   while true
    16286     #     word-slice = next-mu-token(first-line)
    16287     #     if slice-empty?(word-slice) break
    16288     #     assert(word-slice not in '{' '}' '->')
    16289     #     var v: (handle var) = parse-var-with-type(word-slice, first-line)
    16290     #     assert(v->register != null)
    16291     #     out->outputs = append(v, out->outputs)
    16292     #
    16293     # . prologue
    16294     55/push-ebp
    16295     89/<- %ebp 4/r32/esp
    16296     # . save registers
    16297     50/push-eax
    16298     51/push-ecx
    16299     52/push-edx
    16300     53/push-ebx
    16301     57/push-edi
    16302     # edi = out
    16303     8b/-> *(ebp+0xc) 7/r32/edi
    16304     # var word-slice/ecx: slice
    16305     68/push 0/imm32/end
    16306     68/push 0/imm32/start
    16307     89/<- %ecx 4/r32/esp
    16308     # var v/ebx: (handle var)
    16309     68/push 0/imm32
    16310     68/push 0/imm32
    16311     89/<- %ebx 4/r32/esp
    16312     # read function name
    16313     (next-mu-token *(ebp+8) %ecx)
    16314     # error checking
    16315     # if (word-slice == '{') abort
    16316     (slice-equal? %ecx "{")   # => eax
    16317     3d/compare-eax-and 0/imm32/false
    16318     0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
    16319     # if (word-slice == '->') abort
    16320     (slice-equal? %ecx "->")   # => eax
    16321     3d/compare-eax-and 0/imm32/false
    16322     0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
    16323     # if (word-slice == '}') abort
    16324     (slice-equal? %ecx "}")   # => eax
    16325     3d/compare-eax-and 0/imm32/false
    16326     0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
    16327     # if word-slice already defined, abort
    16328     (function-exists? %ecx)  # => eax
    16329     3d/compare-eax-and 0/imm32/false
    16330     0f 85/jump-if-!= $populate-mu-function-signature:error-duplicate/disp32
    16331     #
    16332     (slice-starts-with? %ecx "break")  # => eax
    16333     3d/compare-eax-and 0/imm32/false
    16334     0f 85/jump-if-!= $populate-mu-function-signature:error-break/disp32
    16335     (slice-starts-with? %ecx "loop")  # => eax
    16336     3d/compare-eax-and 0/imm32/false
    16337     0f 85/jump-if-!= $populate-mu-function-signature:error-loop/disp32
    16338     # save function name
    16339     (slice-to-string Heap %ecx %edi)  # Function-name
    16340     # save function inouts
    16341     {
    16342 $populate-mu-function-signature:check-for-inout:
    16343       (next-mu-token *(ebp+8) %ecx)
    16344       (slice-empty? %ecx)  # => eax
    16345       3d/compare-eax-and 0/imm32/false
    16346       0f 85/jump-if-!= break/disp32
    16347       # if (word-slice == '->') break
    16348       (slice-equal? %ecx "->")   # => eax
    16349       3d/compare-eax-and 0/imm32/false
    16350       0f 85/jump-if-!= break/disp32
    16351       # if (word-slice == '{') abort
    16352       (slice-equal? %ecx "{")   # => eax
    16353       3d/compare-eax-and 0/imm32/false
    16354       0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
    16355       # if (word-slice == '}') abort
    16356       (slice-equal? %ecx "}")   # => eax
    16357       3d/compare-eax-and 0/imm32/false
    16358       0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
    16359       # v = parse-var-with-type(word-slice, first-line)
    16360       (lookup *edi *(edi+4))  # Function-name Function-name => eax
    16361       (parse-var-with-type %ecx *(ebp+8) %ebx %eax *(ebp+0x10) *(ebp+0x14))
    16362       # if (v->register != null) abort
    16363       # . eax: (addr var) = lookup(v)
    16364       (lookup *ebx *(ebx+4))  # => eax
    16365       81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
    16366       0f 85/jump-if-!= $populate-mu-function-signature:error2/disp32
    16367       # if function name is not "main"
    16368       #    and v->type contains an 'addr' anywhere except the start, abort
    16369       {
    16370         (lookup *edi *(edi+4))  # Function-name Function-name => eax
    16371         (string-equal? %eax "main")  # => eax
    16372         3d/compare-eax-and 0/imm32/false
    16373         75/jump-if-!= break/disp8
    16374         (lookup *ebx *(ebx+4))  # => eax
    16375         (addr-payload-contains-addr? %eax)  # => eax
    16376         3d/compare-eax-and 0/imm32/false
    16377         0f 85/jump-if-!= $populate-mu-function-signature:error-nested-addr-inout/disp32
    16378       }
    16379       # assert(v->register == null)
    16380       # . eax: (addr var) = lookup(v)
    16381       (lookup *ebx *(ebx+4))  # => eax
    16382       81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
    16383       0f 85/jump-if-!= $populate-mu-function-signature:error2/disp32
    16384       # v->block-depth is implicitly 0
    16385       #
    16386       # out->inouts = append(v, out->inouts)
    16387       8d/copy-address *(edi+8) 0/r32/eax  # Function-inouts
    16388       (append-list Heap  *ebx *(ebx+4)  *(edi+8) *(edi+0xc)  %eax)  # Function-inouts, Function-inouts
    16389       #
    16390       e9/jump loop/disp32
    16391     }
    16392     # save function outputs
    16393     {
    16394 $populate-mu-function-signature:check-for-out:
    16395       (next-mu-token *(ebp+8) %ecx)
    16396       (slice-empty? %ecx)  # => eax
    16397       3d/compare-eax-and 0/imm32/false
    16398       0f 85/jump-if-!= break/disp32
    16399       # if (word-slice == '{') abort
    16400       (slice-equal? %ecx "{")   # => eax
    16401       3d/compare-eax-and 0/imm32/false
    16402       0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
    16403       # if (word-slice == '->') abort
    16404       (slice-equal? %ecx "->")   # => eax
    16405       3d/compare-eax-and 0/imm32/false
    16406       0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
    16407       # if (word-slice == '}') abort
    16408       (slice-equal? %ecx "}")   # => eax
    16409       3d/compare-eax-and 0/imm32/false
    16410       0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
    16411       # v = parse-var-with-type(word-slice, first-line)
    16412       (lookup *edi *(edi+4))  # Function-name Function-name => eax
    16413       (parse-var-with-type %ecx *(ebp+8) %ebx %eax *(ebp+0x10) *(ebp+0x14))
    16414       # assert(var->register != null)
    16415       # . eax: (addr var) = lookup(v)
    16416       (lookup *ebx *(ebx+4))  # => eax
    16417       81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
    16418       0f 84/jump-if-= $populate-mu-function-signature:error3/disp32
    16419       # if (var->name != "_") abort
    16420       (lookup *eax *(eax+4))  # Var-name Var-name => eax
    16421       (string-equal? %eax "_")  # => eax
    16422       3d/compare-eax-and 0/imm32/false
    16423       0f 84/jump-if-= $populate-mu-function-signature:error4/disp32
    16424       # if function name is not "lookup"
    16425       #    and v->type is an addr, abort
    16426       {
    16427         (lookup *edi *(edi+4))  # Function-name Function-name => eax
    16428         (string-equal? %eax "lookup")  # => eax
    16429         3d/compare-eax-and 0/imm32/false
    16430         75/jump-if-!= break/disp8
    16431         (lookup *ebx *(ebx+4))  # => eax
    16432         (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    16433         (mu-addr-type? %eax)  # => eax
    16434         3d/compare-eax-and 0/imm32/false
    16435         0f 85/jump-if-!= $populate-mu-function-signature:error-addr-output/disp32
    16436       }
    16437       # out->outputs = append(v, out->outputs)
    16438       8d/copy-address *(edi+0x10) 0/r32/eax  # Function-outputs
    16439       (append-list Heap  *ebx *(ebx+4)  *(edi+0x10) *(edi+0x14)  %eax)  # Function-outputs, Function-outputs
    16440       #
    16441       e9/jump loop/disp32
    16442     }
    16443 $populate-mu-function-signature:done:
    16444     (check-no-tokens-left *(ebp+8))
    16445 $populate-mu-function-signature:end:
    16446     # . reclaim locals
    16447     81 0/subop/add %esp 0x10/imm32
    16448     # . restore registers
    16449     5f/pop-to-edi
    16450     5b/pop-to-ebx
    16451     5a/pop-to-edx
    16452     59/pop-to-ecx
    16453     58/pop-to-eax
    16454     # . epilogue
    16455     89/<- %esp 5/r32/ebp
    16456     5d/pop-to-ebp
    16457     c3/return
    16458
    16459 $populate-mu-function-signature:error1:
    16460     # error("function signature not in form 'fn <name> {'")
    16461     (write-buffered *(ebp+0x10) "function signature not in form 'fn <name> [inouts] [-> outputs] {' -- '")
    16462     (flush *(ebp+0x10))
    16463     (rewind-stream *(ebp+8))
    16464     (write-stream-data *(ebp+0x10) *(ebp+8))
    16465     (write-buffered *(ebp+0x10) "'\n")
    16466     (flush *(ebp+0x10))
    16467     (stop *(ebp+0x14) 1)
    16468     # never gets here
    16469
    16470 $populate-mu-function-signature:error2:
    16471     # error("fn " fn ": function inout '" var "' cannot be in a register")
    16472     (write-buffered *(ebp+0x10) "fn ")
    16473     50/push-eax
    16474     (lookup *edi *(edi+4))  # Function-name Function-name => eax
    16475     (write-buffered *(ebp+0x10) %eax)
    16476     58/pop-to-eax
    16477     (write-buffered *(ebp+0x10) ": function inout '")
    16478     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    16479     (write-buffered *(ebp+0x10) %eax)
    16480     (write-buffered *(ebp+0x10) "' cannot be in a register")
    16481     (flush *(ebp+0x10))
    16482     (stop *(ebp+0x14) 1)
    16483     # never gets here
    16484
    16485 $populate-mu-function-signature:error3:
    16486     # error("fn " fn ": function output '" var "' must be in a register")
    16487     (write-buffered *(ebp+0x10) "fn ")
    16488     50/push-eax
    16489     (lookup *edi *(edi+4))  # Function-name Function-name => eax
    16490     (write-buffered *(ebp+0x10) %eax)
    16491     58/pop-to-eax
    16492     (write-buffered *(ebp+0x10) ": function output '")
    16493     (lookup *ebx *(ebx+4))  # => eax
    16494     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    16495     (write-buffered *(ebp+0x10) %eax)
    16496     (write-buffered *(ebp+0x10) "' must be in a register, in instruction '")
    16497     (rewind-stream *(ebp+8))
    16498     (write-stream-data *(ebp+0x10) *(ebp+8))
    16499     (write-buffered *(ebp+0x10) "'\n")
    16500     (flush *(ebp+0x10))
    16501     (stop *(ebp+0x14) 1)
    16502     # never gets here
    16503
    16504 $populate-mu-function-signature:error4:
    16505     # error("fn " fn ": function outputs cannot be named; rename '" var "' in the header to '_'")
    16506     (write-buffered *(ebp+0x10) "fn ")
    16507     50/push-eax
    16508     (lookup *edi *(edi+4))  # Function-name Function-name => eax
    16509     (write-buffered *(ebp+0x10) %eax)
    16510     58/pop-to-eax
    16511     (write-buffered *(ebp+0x10) ": function outputs cannot be named; rename '")
    16512     (lookup *ebx *(ebx+4))  # => eax
    16513     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    16514     (write-buffered *(ebp+0x10) %eax)
    16515     (write-buffered *(ebp+0x10) "' in the header to '_'\n")
    16516     (flush *(ebp+0x10))
    16517     (stop *(ebp+0x14) 1)
    16518     # never gets here
    16519
    16520 $populate-mu-function-signature:error-duplicate:
    16521     (write-buffered *(ebp+0x10) "fn ")
    16522     (write-slice-buffered *(ebp+0x10) %ecx)
    16523     (write-buffered *(ebp+0x10) " defined more than once\n")
    16524     (flush *(ebp+0x10))
    16525     (stop *(ebp+0x14) 1)
    16526     # never gets here
    16527
    16528 $populate-mu-function-signature:error-break:
    16529     (write-buffered *(ebp+0x10) "Sorry, I've reserved all function names starting with 'break' for now. Please contact mu@akkartik.com.\n")
    16530     (flush *(ebp+0x10))
    16531     (stop *(ebp+0x14) 1)
    16532     # never gets here
    16533
    16534 $populate-mu-function-signature:error-loop:
    16535     (write-buffered *(ebp+0x10) "Sorry, I've reserved all function names starting with 'loop' for now. Please contact mu@akkartik.com.\n")
    16536     (flush *(ebp+0x10))
    16537     (stop *(ebp+0x14) 1)
    16538     # never gets here
    16539
    16540 $populate-mu-function-signature:error-addr-output:
    16541     # error("fn " fn ": output cannot have an addr type; that could allow unsafe addresses to escape the function")
    16542     (write-buffered *(ebp+0x10) "fn ")
    16543     50/push-eax
    16544     (lookup *edi *(edi+4))  # Function-name Function-name => eax
    16545     (write-buffered *(ebp+0x10) %eax)
    16546     58/pop-to-eax
    16547     (write-buffered *(ebp+0x10) ": output cannot have an addr type; that could allow unsafe addresses to escape the function\n")
    16548     (flush *(ebp+0x10))
    16549     (stop *(ebp+0x14) 1)
    16550     # never gets here
    16551
    16552 $populate-mu-function-signature:error-nested-addr-inout:
    16553     # error("fn " fn ": inout '" var "' cannot contain 'addr' anywhere in the type except the first word; that could allow unsafe addresses to escape the function")
    16554     (write-buffered *(ebp+0x10) "fn ")
    16555     (lookup *edi *(edi+4))  # Function-name Function-name => eax
    16556     (write-buffered *(ebp+0x10) %eax)
    16557     (write-buffered *(ebp+0x10) ": inout '")
    16558     (lookup *ebx *(ebx+4))  # => eax
    16559     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    16560     (write-buffered *(ebp+0x10) %eax)
    16561     (write-buffered *(ebp+0x10) "' cannot contain 'addr' anywhere in the type except the first word; that could allow unsafe addresses to escape the function\n")
    16562     (flush *(ebp+0x10))
    16563     (stop *(ebp+0x14) 1)
    16564     # never gets here
    16565
    16566 addr-payload-contains-addr?:  # v: (addr var) -> result/eax: boolean
    16567     # . prologue
    16568     55/push-ebp
    16569     89/<- %ebp 4/r32/esp
    16570     # var t/eax: (addr type-tree) = v->type
    16571     8b/-> *(ebp+8) 0/r32/eax
    16572     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    16573     # if t->right contains addr, return true
    16574     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
    16575     (type-tree-contains? %eax 2)  # addr => eax
    16576     # we don't have to look at t->left as long as it's guaranteed to be an atom
    16577 $addr-payload-contains-addr?:end:
    16578     # . epilogue
    16579     89/<- %esp 5/r32/ebp
    16580     5d/pop-to-ebp
    16581     c3/return
    16582
    16583 type-tree-contains?:  # t: (addr type-tree), n: type-id -> result/eax: boolean
    16584     # . prologue
    16585     55/push-ebp
    16586     89/<- %ebp 4/r32/esp
    16587     # . save registers
    16588     51/push-ecx
    16589     # if t is null, return false
    16590     8b/-> *(ebp+8) 0/r32/eax
    16591     3d/compare-eax-and 0/imm32
    16592     0f 84/jump-if-= $type-tree-contains?:end/disp32  # eax changes type
    16593     # if t is an atom, return (t->value == n)
    16594     81 7/subop/compare *eax 0/imm32/false
    16595     {
    16596       74/jump-if-= break/disp8
    16597       8b/-> *(ebp+0xc) 1/r32/ecx
    16598       39/compare *(eax+4) 1/r32/ecx  # Type-tree-value
    16599       0f 94/set-if-= %al
    16600       81 4/subop/and %eax 0xff/imm32
    16601       eb/jump $type-tree-contains?:end/disp8
    16602     }
    16603     # if t->left contains n, return true
    16604     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    16605     (type-tree-contains? %eax *(ebp+0xc))  # => eax
    16606     3d/compare-eax-and 0/imm32/false
    16607     75/jump-if-!= $type-tree-contains?:end/disp8
    16608     # otherwise return whether t->right contains n
    16609     8b/-> *(ebp+8) 0/r32/eax
    16610     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
    16611     (type-tree-contains? %eax *(ebp+0xc))  # => eax
    16612 $type-tree-contains?:end:
    16613     # . restore registers
    16614     59/pop-to-ecx
    16615     # . epilogue
    16616     89/<- %esp 5/r32/ebp
    16617     5d/pop-to-ebp
    16618     c3/return
    16619
    16620 function-exists?:  # s: (addr slice) -> result/eax: boolean
    16621     # . prologue
    16622     55/push-ebp
    16623     89/<- %ebp 4/r32/esp
    16624     # . save registers
    16625     51/push-ecx
    16626     # var curr/ecx: (addr function) = functions
    16627     (lookup *_Program-functions *_Program-functions->payload)  # => eax
    16628     89/<- %ecx 0/r32/eax
    16629     {
    16630       # if (curr == null) break
    16631       81 7/subop/compare %ecx 0/imm32
    16632       74/jump-if-= break/disp8
    16633       # if (curr->name == s) return true
    16634       {
    16635         (lookup *ecx *(ecx+4))  # Function-name Function-name => eax
    16636         (slice-equal? *(ebp+8) %eax)  # => eax
    16637         3d/compare-eax-and 0/imm32/false
    16638         74/jump-if-= break/disp8
    16639         b8/copy-to-eax 1/imm32/true
    16640         e9/jump $function-exists?:end/disp32
    16641       }
    16642       # curr = curr->next
    16643       (lookup *(ecx+0x20) *(ecx+0x24))  # Function-next Function-next => eax
    16644       89/<- %ecx 0/r32/eax
    16645       #
    16646       eb/jump loop/disp8
    16647     }
    16648     # var curr/ecx: (addr function) = signatures
    16649     (lookup *_Program-signatures *_Program-signatures->payload)  # => eax
    16650     89/<- %ecx 0/r32/eax
    16651     {
    16652       # if (curr == null) break
    16653       81 7/subop/compare %ecx 0/imm32
    16654       74/jump-if-= break/disp8
    16655       # if (curr->name == s) return true
    16656       {
    16657         (lookup *ecx *(ecx+4))  # Function-name Function-name => eax
    16658         (slice-equal? *(ebp+8) %eax)  # => eax
    16659         3d/compare-eax-and 0/imm32/false
    16660         74/jump-if-= break/disp8
    16661         b8/copy-to-eax 1/imm32/true
    16662         eb/jump $function-exists?:end/disp8
    16663       }
    16664       # curr = curr->next
    16665       (lookup *(ecx+0x20) *(ecx+0x24))  # Function-next Function-next => eax
    16666       89/<- %ecx 0/r32/eax
    16667       #
    16668       eb/jump loop/disp8
    16669     }
    16670     # return false
    16671     b8/copy-to-eax 0/imm32/false
    16672 $function-exists?:end:
    16673     # . restore registers
    16674     59/pop-to-ecx
    16675     # . epilogue
    16676     89/<- %esp 5/r32/ebp
    16677     5d/pop-to-ebp
    16678     c3/return
    16679
    16680 test-function-header-with-arg:
    16681     # . prologue
    16682     55/push-ebp
    16683     89/<- %ebp 4/r32/esp
    16684     # setup
    16685     8b/-> *Primitive-type-ids 0/r32/eax
    16686     89/<- *Type-id 0/r32/eax  # stream-write
    16687     c7 0/subop/copy *_Program-functions 0/imm32
    16688     c7 0/subop/copy *_Program-functions->payload 0/imm32
    16689     c7 0/subop/copy *_Program-types 0/imm32
    16690     c7 0/subop/copy *_Program-types->payload 0/imm32
    16691     c7 0/subop/copy *_Program-signatures 0/imm32
    16692     c7 0/subop/copy *_Program-signatures->payload 0/imm32
    16693     (clear-stream _test-input-stream)
    16694     (write _test-input-stream "foo n: int {\n")
    16695     # var result/ecx: function
    16696     2b/subtract *Function-size 4/r32/esp
    16697     89/<- %ecx 4/r32/esp
    16698     (zero-out %ecx *Function-size)
    16699     # var vars/ebx: (stack live-var 16)
    16700     81 5/subop/subtract %esp 0xc0/imm32
    16701     68/push 0xc0/imm32/size
    16702     68/push 0/imm32/top
    16703     89/<- %ebx 4/r32/esp
    16704     # convert
    16705     (populate-mu-function-header _test-input-stream %ecx %ebx Stderr 0)
    16706     # check result->name
    16707     (lookup *ecx *(ecx+4))  # Function-name Function-name => eax
    16708     (check-strings-equal %eax "foo" "F - test-function-header-with-arg/name")
    16709     # var v/edx: (addr var) = result->inouts->value
    16710     (lookup *(ecx+8) *(ecx+0xc))  # Function-inouts Function-inouts => eax
    16711     (lookup *eax *(eax+4))  # List-value List-value => eax
    16712     89/<- %edx 0/r32/eax
    16713     # check v->name
    16714     (lookup *edx *(edx+4))  # Var-name Var-name => eax
    16715     (check-strings-equal %eax "n" "F - test-function-header-with-arg/inout:0")
    16716     # check v->type
    16717     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
    16718     (check-ints-equal *eax 1 "F - test-function-header-with-arg/inout:0/type:0")  # Type-tree-is-atom
    16719     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-arg/inout:0/type:1")  # Type-tree-value
    16720     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-arg/inout:0/type:2")  # Type-tree-right
    16721     # . epilogue
    16722     89/<- %esp 5/r32/ebp
    16723     5d/pop-to-ebp
    16724     c3/return
    16725
    16726 test-function-header-with-multiple-args:
    16727     # . prologue
    16728     55/push-ebp
    16729     89/<- %ebp 4/r32/esp
    16730     # setup
    16731     8b/-> *Primitive-type-ids 0/r32/eax
    16732     89/<- *Type-id 0/r32/eax  # stream-write
    16733     c7 0/subop/copy *_Program-functions 0/imm32
    16734     c7 0/subop/copy *_Program-functions->payload 0/imm32
    16735     c7 0/subop/copy *_Program-types 0/imm32
    16736     c7 0/subop/copy *_Program-types->payload 0/imm32
    16737     c7 0/subop/copy *_Program-signatures 0/imm32
    16738     c7 0/subop/copy *_Program-signatures->payload 0/imm32
    16739     (clear-stream _test-input-stream)
    16740     (write _test-input-stream "foo a: int, b: int c: int {\n")
    16741     # result/ecx: function
    16742     2b/subtract *Function-size 4/r32/esp
    16743     89/<- %ecx 4/r32/esp
    16744     (zero-out %ecx *Function-size)
    16745     # var vars/ebx: (stack live-var 16)
    16746     81 5/subop/subtract %esp 0xc0/imm32
    16747     68/push 0xc0/imm32/size
    16748     68/push 0/imm32/top
    16749     89/<- %ebx 4/r32/esp
    16750     # convert
    16751     (populate-mu-function-header _test-input-stream %ecx %ebx Stderr 0)
    16752     # check result->name
    16753     (lookup *ecx *(ecx+4))  # Function-name Function-name => eax
    16754     (check-strings-equal %eax "foo" "F - test-function-header-with-multiple-args/name")
    16755     # var inouts/edx: (addr list var) = lookup(result->inouts)
    16756     (lookup *(ecx+8) *(ecx+0xc))  # Function-inouts Function-inouts => eax
    16757     89/<- %edx 0/r32/eax
    16758 $test-function-header-with-multiple-args:inout0:
    16759     # var v/ebx: (addr var) = lookup(inouts->value)
    16760     (lookup *edx *(edx+4))  # List-value List-value => eax
    16761     89/<- %ebx 0/r32/eax
    16762     # check v->name
    16763     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
    16764     (check-strings-equal %eax "a" "F - test-function-header-with-multiple-args/inout:0")  # Var-name
    16765     # check v->type
    16766     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
    16767     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args/inout:0/type:0")  # Type-tree-is-atom
    16768     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args/inout:0/type:1")  # Type-tree-value
    16769     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args/inout:0/type:2")  # Type-tree-right
    16770 $test-function-header-with-multiple-args:inout1:
    16771     # inouts = lookup(inouts->next)
    16772     (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
    16773     89/<- %edx 0/r32/eax
    16774     # v = lookup(inouts->value)
    16775     (lookup *edx *(edx+4))  # List-value List-value => eax
    16776     89/<- %ebx 0/r32/eax
    16777     # check v->name
    16778     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
    16779     (check-strings-equal %eax "b" "F - test-function-header-with-multiple-args/inout:1")  # Var-name
    16780     # check v->type
    16781     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
    16782     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args/inout:1/type:0")  # Type-tree-is-atom
    16783     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args/inout:1/type:1")  # Type-tree-value
    16784     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args/inout:1/type:2")  # Type-tree-right
    16785 $test-function-header-with-multiple-args:inout2:
    16786     # inouts = lookup(inouts->next)
    16787     (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
    16788     89/<- %edx 0/r32/eax
    16789     # v = lookup(inouts->value)
    16790     (lookup *edx *(edx+4))  # List-value List-value => eax
    16791     89/<- %ebx 0/r32/eax
    16792     # check v->name
    16793     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
    16794     (check-strings-equal %eax "c" "F - test-function-header-with-multiple-args/inout:2")  # Var-name
    16795     # check v->type
    16796     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
    16797     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args/inout:2/type:0")  # Type-tree-is-atom
    16798     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args/inout:2/type:1")  # Type-tree-value
    16799     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args/inout:2/type:2")  # Type-tree-right
    16800     # . epilogue
    16801     89/<- %esp 5/r32/ebp
    16802     5d/pop-to-ebp
    16803     c3/return
    16804
    16805 test-function-header-with-multiple-args-and-outputs:
    16806     # . prologue
    16807     55/push-ebp
    16808     89/<- %ebp 4/r32/esp
    16809     # setup
    16810     8b/-> *Primitive-type-ids 0/r32/eax
    16811     89/<- *Type-id 0/r32/eax  # stream-write
    16812     c7 0/subop/copy *_Program-functions 0/imm32
    16813     c7 0/subop/copy *_Program-functions->payload 0/imm32
    16814     c7 0/subop/copy *_Program-types 0/imm32
    16815     c7 0/subop/copy *_Program-types->payload 0/imm32
    16816     c7 0/subop/copy *_Program-signatures 0/imm32
    16817     c7 0/subop/copy *_Program-signatures->payload 0/imm32
    16818     (clear-stream _test-input-stream)
    16819     (write _test-input-stream "foo a: int, b: int, c: int -> _/ecx: int _/edx: int {\n")
    16820     # result/ecx: function
    16821     2b/subtract *Function-size 4/r32/esp
    16822     89/<- %ecx 4/r32/esp
    16823     (zero-out %ecx *Function-size)
    16824     # var vars/ebx: (stack live-var 16)
    16825     81 5/subop/subtract %esp 0xc0/imm32
    16826     68/push 0xc0/imm32/size
    16827     68/push 0/imm32/top
    16828     89/<- %ebx 4/r32/esp
    16829     # convert
    16830     (populate-mu-function-header _test-input-stream %ecx %ebx Stderr 0)
    16831     # check result->name
    16832     (lookup *ecx *(ecx+4))  # Function-name Function-name => eax
    16833     (check-strings-equal %eax "foo" "F - test-function-header-with-multiple-args-and-outputs/name")
    16834     # var inouts/edx: (addr list var) = lookup(result->inouts)
    16835     (lookup *(ecx+8) *(ecx+0xc))  # Function-inouts Function-inouts => eax
    16836     89/<- %edx 0/r32/eax
    16837 $test-function-header-with-multiple-args-and-outputs:inout0:
    16838     # var v/ebx: (addr var) = lookup(inouts->value)
    16839     (lookup *edx *(edx+4))  # List-value List-value => eax
    16840     89/<- %ebx 0/r32/eax
    16841     # check v->name
    16842     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
    16843     (check-strings-equal %eax "a" "F - test-function-header-with-multiple-args-and-outputs/inout:0")
    16844     # check v->type
    16845     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
    16846     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args-and-outputs/inout:0/type:0")  # Type-tree-is-atom
    16847     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args-and-outputs/inout:0/type:1")  # Type-tree-value
    16848     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args-and-outputs/inout:0/type:2")  # Type-tree-right
    16849 $test-function-header-with-multiple-args-and-outputs:inout1:
    16850     # inouts = lookup(inouts->next)
    16851     (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
    16852     89/<- %edx 0/r32/eax
    16853     # v = lookup(inouts->value)
    16854     (lookup *edx *(edx+4))  # List-value List-value => eax
    16855     89/<- %ebx 0/r32/eax
    16856     # check v->name
    16857     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
    16858     (check-strings-equal %eax "b" "F - test-function-header-with-multiple-args-and-outputs/inout:1")
    16859     # check v->type
    16860     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
    16861     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args-and-outputs/inout:1/type:0")  # Type-tree-is-atom
    16862     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args-and-outputs/inout:1/type:1")  # Type-tree-value
    16863     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args-and-outputs/inout:1/type:2")  # Type-tree-right
    16864 $test-function-header-with-multiple-args-and-outputs:inout2:
    16865     # inouts = lookup(inouts->next)
    16866     (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
    16867     89/<- %edx 0/r32/eax
    16868     # v = lookup(inouts->value)
    16869     (lookup *edx *(edx+4))  # List-value List-value => eax
    16870     89/<- %ebx 0/r32/eax
    16871     # check v->name
    16872     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
    16873     (check-strings-equal %eax "c" "F - test-function-header-with-multiple-args-and-outputs/inout:2")
    16874     # check v->type
    16875     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
    16876     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args-and-outputs/inout:2/type:0")  # Type-tree-is-atom
    16877     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args-and-outputs/inout:2/type:1")  # Type-tree-value
    16878     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args-and-outputs/inout:2/type:2")  # Type-tree-right
    16879 $test-function-header-with-multiple-args-and-outputs:out0:
    16880     # var outputs/edx: (addr list var) = lookup(result->outputs)
    16881     (lookup *(ecx+0x10) *(ecx+0x14))  # Function-outputs Function-outputs => eax
    16882     89/<- %edx 0/r32/eax
    16883     # v = lookup(outputs->value)
    16884     (lookup *edx *(edx+4))  # List-value List-value => eax
    16885     89/<- %ebx 0/r32/eax
    16886     # check v->name
    16887     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
    16888     (check-strings-equal %eax "_" "F - test-function-header-with-multiple-args-and-outputs/output:0")
    16889     # check v->register
    16890     (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
    16891     (check-strings-equal %eax "ecx" "F - test-function-header-with-multiple-args-and-outputs/output:0/register")
    16892     # check v->type
    16893     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
    16894     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args-and-outputs/output:0/type:0")  # Type-tree-is-atom
    16895     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args-and-outputs/output:0/type:1")  # Type-tree-value
    16896     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args-and-outputs/output:0/type:2")  # Type-tree-right
    16897 $test-function-header-with-multiple-args-and-outputs:out1:
    16898     # outputs = lookup(outputs->next)
    16899     (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
    16900     89/<- %edx 0/r32/eax
    16901     # v = lookup(inouts->value)
    16902     (lookup *edx *(edx+4))  # List-value List-value => eax
    16903     89/<- %ebx 0/r32/eax
    16904     # check v->name
    16905     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
    16906     (check-strings-equal %eax "_" "F - test-function-header-with-multiple-args-and-outputs/output:1")
    16907     # check v->register
    16908     (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
    16909     (check-strings-equal %eax "edx" "F - test-function-header-with-multiple-args-and-outputs/output:1/register")
    16910     # check v->type
    16911     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
    16912     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args-and-outputs/output:1/type:0")  # Type-tree-is-atom
    16913     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args-and-outputs/output:1/type:1")  # Type-tree-value
    16914     (check-ints-equal *(eax+0c) 0 "F - test-function-header-with-multiple-args-and-outputs/output:1/type:2")  # Type-tree-right
    16915     # . epilogue
    16916     89/<- %esp 5/r32/ebp
    16917     5d/pop-to-ebp
    16918     c3/return
    16919
    16920 # format for variables with types
    16921 #   x: int
    16922 #   x: int,
    16923 #   x/eax: int
    16924 #   x/eax: int,
    16925 # ignores at most one trailing comma
    16926 # does not support other, non-register metadata
    16927 # WARNING: modifies name
    16928 parse-var-with-type:  # name: (addr slice), first-line: (addr stream byte), out: (addr handle var), fn-name: (addr array byte), err: (addr buffered-file), ed: (addr exit-descriptor)
    16929     # pseudocode:
    16930     #   var s: slice
    16931     #   if (!slice-ends-with(name, ":"))
    16932     #     abort
    16933     #   --name->end to skip ':'
    16934     #   next-token-from-slice(name->start, name->end, '/', s)
    16935     #   new-var-from-slice(s, out)
    16936     #   ## register
    16937     #   next-token-from-slice(s->end, name->end, '/', s)
    16938     #   if (!slice-empty?(s))
    16939     #     out->register = slice-to-string(s)
    16940     #   ## type
    16941     #   var type: (handle type-tree) = parse-type(first-line)
    16942     #   out->type = type
    16943     #
    16944     # . prologue
    16945     55/push-ebp
    16946     89/<- %ebp 4/r32/esp
    16947     # . save registers
    16948     50/push-eax
    16949     51/push-ecx
    16950     52/push-edx
    16951     53/push-ebx
    16952     56/push-esi
    16953     57/push-edi
    16954     # esi = name
    16955     8b/-> *(ebp+8) 6/r32/esi
    16956     # if (!slice-ends-with?(name, ":")) abort
    16957     8b/-> *(esi+4) 1/r32/ecx  # Slice-end
    16958     49/decrement-ecx
    16959     8a/copy-byte *ecx 1/r32/CL
    16960     81 4/subop/and %ecx 0xff/imm32
    16961     81 7/subop/compare %ecx 0x3a/imm32/colon
    16962     0f 85/jump-if-!= $parse-var-with-type:abort/disp32
    16963     # --name->end to skip ':'
    16964     ff 1/subop/decrement *(esi+4)
    16965     # var s/ecx: slice
    16966     68/push 0/imm32/end
    16967     68/push 0/imm32/start
    16968     89/<- %ecx 4/r32/esp
    16969 $parse-var-with-type:parse-name:
    16970     (next-token-from-slice *esi *(esi+4) 0x2f %ecx)  # Slice-start, Slice-end, '/'
    16971 $parse-var-with-type:create-var:
    16972     # new-var-from-slice(s, out)
    16973     (new-var-from-slice Heap %ecx *(ebp+0x10))
    16974     # save out->register
    16975 $parse-var-with-type:save-register:
    16976     # . var out-addr/edi: (addr var) = lookup(*out)
    16977     8b/-> *(ebp+0x10) 7/r32/edi
    16978     (lookup *edi *(edi+4))  # => eax
    16979     89/<- %edi 0/r32/eax
    16980     # . s = next-token(...)
    16981     (next-token-from-slice *(ecx+4) *(esi+4) 0x2f %ecx)  # s->end, name->end, '/'
    16982     # . if (!slice-empty?(s)) out->register = slice-to-string(s)
    16983     {
    16984 $parse-var-with-type:write-register:
    16985       (slice-empty? %ecx)  # => eax
    16986       3d/compare-eax-and 0/imm32/false
    16987       75/jump-if-!= break/disp8
    16988       # out->register = slice-to-string(s)
    16989       8d/copy-address *(edi+0x18) 0/r32/eax  # Var-register
    16990       (slice-to-string Heap %ecx %eax)
    16991     }
    16992 $parse-var-with-type:save-type:
    16993     8d/copy-address *(edi+8) 0/r32/eax  # Var-type
    16994     (parse-type Heap *(ebp+0xc) %eax *(ebp+0x18) *(ebp+0x1c))
    16995 $parse-var-with-type:check-register:
    16996     (lookup *(edi+0x18) *(edi+0x1c))  # Var-register Var-register => eax
    16997     3d/compare-eax-and 0/imm32
    16998     74/jump-if-= $parse-var-with-type:end/disp8
    16999     (float-register? %eax)  # => eax
    17000     {
    17001       3d/compare-eax-and 0/imm32/false
    17002       74/jump-if-= break/disp8
    17003       # var is in a float register; ensure type is float
    17004       (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
    17005       (simple-mu-type? %eax 0xf)  # float => eax
    17006       3d/compare-eax-and 0/imm32/false
    17007       0f 84/jump-if-= $parse-var-with-type:error-non-float-in-floating-point-register/disp32
    17008       eb/jump $parse-var-with-type:end/disp8
    17009     }
    17010     # var is not in a float register; ensure type is not float
    17011     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
    17012     (simple-mu-type? %eax 0xf)  # float => eax
    17013     3d/compare-eax-and 0/imm32/false
    17014     0f 85/jump-if-!= $parse-var-with-type:error-float-in-integer-register/disp32
    17015 $parse-var-with-type:end:
    17016     # . reclaim locals
    17017     81 0/subop/add %esp 8/imm32
    17018     # . restore registers
    17019     5f/pop-to-edi
    17020     5e/pop-to-esi
    17021     5b/pop-to-ebx
    17022     5a/pop-to-edx
    17023     59/pop-to-ecx
    17024     58/pop-to-eax
    17025     # . epilogue
    17026     89/<- %esp 5/r32/ebp
    17027     5d/pop-to-ebp
    17028     c3/return
    17029
    17030 $parse-var-with-type:abort:
    17031     # error("fn " fn ": var should have form 'name: type' in '" line "'\n")
    17032     (write-buffered *(ebp+0x18) "fn ")
    17033     (write-buffered *(ebp+0x18) *(ebp+0x14))
    17034     (write-buffered *(ebp+0x18) ": var should have form 'name: type' in '")
    17035     (flush *(ebp+0x18))
    17036     (rewind-stream *(ebp+0xc))
    17037     (write-stream-data *(ebp+0x18) *(ebp+0xc))
    17038     (write-buffered *(ebp+0x18) "'\n")
    17039     (flush *(ebp+0x18))
    17040     (stop *(ebp+0x1c) 1)
    17041     # never gets here
    17042
    17043 $parse-var-with-type:error-float-in-integer-register:
    17044     # error("fn " fn ": float var '" var "' should be in a floating-point register\n")
    17045     (write-buffered *(ebp+0x18) "fn ")
    17046     (write-buffered *(ebp+0x18) *(ebp+0x14))
    17047     (write-buffered *(ebp+0x18) ": float var '")
    17048     (lookup *edi *(edi+4))  # Var-name Var-name => eax
    17049     (write-buffered *(ebp+0x18) %eax)
    17050     (write-buffered *(ebp+0x18) "' should be in a floating-point register\n")
    17051     (flush *(ebp+0x18))
    17052     (stop *(ebp+0x1c) 1)
    17053     # never gets here
    17054
    17055 $parse-var-with-type:error-non-float-in-floating-point-register:
    17056     # error("fn " fn ": non-float var '" var "' should be in an integer register\n")
    17057     (write-buffered *(ebp+0x18) "fn ")
    17058     (write-buffered *(ebp+0x18) *(ebp+0x14))
    17059     (write-buffered *(ebp+0x18) ": non-float var '")
    17060     (lookup *edi *(edi+4))  # Var-name Var-name => eax
    17061     (write-buffered *(ebp+0x18) %eax)
    17062     (write-buffered *(ebp+0x18) "' should be in an integer register\n")
    17063     (flush *(ebp+0x18))
    17064     (stop *(ebp+0x1c) 1)
    17065     # never gets here
    17066
    17067 float-register?:  # r: (addr array byte) -> result/eax: boolean
    17068     # . prologue
    17069     55/push-ebp
    17070     89/<- %ebp 4/r32/esp
    17071     #
    17072     (get Mu-registers-unique *(ebp+8) 0xc "Mu-registers-unique")  # => eax
    17073     81 7/subop/compare *eax 8/imm32/start-of-floating-point-registers
    17074     0f 9d/set-if->= %al
    17075     81 4/subop/and %eax 0xff/imm32
    17076 $float-register?:end:
    17077     # . epilogue
    17078     89/<- %esp 5/r32/ebp
    17079     5d/pop-to-ebp
    17080     c3/return
    17081
    17082 parse-type:  # ad: (addr allocation-descriptor), in: (addr stream byte), out: (addr handle type-tree), err: (addr buffered-file), ed: (addr exit-descriptor)
    17083     # pseudocode:
    17084     #   var s: slice = next-mu-token(in)
    17085     #   assert s != ""
    17086     #   assert s != "->"
    17087     #   assert s != "{"
    17088     #   assert s != "}"
    17089     #   if s == ")"
    17090     #     return
    17091     #   out = allocate(Type-tree)
    17092     #   if s != "("
    17093     #     HACK: if s is an int, parse and return it
    17094     #     out->is-atom? = true
    17095     #     if (s[0] == "_")
    17096     #       out->value = type-parameter
    17097     #       out->parameter-name = slice-to-string(ad, s)
    17098     #     else
    17099     #       out->value = pos-or-insert-slice(Type-id, s)
    17100     #     return
    17101     #   out->left = parse-type(ad, in)
    17102     #   out->right = parse-type-tree(ad, in)
    17103     #
    17104     # . prologue
    17105     55/push-ebp
    17106     89/<- %ebp 4/r32/esp
    17107     # . save registers
    17108     50/push-eax
    17109     51/push-ecx
    17110     52/push-edx
    17111     # clear out
    17112     (zero-out *(ebp+0x10) *Handle-size)
    17113     # var s/ecx: slice
    17114     68/push 0/imm32
    17115     68/push 0/imm32
    17116     89/<- %ecx 4/r32/esp
    17117     # s = next-mu-token(in)
    17118     (next-mu-token *(ebp+0xc) %ecx)
    17119 #?     (write-buffered Stderr "tok: ")
    17120 #?     (write-slice-buffered Stderr %ecx)
    17121 #?     (write-buffered Stderr "$\n")
    17122 #?     (flush Stderr)
    17123     # assert s != ""
    17124     (slice-equal? %ecx "")  # => eax
    17125     3d/compare-eax-and 0/imm32/false
    17126     0f 85/jump-if-!= $parse-type:abort/disp32
    17127     # assert s != "{"
    17128     (slice-equal? %ecx "{")  # => eax
    17129     3d/compare-eax-and 0/imm32/false
    17130     0f 85/jump-if-!= $parse-type:abort/disp32
    17131     # assert s != "}"
    17132     (slice-equal? %ecx "}")  # => eax
    17133     3d/compare-eax-and 0/imm32/false
    17134     0f 85/jump-if-!= $parse-type:abort/disp32
    17135     # assert s != "->"
    17136     (slice-equal? %ecx "->")  # => eax
    17137     3d/compare-eax-and 0/imm32/false
    17138     0f 85/jump-if-!= $parse-type:abort/disp32
    17139     # if (s == ")") return
    17140     (slice-equal? %ecx ")")  # => eax
    17141     3d/compare-eax-and 0/imm32/false
    17142     0f 85/jump-if-!= $parse-type:end/disp32
    17143     # out = new tree
    17144     (allocate *(ebp+8) *Type-tree-size *(ebp+0x10))
    17145     # var out-addr/edx: (addr type-tree) = lookup(*out)
    17146     8b/-> *(ebp+0x10) 2/r32/edx
    17147     (lookup *edx *(edx+4))  # => eax
    17148     89/<- %edx 0/r32/eax
    17149     {
    17150       # if (s != "(") break
    17151       (slice-equal? %ecx "(")  # => eax
    17152       3d/compare-eax-and 0/imm32/false
    17153       0f 85/jump-if-!= break/disp32
    17154       # if s is a number, store it in the type's size field
    17155       {
    17156 $parse-type:check-for-int:
    17157         # var tmp/eax: byte = *s->slice
    17158         8b/-> *ecx 0/r32/eax
    17159         8a/copy-byte *eax 0/r32/AL
    17160         81 4/subop/and %eax 0xff/imm32
    17161         # TODO: raise an error on `var x: (array int a)`
    17162         (decimal-digit? %eax)  # => eax
    17163         3d/compare-eax-and 0/imm32/false
    17164         74/jump-if-= break/disp8
    17165 $parse-type:int:
    17166         # strip out metadata
    17167         (next-token-from-slice *ecx *(ecx+4) 0x2f %ecx)
    17168         #
    17169         (check-mu-hex-int %ecx *(ebp+0x14) *(ebp+0x18))
    17170         (parse-hex-int-from-slice %ecx)  # => eax
    17171         c7 0/subop/copy *(edx+4) 9/imm32/type-id-array-capacity  # Type-tree-value
    17172         89/<- *(edx+8) 0/r32/eax  # Type-tree-value-size
    17173         e9/jump $parse-type:end/disp32
    17174       }
    17175 $parse-type:atom:
    17176       # out->is-atom? = true
    17177       c7 0/subop/copy *edx 1/imm32/true  # Type-tree-is-atom
    17178       {
    17179 $parse-type:check-for-type-parameter:
    17180         # var tmp/eax: byte = *s->slice
    17181         8b/-> *ecx 0/r32/eax
    17182         8a/copy-byte *eax 0/r32/AL
    17183         81 4/subop/and %eax 0xff/imm32
    17184         # if (tmp != '_') break
    17185         3d/compare-eax-and 0x5f/imm32/_
    17186         75/jump-if-!= break/disp8
    17187 $parse-type:type-parameter:
    17188         # out->value = type-parameter
    17189         c7 0/subop/copy *(edx+4) 0xa/imm32/type-parameter  # Type-tree-value
    17190         # out->parameter-name = slice-to-string(ad, s)
    17191         8d/copy-address *(edx+8) 0/r32/eax  # Type-tree-parameter-name
    17192         (slice-to-string *(ebp+8) %ecx %eax)
    17193         e9/jump $parse-type:end/disp32
    17194       }
    17195 $parse-type:non-type-parameter:
    17196       # out->value = pos-or-insert-slice(Type-id, s)
    17197       (pos-or-insert-slice Type-id %ecx)  # => eax
    17198       89/<- *(edx+4) 0/r32/eax  # Type-tree-value
    17199       e9/jump $parse-type:end/disp32
    17200     }
    17201 $parse-type:non-atom:
    17202     # otherwise s == "("
    17203     # out->left = parse-type(ad, in)
    17204     8d/copy-address *(edx+4) 0/r32/eax  # Type-tree-left
    17205     (parse-type *(ebp+8) *(ebp+0xc) %eax *(ebp+0x14) *(ebp+0x18))
    17206     # out->right = parse-type-tree(ad, in)
    17207     8d/copy-address *(edx+0xc) 0/r32/eax  # Type-tree-right
    17208     (parse-type-tree *(ebp+8) *(ebp+0xc) %eax *(ebp+0x14) *(ebp+0x18))
    17209 $parse-type:end:
    17210     # . reclaim locals
    17211     81 0/subop/add %esp 8/imm32
    17212     # . restore registers
    17213     5a/pop-to-edx
    17214     59/pop-to-ecx
    17215     58/pop-to-eax
    17216     # . epilogue
    17217     89/<- %esp 5/r32/ebp
    17218     5d/pop-to-ebp
    17219     c3/return
    17220
    17221 $parse-type:abort:
    17222     # error("unexpected token when parsing type: '" s "'\n")
    17223     (write-buffered *(ebp+0x14) "unexpected token when parsing type: '")
    17224     (write-slice-buffered *(ebp+0x14) %ecx)
    17225     (write-buffered *(ebp+0x14) "'\n")
    17226     (flush *(ebp+0x14))
    17227     (stop *(ebp+0x18) 1)
    17228     # never gets here
    17229
    17230 parse-type-tree:  # ad: (addr allocation-descriptor), in: (addr stream byte), out: (addr handle type-tree), err: (addr buffered-file), ed: (addr exit-descriptor)
    17231     # pseudocode:
    17232     #   var tmp: (handle type-tree) = parse-type(ad, in)
    17233     #   if tmp == 0
    17234     #     return 0
    17235     #   out = allocate(Type-tree)
    17236     #   out->left = tmp
    17237     #   out->right = parse-type-tree(ad, in)
    17238     #
    17239     # . prologue
    17240     55/push-ebp
    17241     89/<- %ebp 4/r32/esp
    17242     # . save registers
    17243     50/push-eax
    17244     51/push-ecx
    17245     52/push-edx
    17246     #
    17247     (zero-out *(ebp+0x10) *Handle-size)
    17248     # var tmp/ecx: (handle type-tree)
    17249     68/push 0/imm32
    17250     68/push 0/imm32
    17251     89/<- %ecx 4/r32/esp
    17252     # tmp = parse-type(ad, in)
    17253     (parse-type *(ebp+8) *(ebp+0xc) %ecx *(ebp+0x14) *(ebp+0x18))
    17254     # if (tmp == 0) return
    17255     81 7/subop/compare *ecx 0/imm32
    17256     74/jump-if-= $parse-type-tree:end/disp8
    17257     # out = new tree
    17258     (allocate *(ebp+8) *Type-tree-size *(ebp+0x10))
    17259     # var out-addr/edx: (addr tree) = lookup(*out)
    17260     8b/-> *(ebp+0x10) 2/r32/edx
    17261     (lookup *edx *(edx+4))  # => eax
    17262     89/<- %edx 0/r32/eax
    17263     # out->left = tmp
    17264     8b/-> *ecx 0/r32/eax
    17265     89/<- *(edx+4) 0/r32/eax  # Type-tree-left
    17266     8b/-> *(ecx+4) 0/r32/eax
    17267     89/<- *(edx+8) 0/r32/eax  # Type-tree-left
    17268     # out->right = parse-type-tree(ad, in)
    17269     8d/copy-address *(edx+0xc) 0/r32/eax  # Type-tree-right
    17270     (parse-type-tree *(ebp+8) *(ebp+0xc) %eax *(ebp+0x14) *(ebp+0x18))
    17271 $parse-type-tree:end:
    17272     # . reclaim locals
    17273     81 0/subop/add %esp 8/imm32
    17274     # . restore registers
    17275     5a/pop-to-edx
    17276     59/pop-to-ecx
    17277     58/pop-to-eax
    17278     # . epilogue
    17279     89/<- %esp 5/r32/ebp
    17280     5d/pop-to-ebp
    17281     c3/return
    17282
    17283 next-mu-token:  # in: (addr stream byte), out: (addr slice)
    17284     # pseudocode:
    17285     # start:
    17286     #   skip-chars-matching-whitespace(in)
    17287     #   if in->read >= in->write              # end of in
    17288     #     out = {0, 0}
    17289     #     return
    17290     #   out->start = &in->data[in->read]
    17291     #   var curr-byte/eax: byte = in->data[in->read]
    17292     #   if curr->byte == ','                  # comment token
    17293     #     ++in->read
    17294     #     goto start
    17295     #   if curr-byte == '#'                   # comment
    17296     #     goto done                             # treat as eof
    17297     #   if curr-byte == '"'                   # string literal
    17298     #     skip-string(in)
    17299     #     goto done                           # no metadata
    17300     #   if curr-byte == '('
    17301     #     ++in->read
    17302     #     goto done
    17303     #   if curr-byte == ')'
    17304     #     ++in->read
    17305     #     goto done
    17306     #   # read a word
    17307     #   while true
    17308     #     if in->read >= in->write
    17309     #       break
    17310     #     curr-byte = in->data[in->read]
    17311     #     if curr-byte == ' '
    17312     #       break
    17313     #     if curr-byte == '\r'
    17314     #       break
    17315     #     if curr-byte == '\n'
    17316     #       break
    17317     #     if curr-byte == '('
    17318     #       break
    17319     #     if curr-byte == ')'
    17320     #       break
    17321     #     if curr-byte == ','
    17322     #       break
    17323     #     ++in->read
    17324     # done:
    17325     #   out->end = &in->data[in->read]
    17326     #
    17327     # . prologue
    17328     55/push-ebp
    17329     89/<- %ebp 4/r32/esp
    17330     # . save registers
    17331     50/push-eax
    17332     51/push-ecx
    17333     56/push-esi
    17334     57/push-edi
    17335     # esi = in
    17336     8b/-> *(ebp+8) 6/r32/esi
    17337     # edi = out
    17338     8b/-> *(ebp+0xc) 7/r32/edi
    17339 $next-mu-token:start:
    17340     (skip-chars-matching-whitespace %esi)
    17341 $next-mu-token:check0:
    17342     # if (in->read >= in->write) return out = {0, 0}
    17343     # . ecx = in->read
    17344     8b/-> *(esi+4) 1/r32/ecx
    17345     # . if (ecx >= in->write) return out = {0, 0}
    17346     3b/compare<- *esi 1/r32/ecx
    17347     c7 0/subop/copy *edi 0/imm32
    17348     c7 0/subop/copy *(edi+4) 0/imm32
    17349     0f 8d/jump-if->= $next-mu-token:end/disp32
    17350     # out->start = &in->data[in->read]
    17351     8d/copy-address *(esi+ecx+0xc) 0/r32/eax
    17352     89/<- *edi 0/r32/eax
    17353     # var curr-byte/eax: byte = in->data[in->read]
    17354     31/xor-with %eax 0/r32/eax
    17355     8a/copy-byte *(esi+ecx+0xc) 0/r32/AL
    17356     {
    17357 $next-mu-token:check-for-comma:
    17358       # if (curr-byte != ',') break
    17359       3d/compare-eax-and 0x2c/imm32/comma
    17360       75/jump-if-!= break/disp8
    17361       # ++in->read
    17362       ff 0/subop/increment *(esi+4)
    17363       # restart
    17364       e9/jump $next-mu-token:start/disp32
    17365     }
    17366     {
    17367 $next-mu-token:check-for-comment:
    17368       # if (curr-byte != '#') break
    17369       3d/compare-eax-and 0x23/imm32/pound
    17370       75/jump-if-!= break/disp8
    17371       # return eof
    17372       e9/jump $next-mu-token:done/disp32
    17373     }
    17374     {
    17375 $next-mu-token:check-for-string-literal:
    17376       # if (curr-byte != '"') break
    17377       3d/compare-eax-and 0x22/imm32/dquote
    17378       75/jump-if-!= break/disp8
    17379       (skip-string %esi)
    17380       # return
    17381       e9/jump $next-mu-token:done/disp32
    17382     }
    17383     {
    17384 $next-mu-token:check-for-open-paren:
    17385       # if (curr-byte != '(') break
    17386       3d/compare-eax-and 0x28/imm32/open-paren
    17387       75/jump-if-!= break/disp8
    17388       # ++in->read
    17389       ff 0/subop/increment *(esi+4)
    17390       # return
    17391       e9/jump $next-mu-token:done/disp32
    17392     }
    17393     {
    17394 $next-mu-token:check-for-close-paren:
    17395       # if (curr-byte != ')') break
    17396       3d/compare-eax-and 0x29/imm32/close-paren
    17397       75/jump-if-!= break/disp8
    17398       # ++in->read
    17399       ff 0/subop/increment *(esi+4)
    17400       # return
    17401       e9/jump $next-mu-token:done/disp32
    17402     }
    17403     {
    17404 $next-mu-token:regular-word-without-metadata:
    17405       # if (in->read >= in->write) break
    17406       # . ecx = in->read
    17407       8b/-> *(esi+4) 1/r32/ecx
    17408       # . if (ecx >= in->write) break
    17409       3b/compare<- *esi 1/r32/ecx
    17410       7d/jump-if->= break/disp8
    17411       # var c/eax: byte = in->data[in->read]
    17412       31/xor-with %eax 0/r32/eax
    17413       8a/copy-byte *(esi+ecx+0xc) 0/r32/AL
    17414       # if (c == ' ') break
    17415       3d/compare-eax-and 0x20/imm32/space
    17416       74/jump-if-= break/disp8
    17417       # if (c == '\r') break
    17418       3d/compare-eax-and 0xd/imm32/carriage-return
    17419       74/jump-if-= break/disp8
    17420       # if (c == '\n') break
    17421       3d/compare-eax-and 0xa/imm32/newline
    17422       74/jump-if-= break/disp8
    17423       # if (c == '(') break
    17424       3d/compare-eax-and 0x28/imm32/open-paren
    17425       0f 84/jump-if-= break/disp32
    17426       # if (c == ')') break
    17427       3d/compare-eax-and 0x29/imm32/close-paren
    17428       0f 84/jump-if-= break/disp32
    17429       # if (c == ',') break
    17430       3d/compare-eax-and 0x2c/imm32/comma
    17431       0f 84/jump-if-= break/disp32
    17432       # ++in->read
    17433       ff 0/subop/increment *(esi+4)
    17434       #
    17435       e9/jump loop/disp32
    17436     }
    17437 $next-mu-token:done:
    17438     # out->end = &in->data[in->read]
    17439     8b/-> *(esi+4) 1/r32/ecx
    17440     8d/copy-address *(esi+ecx+0xc) 0/r32/eax
    17441     89/<- *(edi+4) 0/r32/eax
    17442 $next-mu-token:end:
    17443     # . restore registers
    17444     5f/pop-to-edi
    17445     5e/pop-to-esi
    17446     59/pop-to-ecx
    17447     58/pop-to-eax
    17448     # . epilogue
    17449     89/<- %esp 5/r32/ebp
    17450     5d/pop-to-ebp
    17451     c3/return
    17452
    17453 pos-or-insert-slice:  # arr: (addr stream (addr array byte)), s: (addr slice) -> index/eax: int
    17454     # . prologue
    17455     55/push-ebp
    17456     89/<- %ebp 4/r32/esp
    17457     # if (pos-slice(arr, s) != -1) return it
    17458     (pos-slice *(ebp+8) *(ebp+0xc))  # => eax
    17459     3d/compare-eax-and -1/imm32
    17460     75/jump-if-!= $pos-or-insert-slice:end/disp8
    17461 $pos-or-insert-slice:insert:
    17462     # var s2/eax: (handle array byte)
    17463     68/push 0/imm32
    17464     68/push 0/imm32
    17465     89/<- %eax 4/r32/esp
    17466     (slice-to-string Heap *(ebp+0xc) %eax)
    17467     # throw away alloc-id
    17468     (lookup *eax *(eax+4))  # => eax
    17469     (write-int *(ebp+8) %eax)
    17470     (pos-slice *(ebp+8) *(ebp+0xc))  # => eax
    17471 $pos-or-insert-slice:end:
    17472     # . reclaim locals
    17473     81 0/subop/add %esp 8/imm32
    17474     # . epilogue
    17475     89/<- %esp 5/r32/ebp
    17476     5d/pop-to-ebp
    17477     c3/return
    17478
    17479 # return the index in an array of strings matching 's', -1 if not found
    17480 # index is denominated in elements, not bytes
    17481 pos-slice:  # arr: (addr stream (addr array byte)), s: (addr slice) -> index/eax: int
    17482     # . prologue
    17483     55/push-ebp
    17484     89/<- %ebp 4/r32/esp
    17485     # . save registers
    17486     51/push-ecx
    17487     52/push-edx
    17488     53/push-ebx
    17489     56/push-esi
    17490 #?     (write-buffered Stderr "pos-slice: ")
    17491 #?     (write-slice-buffered Stderr *(ebp+0xc))
    17492 #?     (write-buffered Stderr "\n")
    17493 #?     (flush Stderr)
    17494     # esi = arr
    17495     8b/-> *(ebp+8) 6/r32/esi
    17496     # var index/ecx: int = 0
    17497     b9/copy-to-ecx 0/imm32
    17498     # var curr/edx: (addr (addr array byte)) = arr->data
    17499     8d/copy-address *(esi+0xc) 2/r32/edx
    17500     # var max/ebx: (addr (addr array byte)) = &arr->data[arr->write]
    17501     8b/-> *esi 3/r32/ebx
    17502     8d/copy-address *(esi+ebx+0xc) 3/r32/ebx
    17503     {
    17504 #?       (write-buffered Stderr "  ")
    17505 #?       (write-int32-hex-buffered Stderr %ecx)
    17506 #?       (write-buffered Stderr "\n")
    17507 #?       (flush Stderr)
    17508       # if (curr >= max) return -1
    17509       39/compare %edx 3/r32/ebx
    17510       b8/copy-to-eax -1/imm32
    17511       73/jump-if-addr>= $pos-slice:end/disp8
    17512       # if (slice-equal?(s, *curr)) break
    17513       (slice-equal? *(ebp+0xc) *edx)  # => eax
    17514       3d/compare-eax-and 0/imm32/false
    17515       75/jump-if-!= break/disp8
    17516       # ++index
    17517       41/increment-ecx
    17518       # curr += 4
    17519       81 0/subop/add %edx 4/imm32
    17520       #
    17521       eb/jump loop/disp8
    17522     }
    17523     # return index
    17524     89/<- %eax 1/r32/ecx
    17525 $pos-slice:end:
    17526 #?     (write-buffered Stderr "=> ")
    17527 #?     (write-int32-hex-buffered Stderr %eax)
    17528 #?     (write-buffered Stderr "\n")
    17529     # . restore registers
    17530     5e/pop-to-esi
    17531     5b/pop-to-ebx
    17532     5a/pop-to-edx
    17533     59/pop-to-ecx
    17534     # . epilogue
    17535     89/<- %esp 5/r32/ebp
    17536     5d/pop-to-ebp
    17537     c3/return
    17538
    17539 test-parse-var-with-type:
    17540     # . prologue
    17541     55/push-ebp
    17542     89/<- %ebp 4/r32/esp
    17543     # setup
    17544     8b/-> *Primitive-type-ids 0/r32/eax
    17545     89/<- *Type-id 0/r32/eax  # stream-write
    17546     # (eax..ecx) = "x:"
    17547     b8/copy-to-eax "x:"/imm32
    17548     8b/-> *eax 1/r32/ecx
    17549     8d/copy-address *(eax+ecx+4) 1/r32/ecx
    17550     05/add-to-eax 4/imm32
    17551     # var slice/ecx: slice = {eax, ecx}
    17552     51/push-ecx
    17553     50/push-eax
    17554     89/<- %ecx 4/r32/esp
    17555     # _test-input-stream contains "int"
    17556     (clear-stream _test-input-stream)
    17557     (write _test-input-stream "int")
    17558     # var v/edx: (handle var)
    17559     68/push 0/imm32
    17560     68/push 0/imm32
    17561     89/<- %edx 4/r32/esp
    17562     #
    17563     (parse-var-with-type %ecx _test-input-stream %edx 0 Stderr 0)
    17564     # var v-addr/edx: (addr var) = lookup(v)
    17565     (lookup *edx *(edx+4))  # => eax
    17566     89/<- %edx 0/r32/eax
    17567     # check v-addr->name
    17568     (lookup *edx *(edx+4))  # Var-name Var-name => eax
    17569     (check-strings-equal %eax "x" "F - test-parse-var-with-type/name")
    17570     # check v-addr->type
    17571     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
    17572     (check-ints-equal *eax 1 "F - test-parse-var-with-type/type:0")  # Type-tree-is-atom
    17573     (check-ints-equal *(eax+4) 1 "F - test-parse-var-with-type/type:1")  # Type-tree-value
    17574     (check-ints-equal *(eax+0xc) 0 "F - test-parse-var-with-type/type:2")  # Type-tree-right
    17575     # . epilogue
    17576     89/<- %esp 5/r32/ebp
    17577     5d/pop-to-ebp
    17578     c3/return
    17579
    17580 test-parse-var-with-type-and-register:
    17581     # . prologue
    17582     55/push-ebp
    17583     89/<- %ebp 4/r32/esp
    17584     # setup
    17585     8b/-> *Primitive-type-ids 0/r32/eax
    17586     89/<- *Type-id 0/r32/eax  # stream-write
    17587     # (eax..ecx) = "x/eax:"
    17588     b8/copy-to-eax "x/eax:"/imm32
    17589     8b/-> *eax 1/r32/ecx
    17590     8d/copy-address *(eax+ecx+4) 1/r32/ecx
    17591     05/add-to-eax 4/imm32
    17592     # var slice/ecx: slice = {eax, ecx}
    17593     51/push-ecx
    17594     50/push-eax
    17595     89/<- %ecx 4/r32/esp
    17596     # _test-input-stream contains "int"
    17597     (clear-stream _test-input-stream)
    17598     (write _test-input-stream "int")
    17599     # var v/edx: (handle var)
    17600     68/push 0/imm32
    17601     68/push 0/imm32
    17602     89/<- %edx 4/r32/esp
    17603     #
    17604     (parse-var-with-type %ecx _test-input-stream %edx 0 Stderr 0)
    17605     # var v-addr/edx: (addr var) = lookup(v)
    17606     (lookup *edx *(edx+4))  # => eax
    17607     89/<- %edx 0/r32/eax
    17608     # check v-addr->name
    17609     (lookup *edx *(edx+4))  # Var-name Var-name => eax
    17610     (check-strings-equal %eax "x" "F - test-parse-var-with-type-and-register/name")
    17611     # check v-addr->register
    17612     (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
    17613     (check-strings-equal %eax "eax" "F - test-parse-var-with-type-and-register/register")
    17614     # check v-addr->type
    17615     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
    17616     (check-ints-equal *eax 1 "F - test-parse-var-with-type-and-register/type:0")  # Type-tree-is-atom
    17617     (check-ints-equal *(eax+4) 1 "F - test-parse-var-with-type-and-register/type:1")  # Type-tree-left
    17618     (check-ints-equal *(eax+0xc) 0 "F - test-parse-var-with-type-and-register/type:2")  # Type-tree-right
    17619     # . epilogue
    17620     89/<- %esp 5/r32/ebp
    17621     5d/pop-to-ebp
    17622     c3/return
    17623
    17624 test-parse-var-with-trailing-characters:
    17625     # . prologue
    17626     55/push-ebp
    17627     89/<- %ebp 4/r32/esp
    17628     # setup
    17629     8b/-> *Primitive-type-ids 0/r32/eax
    17630     89/<- *Type-id 0/r32/eax  # stream-write
    17631     # (eax..ecx) = "x:"
    17632     b8/copy-to-eax "x:"/imm32
    17633     8b/-> *eax 1/r32/ecx
    17634     8d/copy-address *(eax+ecx+4) 1/r32/ecx
    17635     05/add-to-eax 4/imm32
    17636     # var slice/ecx: slice = {eax, ecx}
    17637     51/push-ecx
    17638     50/push-eax
    17639     89/<- %ecx 4/r32/esp
    17640     # _test-input-stream contains "int,"
    17641     (clear-stream _test-input-stream)
    17642     (write _test-input-stream "int,")
    17643     # var v/edx: (handle var)
    17644     68/push 0/imm32
    17645     68/push 0/imm32
    17646     89/<- %edx 4/r32/esp
    17647     #
    17648     (parse-var-with-type %ecx _test-input-stream %edx 0 Stderr 0)
    17649     # var v-addr/edx: (addr var) = lookup(v)
    17650     (lookup *edx *(edx+4))  # => eax
    17651     89/<- %edx 0/r32/eax
    17652     # check v-addr->name
    17653     (lookup *edx *(edx+4))  # Var-name Var-name => eax
    17654     (check-strings-equal %eax "x" "F - test-parse-var-with-trailing-characters/name")
    17655     # check v-addr->register
    17656     (check-ints-equal *(edx+0x18) 0 "F - test-parse-var-with-trailing-characters/register")  # Var-register
    17657     # check v-addr->type
    17658     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
    17659     (check-ints-equal *eax 1 "F - test-parse-var-with-trailing-characters/type:0")  # Type-tree-is-atom
    17660     (check-ints-equal *(eax+4) 1 "F - test-parse-var-with-trailing-characters/type:1")  # Type-tree-left
    17661     (check-ints-equal *(eax+0xc) 0 "F - test-parse-var-with-trailing-characters/type:1")  # Type-tree-right
    17662     # . epilogue
    17663     89/<- %esp 5/r32/ebp
    17664     5d/pop-to-ebp
    17665     c3/return
    17666
    17667 test-parse-var-with-register-and-trailing-characters:
    17668     # . prologue
    17669     55/push-ebp
    17670     89/<- %ebp 4/r32/esp
    17671     # setup
    17672     8b/-> *Primitive-type-ids 0/r32/eax
    17673     89/<- *Type-id 0/r32/eax  # stream-write
    17674     # (eax..ecx) = "x/eax:"
    17675     b8/copy-to-eax "x/eax:"/imm32
    17676     8b/-> *eax 1/r32/ecx
    17677     8d/copy-address *(eax+ecx+4) 1/r32/ecx
    17678     05/add-to-eax 4/imm32
    17679     # var slice/ecx: slice = {eax, ecx}
    17680     51/push-ecx
    17681     50/push-eax
    17682     89/<- %ecx 4/r32/esp
    17683     # _test-input-stream contains "int,"
    17684     (clear-stream _test-input-stream)
    17685     (write _test-input-stream "int,")
    17686     # var v/edx: (handle var)
    17687     68/push 0/imm32
    17688     68/push 0/imm32
    17689     89/<- %edx 4/r32/esp
    17690     #
    17691     (parse-var-with-type %ecx _test-input-stream %edx 0 Stderr 0)
    17692     # var v-addr/edx: (addr var) = lookup(v)
    17693     (lookup *edx *(edx+4))  # => eax
    17694     89/<- %edx 0/r32/eax
    17695     # check v-addr->name
    17696     (lookup *edx *(edx+4))  # Var-name Var-name => eax
    17697     (check-strings-equal %eax "x" "F - test-parse-var-with-register-and-trailing-characters/name")
    17698     # check v-addr->register
    17699     (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
    17700     (check-strings-equal %eax "eax" "F - test-parse-var-with-register-and-trailing-characters/register")
    17701     # check v-addr->type
    17702     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
    17703     (check-ints-equal *eax 1 "F - test-parse-var-with-register-and-trailing-characters/type:0")  # Type-tree-is-atom
    17704     (check-ints-equal *(eax+4) 1 "F - test-parse-var-with-register-and-trailing-characters/type:1")  # Type-tree-left
    17705     (check-ints-equal *(eax+0xc) 0 "F - test-parse-var-with-register-and-trailing-characters/type:2")  # Type-tree-right
    17706     # . epilogue
    17707     89/<- %esp 5/r32/ebp
    17708     5d/pop-to-ebp
    17709     c3/return
    17710
    17711 test-parse-var-with-compound-type:
    17712     # . prologue
    17713     55/push-ebp
    17714     89/<- %ebp 4/r32/esp
    17715     # setup
    17716     8b/-> *Primitive-type-ids 0/r32/eax
    17717     89/<- *Type-id 0/r32/eax  # stream-write
    17718     # (eax..ecx) = "x:"
    17719     b8/copy-to-eax "x:"/imm32
    17720     8b/-> *eax 1/r32/ecx
    17721     8d/copy-address *(eax+ecx+4) 1/r32/ecx
    17722     05/add-to-eax 4/imm32
    17723     # var slice/ecx: slice = {eax, ecx}
    17724     51/push-ecx
    17725     50/push-eax
    17726     89/<- %ecx 4/r32/esp
    17727     # _test-input-stream contains "(addr int)"
    17728     (clear-stream _test-input-stream)
    17729     (write _test-input-stream "(addr int)")
    17730     # var v/edx: (handle var)
    17731     68/push 0/imm32
    17732     68/push 0/imm32
    17733     89/<- %edx 4/r32/esp
    17734     #
    17735     (parse-var-with-type %ecx _test-input-stream %edx 0 Stderr 0)
    17736     # var v-addr/edx: (addr var) = lookup(v)
    17737     (lookup *edx *(edx+4))  # => eax
    17738     89/<- %edx 0/r32/eax
    17739     # check v-addr->name
    17740     (lookup *edx *(edx+4))  # Var-name Var-name => eax
    17741     (check-strings-equal %eax "x" "F - test-parse-var-with-compound-type/name")
    17742     # check v-addr->register
    17743     (check-ints-equal *(edx+0x18) 0 "F - test-parse-var-with-compound-type/register")  # Var-register
    17744     # - check v-addr->type
    17745     # var type/edx: (addr type-tree) = var->type
    17746     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
    17747     89/<- %edx 0/r32/eax
    17748     # type is a non-atom
    17749     (check-ints-equal *edx 0 "F - test-parse-var-with-compound-type/type:0")  # Type-tree-is-atom
    17750     # type->left == atom(addr)
    17751     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
    17752     (check-ints-equal *eax 1 "F - test-parse-var-with-compound-type/type:1")  # Type-tree-is-atom
    17753     (check-ints-equal *(eax+4) 2 "F - test-parse-var-with-compound-type/type:2")  # Type-tree-value
    17754     # type->right->left == atom(int)
    17755     (lookup *(edx+0xc) *(edx+0x10))  # Type-tree-right Type-tree-right => eax
    17756     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    17757     (check-ints-equal *eax 1 "F - test-parse-var-with-compound-type/type:3")  # Type-tree-is-atom
    17758     (check-ints-equal *(eax+4) 1 "F - test-parse-var-with-compound-type/type:4")  # Type-tree-value
    17759     # type->right->right == null
    17760     (check-ints-equal *(eax+0xc) 0 "F - test-parse-var-with-compound-type/type:5")  # Type-tree-right
    17761     # . epilogue
    17762     89/<- %esp 5/r32/ebp
    17763     5d/pop-to-ebp
    17764     c3/return
    17765
    17766 # identifier starts with a letter or '$' or '_'
    17767 # no constraints at the moment on later letters
    17768 # all we really want to do so far is exclude '{', '}' and '->'
    17769 identifier?:  # in: (addr slice) -> result/eax: boolean
    17770     # . prologue
    17771     55/push-ebp
    17772     89/<- %ebp 4/r32/esp
    17773     # if (slice-empty?(in)) return false
    17774     (slice-empty? *(ebp+8))  # => eax
    17775     3d/compare-eax-and 0/imm32/false
    17776     75/jump-if-!= $identifier?:false/disp8
    17777     # var c/eax: byte = *in->start
    17778     8b/-> *(ebp+8) 0/r32/eax
    17779     8b/-> *eax 0/r32/eax
    17780     8a/copy-byte *eax 0/r32/AL
    17781     81 4/subop/and %eax 0xff/imm32
    17782     # if (c == '$') return true
    17783     3d/compare-eax-and 0x24/imm32/$
    17784     74/jump-if-= $identifier?:true/disp8
    17785     # if (c == '_') return true
    17786     3d/compare-eax-and 0x5f/imm32/_
    17787     74/jump-if-= $identifier?:true/disp8
    17788     # drop case
    17789     25/and-eax-with 0x5f/imm32
    17790     # if (c < 'A') return false
    17791     3d/compare-eax-and 0x41/imm32/A
    17792     7c/jump-if-< $identifier?:false/disp8
    17793     # if (c > 'Z') return false
    17794     3d/compare-eax-and 0x5a/imm32/Z
    17795     7f/jump-if-> $identifier?:false/disp8
    17796     # otherwise return true
    17797 $identifier?:true:
    17798     b8/copy-to-eax 1/imm32/true
    17799     eb/jump $identifier?:end/disp8
    17800 $identifier?:false:
    17801     b8/copy-to-eax 0/imm32/false
    17802 $identifier?:end:
    17803     # . epilogue
    17804     89/<- %esp 5/r32/ebp
    17805     5d/pop-to-ebp
    17806     c3/return
    17807
    17808 test-is-identifier-dollar:
    17809     # . prologue
    17810     55/push-ebp
    17811     89/<- %ebp 4/r32/esp
    17812     # (eax..ecx) = "$a"
    17813     b8/copy-to-eax "$a"/imm32
    17814     8b/-> *eax 1/r32/ecx
    17815     8d/copy-address *(eax+ecx+4) 1/r32/ecx
    17816     05/add-to-eax 4/imm32
    17817     # var slice/ecx: slice = {eax, ecx}
    17818     51/push-ecx
    17819     50/push-eax
    17820     89/<- %ecx 4/r32/esp
    17821     #
    17822     (identifier? %ecx)
    17823     (check-ints-equal %eax 1 "F - test-is-identifier-dollar")
    17824     # . epilogue
    17825     89/<- %esp 5/r32/ebp
    17826     5d/pop-to-ebp
    17827     c3/return
    17828
    17829 test-is-identifier-underscore:
    17830     # . prologue
    17831     55/push-ebp
    17832     89/<- %ebp 4/r32/esp
    17833     # (eax..ecx) = "_a"
    17834     b8/copy-to-eax "_a"/imm32
    17835     8b/-> *eax 1/r32/ecx
    17836     8d/copy-address *(eax+ecx+4) 1/r32/ecx
    17837     05/add-to-eax 4/imm32
    17838     # var slice/ecx: slice = {eax, ecx}
    17839     51/push-ecx
    17840     50/push-eax
    17841     89/<- %ecx 4/r32/esp
    17842     #
    17843     (identifier? %ecx)
    17844     (check-ints-equal %eax 1 "F - test-is-identifier-underscore")
    17845     # . epilogue
    17846     89/<- %esp 5/r32/ebp
    17847     5d/pop-to-ebp
    17848     c3/return
    17849
    17850 test-is-identifier-a:
    17851     # . prologue
    17852     55/push-ebp
    17853     89/<- %ebp 4/r32/esp
    17854     # (eax..ecx) = "a$"
    17855     b8/copy-to-eax "a$"/imm32
    17856     8b/-> *eax 1/r32/ecx
    17857     8d/copy-address *(eax+ecx+4) 1/r32/ecx
    17858     05/add-to-eax 4/imm32
    17859     # var slice/ecx: slice = {eax, ecx}
    17860     51/push-ecx
    17861     50/push-eax
    17862     89/<- %ecx 4/r32/esp
    17863     #
    17864     (identifier? %ecx)
    17865     (check-ints-equal %eax 1 "F - test-is-identifier-a")
    17866     # . epilogue
    17867     89/<- %esp 5/r32/ebp
    17868     5d/pop-to-ebp
    17869     c3/return
    17870
    17871 test-is-identifier-z:
    17872     # . prologue
    17873     55/push-ebp
    17874     89/<- %ebp 4/r32/esp
    17875     # (eax..ecx) = "z$"
    17876     b8/copy-to-eax "z$"/imm32
    17877     8b/-> *eax 1/r32/ecx
    17878     8d/copy-address *(eax+ecx+4) 1/r32/ecx
    17879     05/add-to-eax 4/imm32
    17880     # var slice/ecx: slice = {eax, ecx}
    17881     51/push-ecx
    17882     50/push-eax
    17883     89/<- %ecx 4/r32/esp
    17884     #
    17885     (identifier? %ecx)
    17886     (check-ints-equal %eax 1 "F - test-is-identifier-z")
    17887     # . epilogue
    17888     89/<- %esp 5/r32/ebp
    17889     5d/pop-to-ebp
    17890     c3/return
    17891
    17892 test-is-identifier-A:
    17893     # . prologue
    17894     55/push-ebp
    17895     89/<- %ebp 4/r32/esp
    17896     # (eax..ecx) = "A$"
    17897     b8/copy-to-eax "A$"/imm32
    17898     8b/-> *eax 1/r32/ecx
    17899     8d/copy-address *(eax+ecx+4) 1/r32/ecx
    17900     05/add-to-eax 4/imm32
    17901     # var slice/ecx: slice = {eax, ecx}
    17902     51/push-ecx
    17903     50/push-eax
    17904     89/<- %ecx 4/r32/esp
    17905     #
    17906     (identifier? %ecx)
    17907     (check-ints-equal %eax 1 "F - test-is-identifier-A")
    17908     # . epilogue
    17909     89/<- %esp 5/r32/ebp
    17910     5d/pop-to-ebp
    17911     c3/return
    17912
    17913 test-is-identifier-Z:
    17914     # . prologue
    17915     55/push-ebp
    17916     89/<- %ebp 4/r32/esp
    17917     # (eax..ecx) = "Z$"
    17918     b8/copy-to-eax "Z$"/imm32
    17919     8b/-> *eax 1/r32/ecx
    17920     8d/copy-address *(eax+ecx+4) 1/r32/ecx
    17921     05/add-to-eax 4/imm32
    17922     # var slice/ecx: slice = {eax, ecx}
    17923     51/push-ecx
    17924     50/push-eax
    17925     89/<- %ecx 4/r32/esp
    17926     #
    17927     (identifier? %ecx)
    17928     (check-ints-equal %eax 1 "F - test-is-identifier-Z")
    17929     # . epilogue
    17930     89/<- %esp 5/r32/ebp
    17931     5d/pop-to-ebp
    17932     c3/return
    17933
    17934 test-is-identifier-at:
    17935     # character before 'A' is invalid
    17936     # . prologue
    17937     55/push-ebp
    17938     89/<- %ebp 4/r32/esp
    17939     # (eax..ecx) = "@a"
    17940     b8/copy-to-eax "@a"/imm32
    17941     8b/-> *eax 1/r32/ecx
    17942     8d/copy-address *(eax+ecx+4) 1/r32/ecx
    17943     05/add-to-eax 4/imm32
    17944     # var slice/ecx: slice = {eax, ecx}
    17945     51/push-ecx
    17946     50/push-eax
    17947     89/<- %ecx 4/r32/esp
    17948     #
    17949     (identifier? %ecx)
    17950     (check-ints-equal %eax 0 "F - test-is-identifier-@")
    17951     # . epilogue
    17952     89/<- %esp 5/r32/ebp
    17953     5d/pop-to-ebp
    17954     c3/return
    17955
    17956 test-is-identifier-square-bracket:
    17957     # character after 'Z' is invalid
    17958     # . prologue
    17959     55/push-ebp
    17960     89/<- %ebp 4/r32/esp
    17961     # (eax..ecx) = "[a"
    17962     b8/copy-to-eax "[a"/imm32
    17963     8b/-> *eax 1/r32/ecx
    17964     8d/copy-address *(eax+ecx+4) 1/r32/ecx
    17965     05/add-to-eax 4/imm32
    17966     # var slice/ecx: slice = {eax, ecx}
    17967     51/push-ecx
    17968     50/push-eax
    17969     89/<- %ecx 4/r32/esp
    17970     #
    17971     (identifier? %ecx)
    17972     (check-ints-equal %eax 0 "F - test-is-identifier-@")
    17973     # . epilogue
    17974     89/<- %esp 5/r32/ebp
    17975     5d/pop-to-ebp
    17976     c3/return
    17977
    17978 test-is-identifier-backtick:
    17979     # character before 'a' is invalid
    17980     # . prologue
    17981     55/push-ebp
    17982     89/<- %ebp 4/r32/esp
    17983     # (eax..ecx) = "`a"
    17984     b8/copy-to-eax "`a"/imm32
    17985     8b/-> *eax 1/r32/ecx
    17986     8d/copy-address *(eax+ecx+4) 1/r32/ecx
    17987     05/add-to-eax 4/imm32
    17988     # var slice/ecx: slice = {eax, ecx}
    17989     51/push-ecx
    17990     50/push-eax
    17991     89/<- %ecx 4/r32/esp
    17992     #
    17993     (identifier? %ecx)
    17994     (check-ints-equal %eax 0 "F - test-is-identifier-backtick")
    17995     # . epilogue
    17996     89/<- %esp 5/r32/ebp
    17997     5d/pop-to-ebp
    17998     c3/return
    17999
    18000 test-is-identifier-curly-brace-open:
    18001     # character after 'z' is invalid; also used for blocks
    18002     # . prologue
    18003     55/push-ebp
    18004     89/<- %ebp 4/r32/esp
    18005     # (eax..ecx) = "{a"
    18006     b8/copy-to-eax "{a"/imm32
    18007     8b/-> *eax 1/r32/ecx
    18008     8d/copy-address *(eax+ecx+4) 1/r32/ecx
    18009     05/add-to-eax 4/imm32
    18010     # var slice/ecx: slice = {eax, ecx}
    18011     51/push-ecx
    18012     50/push-eax
    18013     89/<- %ecx 4/r32/esp
    18014     #
    18015     (identifier? %ecx)
    18016     (check-ints-equal %eax 0 "F - test-is-identifier-curly-brace-open")
    18017     # . epilogue
    18018     89/<- %esp 5/r32/ebp
    18019     5d/pop-to-ebp
    18020     c3/return
    18021
    18022 test-is-identifier-curly-brace-close:
    18023     # . prologue
    18024     55/push-ebp
    18025     89/<- %ebp 4/r32/esp
    18026     # (eax..ecx) = "}a"
    18027     b8/copy-to-eax "}a"/imm32
    18028     8b/-> *eax 1/r32/ecx
    18029     8d/copy-address *(eax+ecx+4) 1/r32/ecx
    18030     05/add-to-eax 4/imm32
    18031     # var slice/ecx: slice = {eax, ecx}
    18032     51/push-ecx
    18033     50/push-eax
    18034     89/<- %ecx 4/r32/esp
    18035     #
    18036     (identifier? %ecx)
    18037     (check-ints-equal %eax 0 "F - test-is-identifier-curly-brace-close")
    18038     # . epilogue
    18039     89/<- %esp 5/r32/ebp
    18040     5d/pop-to-ebp
    18041     c3/return
    18042
    18043 test-is-identifier-hyphen:
    18044     # disallow leading '-' since '->' has special meaning
    18045     # . prologue
    18046     55/push-ebp
    18047     89/<- %ebp 4/r32/esp
    18048     # (eax..ecx) = "-a"
    18049     b8/copy-to-eax "-a"/imm32
    18050     8b/-> *eax 1/r32/ecx
    18051     8d/copy-address *(eax+ecx+4) 1/r32/ecx
    18052     05/add-to-eax 4/imm32
    18053     # var slice/ecx: slice = {eax, ecx}
    18054     51/push-ecx
    18055     50/push-eax
    18056     89/<- %ecx 4/r32/esp
    18057     #
    18058     (identifier? %ecx)
    18059     (check-ints-equal %eax 0 "F - test-is-identifier-hyphen")
    18060     # . epilogue
    18061     89/<- %esp 5/r32/ebp
    18062     5d/pop-to-ebp
    18063     c3/return
    18064
    18065 populate-mu-function-body:  # in: (addr buffered-file), out: (addr function), vars: (addr stack live-var), err: (addr buffered-file), ed: (addr exit-descriptor)
    18066     # . prologue
    18067     55/push-ebp
    18068     89/<- %ebp 4/r32/esp
    18069     # . save registers
    18070     50/push-eax
    18071     56/push-esi
    18072     57/push-edi
    18073     # esi = in
    18074     8b/-> *(ebp+8) 6/r32/esi
    18075     # edi = out
    18076     8b/-> *(ebp+0xc) 7/r32/edi
    18077     # initialize some global state
    18078     c7 0/subop/copy *Curr-block-depth 1/imm32
    18079     # parse-mu-block(in, vars, out, out->body)
    18080     8d/copy-address *(edi+0x18) 0/r32/eax  # Function-body
    18081     (parse-mu-block %esi *(ebp+0x10) %edi %eax *(ebp+0x14) *(ebp+0x18))
    18082 $populate-mu-function-body:end:
    18083     # . restore registers
    18084     5f/pop-to-edi
    18085     5e/pop-to-esi
    18086     58/pop-to-eax
    18087     # . epilogue
    18088     89/<- %esp 5/r32/ebp
    18089     5d/pop-to-ebp
    18090     c3/return
    18091
    18092 # parses a block, assuming that the leading '{' has already been read by the caller
    18093 parse-mu-block:  # in: (addr buffered-file), vars: (addr stack live-var), fn: (addr function), out: (addr handle block), err: (addr buffered-file), ed: (addr exit-descriptor)
    18094     # pseudocode:
    18095     #   var line: (stream byte 512)
    18096     #   var word-slice: slice
    18097     #   allocate(Heap, Stmt-size, out)
    18098     #   var out-addr: (addr block) = lookup(*out)
    18099     #   out-addr->tag = 0/block
    18100     #   out-addr->var = some unique name
    18101     #   push(vars, {out-addr->var, false})
    18102     #   while true                                  # line loop
    18103     #     clear-stream(line)
    18104     #     read-line-buffered(in, line)
    18105     #     if (line->write == 0) break               # end of file
    18106     #     word-slice = next-mu-token(line)
    18107     #     if slice-empty?(word-slice)               # end of line
    18108     #       continue
    18109     #     else if slice-starts-with?(word-slice, "#")
    18110     #       continue
    18111     #     else if slice-equal?(word-slice, "{")
    18112     #       assert(no-tokens-in(line))
    18113     #       block = parse-mu-block(in, vars, fn)
    18114     #       append-to-block(out-addr, block)
    18115     #     else if slice-equal?(word-slice, "}")
    18116     #       break
    18117     #     else if slice-ends-with?(word-slice, ":")
    18118     #       # TODO: error-check the rest of 'line'
    18119     #       --word-slice->end to skip ':'
    18120     #       named-block = parse-mu-named-block(word-slice, in, vars, fn)
    18121     #       append-to-block(out-addr, named-block)
    18122     #     else if slice-equal?(word-slice, "var")
    18123     #       var-def = parse-mu-var-def(line, vars, fn)
    18124     #       append-to-block(out-addr, var-def)
    18125     #     else
    18126     #       stmt = parse-mu-stmt(line, vars, fn)
    18127     #       append-to-block(out-addr, stmt)
    18128     #   pop(vars)
    18129     #
    18130     # . prologue
    18131     55/push-ebp
    18132     89/<- %ebp 4/r32/esp
    18133     # . save registers
    18134     50/push-eax
    18135     51/push-ecx
    18136     52/push-edx
    18137     53/push-ebx
    18138     57/push-edi
    18139     # var line/ecx: (stream byte 512)
    18140     81 5/subop/subtract %esp 0x200/imm32
    18141     68/push 0x200/imm32/size
    18142     68/push 0/imm32/read
    18143     68/push 0/imm32/write
    18144     89/<- %ecx 4/r32/esp
    18145     # var word-slice/edx: slice
    18146     68/push 0/imm32/end
    18147     68/push 0/imm32/start
    18148     89/<- %edx 4/r32/esp
    18149     # allocate into out
    18150     (allocate Heap *Stmt-size *(ebp+0x14))
    18151     # var out-addr/edi: (addr block) = lookup(*out)
    18152     8b/-> *(ebp+0x14) 7/r32/edi
    18153     (lookup *edi *(edi+4))  # => eax
    18154     89/<- %edi 0/r32/eax
    18155     # out-addr->tag is 0 (block) by default
    18156     # set out-addr->var
    18157     8d/copy-address *(edi+0xc) 0/r32/eax  # Block-var
    18158     (new-block-name *(ebp+0x10) %eax)
    18159     # push(vars, out-addr->var)
    18160     (push *(ebp+0xc) *(edi+0xc))  # Block-var
    18161     (push *(ebp+0xc) *(edi+0x10))  # Block-var
    18162     (push *(ebp+0xc) 0)  # false
    18163     # increment *Curr-block-depth
    18164     ff 0/subop/increment *Curr-block-depth
    18165     {
    18166 $parse-mu-block:line-loop:
    18167       # line = read-line-buffered(in)
    18168       (clear-stream %ecx)
    18169       (read-line-buffered *(ebp+8) %ecx)
    18170 #?       (write-buffered Stderr "line: ")
    18171 #?       (write-stream-data Stderr %ecx)
    18172 #? #?       (write-buffered Stderr Newline)  # line has its own newline
    18173 #?       (flush Stderr)
    18174 #?       (rewind-stream %ecx)
    18175       # if (line->write == 0) break
    18176       81 7/subop/compare *ecx 0/imm32
    18177       0f 84/jump-if-= break/disp32
    18178 #?       (write-buffered Stderr "vars:\n")
    18179 #?       (dump-vars *(ebp+0xc))
    18180       # word-slice = next-mu-token(line)
    18181       (next-mu-token %ecx %edx)
    18182 #?       (write-buffered Stderr "word: ")
    18183 #?       (write-slice-buffered Stderr %edx)
    18184 #?       (write-buffered Stderr Newline)
    18185 #?       (flush Stderr)
    18186       # if slice-empty?(word-slice) continue
    18187       (slice-empty? %edx)
    18188       3d/compare-eax-and 0/imm32/false
    18189       0f 85/jump-if-!= loop/disp32
    18190       # if (slice-starts-with?(word-slice, '#') continue
    18191       # . eax = *word-slice->start
    18192       8b/-> *edx 0/r32/eax
    18193       8a/copy-byte *eax 0/r32/AL
    18194       81 4/subop/and %eax 0xff/imm32
    18195       # . if (eax == '#') continue
    18196       3d/compare-eax-and 0x23/imm32/hash
    18197       0f 84/jump-if-= loop/disp32
    18198       # if slice-equal?(word-slice, "{")
    18199       {
    18200 $parse-mu-block:check-for-block:
    18201         (slice-equal? %edx "{")
    18202         3d/compare-eax-and 0/imm32/false
    18203         74/jump-if-= break/disp8
    18204         (check-no-tokens-left %ecx)
    18205         # parse new block and append
    18206         # . var tmp/eax: (handle block)
    18207         68/push 0/imm32
    18208         68/push 0/imm32
    18209         89/<- %eax 4/r32/esp
    18210         # .
    18211         (parse-mu-block *(ebp+8) *(ebp+0xc) *(ebp+0x10) %eax *(ebp+0x18) *(ebp+0x1c))
    18212         (append-to-block Heap %edi  *eax *(eax+4))
    18213         # . reclaim tmp
    18214         81 0/subop/add %esp 8/imm32
    18215         # .
    18216         e9/jump $parse-mu-block:line-loop/disp32
    18217       }
    18218       # if slice-equal?(word-slice, "}") break
    18219 $parse-mu-block:check-for-end:
    18220       (slice-equal? %edx "}")
    18221       3d/compare-eax-and 0/imm32/false
    18222       0f 85/jump-if-!= break/disp32
    18223       # if slice-ends-with?(word-slice, ":") parse named block and append
    18224       {
    18225 $parse-mu-block:check-for-named-block:
    18226         # . eax = *(word-slice->end-1)
    18227         8b/-> *(edx+4) 0/r32/eax
    18228         48/decrement-eax
    18229         8a/copy-byte *eax 0/r32/AL
    18230         81 4/subop/and %eax 0xff/imm32
    18231         # . if (eax != ':') break
    18232         3d/compare-eax-and 0x3a/imm32/colon
    18233         0f 85/jump-if-!= break/disp32
    18234         # TODO: error-check the rest of 'line'
    18235         #
    18236         # skip ':'
    18237         ff 1/subop/decrement *(edx+4)  # Slice-end
    18238         # var tmp/eax: (handle block)
    18239         68/push 0/imm32
    18240         68/push 0/imm32
    18241         89/<- %eax 4/r32/esp
    18242         #
    18243         (parse-mu-named-block %edx *(ebp+8) *(ebp+0xc) *(ebp+0x10) %eax *(ebp+0x18) *(ebp+0x1c))
    18244         (append-to-block Heap %edi  *eax *(eax+4))
    18245         # reclaim tmp
    18246         81 0/subop/add %esp 8/imm32
    18247         #
    18248         e9/jump $parse-mu-block:line-loop/disp32
    18249       }
    18250       # if slice-equal?(word-slice, "var")
    18251       {
    18252 $parse-mu-block:check-for-var:
    18253         (slice-equal? %edx "var")
    18254         3d/compare-eax-and 0/imm32/false
    18255         74/jump-if-= break/disp8
    18256         # var tmp/eax: (handle block)
    18257         68/push 0/imm32
    18258         68/push 0/imm32
    18259         89/<- %eax 4/r32/esp
    18260         #
    18261         (parse-mu-var-def %ecx *(ebp+0xc) %eax *(ebp+0x10) *(ebp+0x18) *(ebp+0x1c))
    18262         (append-to-block Heap %edi  *eax *(eax+4))
    18263         # reclaim tmp
    18264         81 0/subop/add %esp 8/imm32
    18265         #
    18266         e9/jump $parse-mu-block:line-loop/disp32
    18267       }
    18268 $parse-mu-block:regular-stmt:
    18269       # otherwise
    18270       # var tmp/eax: (handle block)
    18271       68/push 0/imm32
    18272       68/push 0/imm32
    18273       89/<- %eax 4/r32/esp
    18274       #
    18275       (parse-mu-stmt %ecx *(ebp+0xc) *(ebp+0x10) %eax *(ebp+0x18) *(ebp+0x1c))
    18276       (append-to-block Heap %edi  *eax *(eax+4))
    18277       # reclaim tmp
    18278       81 0/subop/add %esp 8/imm32
    18279       #
    18280       e9/jump loop/disp32
    18281     } # end line loop
    18282     (clean-up-blocks *(ebp+0xc) *Curr-block-depth *(ebp+0x10))
    18283     # decrement *Curr-block-depth
    18284     ff 1/subop/decrement *Curr-block-depth
    18285     # pop(vars)
    18286     (pop *(ebp+0xc))  # => eax
    18287     (pop *(ebp+0xc))  # => eax
    18288     (pop *(ebp+0xc))  # => eax
    18289 $parse-mu-block:end:
    18290     # . reclaim locals
    18291     81 0/subop/add %esp 0x214/imm32
    18292     # . restore registers
    18293     5f/pop-to-edi
    18294     5b/pop-to-ebx
    18295     5a/pop-to-edx
    18296     59/pop-to-ecx
    18297     58/pop-to-eax
    18298     # . epilogue
    18299     89/<- %esp 5/r32/ebp
    18300     5d/pop-to-ebp
    18301     c3/return
    18302
    18303 $parse-mu-block:abort:
    18304     # error("'{' or '}' should be on its own line, but got '")
    18305     (write-buffered *(ebp+0x18) "'{' or '}' should be on its own line, but got '")
    18306     (rewind-stream %ecx)
    18307     (write-stream-data *(ebp+0x18) %ecx)
    18308     (write-buffered *(ebp+0x18) "'\n")
    18309     (flush *(ebp+0x18))
    18310     (stop *(ebp+0x1c) 1)
    18311     # never gets here
    18312
    18313 new-block-name:  # fn: (addr function), out: (addr handle var)
    18314     # . prologue
    18315     55/push-ebp
    18316     89/<- %ebp 4/r32/esp
    18317     # . save registers
    18318     50/push-eax
    18319     51/push-ecx
    18320     52/push-edx
    18321     # var n/ecx: int = len(fn->name) + 10 for an int + 2 for '$:'
    18322     8b/-> *(ebp+8) 0/r32/eax
    18323     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    18324     8b/-> *eax 0/r32/eax  # String-size
    18325     05/add-to-eax 0xd/imm32  # 10 + 2 for '$:'
    18326     89/<- %ecx 0/r32/eax
    18327     # var name/edx: (stream byte n)
    18328     29/subtract-from %esp 1/r32/ecx
    18329     ff 6/subop/push %ecx
    18330     68/push 0/imm32/read
    18331     68/push 0/imm32/write
    18332     89/<- %edx 4/r32/esp
    18333     (clear-stream %edx)
    18334     # eax = fn->name
    18335     8b/-> *(ebp+8) 0/r32/eax
    18336     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    18337     # construct result using Next-block-index (and increment it)
    18338     (write %edx "$")
    18339     (write %edx %eax)
    18340     (write %edx ":")
    18341     (write-int32-hex %edx *Next-block-index)
    18342     ff 0/subop/increment *Next-block-index
    18343     # var s/eax: slice = {name->data, name->data + name->write}  (clobbering edx)
    18344     # . eax = name->write
    18345     8b/-> *edx 0/r32/eax
    18346     # . edx = name->data
    18347     8d/copy-address *(edx+0xc) 2/r32/edx
    18348     # . eax = name->write + name->data
    18349     01/add-to %eax 2/r32/edx
    18350     # . push {edx, eax}
    18351     ff 6/subop/push %eax
    18352     ff 6/subop/push %edx
    18353     89/<- %eax 4/r32/esp
    18354     # out = new literal(s)
    18355     (new-literal Heap %eax *(ebp+0xc))
    18356 #?     8b/-> *(ebp+0xc) 0/r32/eax
    18357 #?     (write-buffered Stderr "type allocid in caller after new-literal: ")
    18358 #?     (write-int32-hex-buffered Stderr *(eax+8))
    18359 #?     (write-buffered Stderr " for var ")
    18360 #?     (write-int32-hex-buffered Stderr %eax)
    18361 #?     (write-buffered Stderr Newline)
    18362 #?     (flush Stderr)
    18363 $new-block-name:end:
    18364     # . reclaim locals
    18365     81 0/subop/add %ecx 0xc/imm32  # name.{read/write/len}
    18366     81 0/subop/add %ecx 8/imm32  # slice
    18367     01/add-to %esp 1/r32/ecx
    18368     # . restore registers
    18369     5a/pop-to-edx
    18370     59/pop-to-ecx
    18371     58/pop-to-eax
    18372     # . epilogue
    18373     89/<- %esp 5/r32/ebp
    18374     5d/pop-to-ebp
    18375     c3/return
    18376
    18377 check-no-tokens-left:  # line: (addr stream byte)
    18378     # . prologue
    18379     55/push-ebp
    18380     89/<- %ebp 4/r32/esp
    18381     # . save registers
    18382     50/push-eax
    18383     51/push-ecx
    18384     # var s/ecx: slice
    18385     68/push 0/imm32/end
    18386     68/push 0/imm32/start
    18387     89/<- %ecx 4/r32/esp
    18388     #
    18389     (next-mu-token *(ebp+8) %ecx)
    18390     # if slice-empty?(s) return
    18391     (slice-empty? %ecx)
    18392     3d/compare-eax-and 0/imm32/false
    18393     75/jump-if-!= $check-no-tokens-left:end/disp8
    18394     # if (slice-starts-with?(s, '#') return
    18395     # . eax = *s->start
    18396     8b/-> *edx 0/r32/eax
    18397     8a/copy-byte *eax 0/r32/AL
    18398     81 4/subop/and %eax 0xff/imm32
    18399     # . if (eax == '#') continue
    18400     3d/compare-eax-and 0x23/imm32/hash
    18401     74/jump-if-= $check-no-tokens-left:end/disp8
    18402     # abort
    18403     (write-buffered Stderr "'{' or '}' should be on its own line, but got '")
    18404     (rewind-stream %ecx)
    18405     (write-stream 2 %ecx)
    18406     (write-buffered Stderr "'\n")
    18407     (flush Stderr)
    18408     # . syscall(exit, 1)
    18409     bb/copy-to-ebx  1/imm32
    18410     e8/call syscall_exit/disp32
    18411     # never gets here
    18412 $check-no-tokens-left:end:
    18413     # . reclaim locals
    18414     81 0/subop/add %esp 8/imm32
    18415     # . restore registers
    18416     59/pop-to-ecx
    18417     58/pop-to-eax
    18418     # . epilogue
    18419     89/<- %esp 5/r32/ebp
    18420     5d/pop-to-ebp
    18421     c3/return
    18422
    18423 parse-mu-named-block:  # name: (addr slice), in: (addr buffered-file), vars: (addr stack live-var), fn: (addr function), out: (addr handle stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
    18424     # pseudocode:
    18425     #   var v: (handle var)
    18426     #   new-literal(name, v)
    18427     #   push(vars, {v, false})
    18428     #   parse-mu-block(in, vars, fn, out)
    18429     #   pop(vars)
    18430     #   out->tag = block
    18431     #   out->var = v
    18432     #
    18433     # . prologue
    18434     55/push-ebp
    18435     89/<- %ebp 4/r32/esp
    18436     # . save registers
    18437     50/push-eax
    18438     51/push-ecx
    18439     57/push-edi
    18440     # var v/ecx: (handle var)
    18441     68/push 0/imm32
    18442     68/push 0/imm32
    18443     89/<- %ecx 4/r32/esp
    18444     #
    18445     (new-literal Heap *(ebp+8) %ecx)
    18446     # push(vars, v)
    18447     (push *(ebp+0x10) *ecx)
    18448     (push *(ebp+0x10) *(ecx+4))
    18449     (push *(ebp+0x10) 0)  # false
    18450     #
    18451     (parse-mu-block *(ebp+0xc) *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c) *(ebp+0x20))
    18452     # pop v off vars
    18453     (pop *(ebp+0x10))  # => eax
    18454     (pop *(ebp+0x10))  # => eax
    18455     (pop *(ebp+0x10))  # => eax
    18456     # var out-addr/edi: (addr stmt) = lookup(*out)
    18457     8b/-> *(ebp+0x18) 7/r32/edi
    18458     (lookup *edi *(edi+4))  # => eax
    18459     89/<- %edi 0/r32/eax
    18460     # out-addr->tag = named-block
    18461     c7 0/subop/copy *edi 0/imm32/block  # Stmt-tag
    18462     # out-addr->var = v
    18463     8b/-> *ecx 0/r32/eax
    18464     89/<- *(edi+0xc) 0/r32/eax  # Block-var
    18465     8b/-> *(ecx+4) 0/r32/eax
    18466     89/<- *(edi+0x10) 0/r32/eax  # Block-var
    18467 $parse-mu-named-block:end:
    18468     # . reclaim locals
    18469     81 0/subop/add %esp 8/imm32
    18470     # . restore registers
    18471     5f/pop-to-edi
    18472     59/pop-to-ecx
    18473     58/pop-to-eax
    18474     # . epilogue
    18475     89/<- %esp 5/r32/ebp
    18476     5d/pop-to-ebp
    18477     c3/return
    18478
    18479 parse-mu-var-def:  # line: (addr stream byte), vars: (addr stack live-var), out: (addr handle stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    18480     # . prologue
    18481     55/push-ebp
    18482     89/<- %ebp 4/r32/esp
    18483     # . save registers
    18484     50/push-eax
    18485     51/push-ecx
    18486     52/push-edx
    18487     56/push-esi
    18488     57/push-edi
    18489     # edi = out
    18490     8b/-> *(ebp+0x10) 7/r32/edi
    18491     # var word-slice/ecx: slice
    18492     68/push 0/imm32/end
    18493     68/push 0/imm32/start
    18494     89/<- %ecx 4/r32/esp
    18495     # var v/edx: (handle var)
    18496     68/push 0/imm32
    18497     68/push 0/imm32
    18498     89/<- %edx 4/r32/esp
    18499     # v = parse-var-with-type(next-mu-token(line))
    18500     (next-mu-token *(ebp+8) %ecx)
    18501     {
    18502       # just for tests, support null fn
    18503       8b/-> *(ebp+0x14) 0/r32/eax
    18504       3d/compare-eax-and 0/imm32
    18505       74/jump-if-= break/disp8
    18506       (lookup *eax *(eax+4))  # Var-name Var-name => eax
    18507     }
    18508     (parse-var-with-type %ecx *(ebp+8) %edx %eax *(ebp+0x18) *(ebp+0x1c))
    18509     # var v-addr/esi: (addr var)
    18510     (lookup *edx *(edx+4))  # => eax
    18511     89/<- %esi 0/r32/eax
    18512     # v->block-depth = *Curr-block-depth
    18513     8b/-> *Curr-block-depth 0/r32/eax
    18514     89/<- *(esi+0x10) 0/r32/eax  # Var-block-depth
    18515     # either v has no register and there's no more to this line
    18516     81 7/subop/compare *(esi+0x18) 0/imm32
    18517     {
    18518       75/jump-if-!= break/disp8
    18519       # if v-addr->type == byte, abort
    18520       (lookup *(esi+8) *(esi+0xc))  # Var-type Var-type => eax
    18521       (simple-mu-type? %eax 8)  # byte => eax
    18522       3d/compare-eax-and 0/imm32/false
    18523       0f 85/jump-if-!= $parse-mu-var-def:error-byte-on-stack/disp32
    18524       # ensure that there's nothing else on this line
    18525       (next-mu-token *(ebp+8) %ecx)
    18526       (slice-empty? %ecx)  # => eax
    18527       3d/compare-eax-and 0/imm32/false
    18528       0f 84/jump-if-= $parse-mu-var-def:error2/disp32
    18529       #
    18530       (new-var-def Heap  *edx *(edx+4)  %edi)
    18531       e9/jump $parse-mu-var-def:update-vars/disp32
    18532     }
    18533     # or v has a register and there's more to this line
    18534     {
    18535       0f 84/jump-if-= break/disp32
    18536       # if v-addr->type == byte, check for unsupported registers
    18537       {
    18538         (lookup *(esi+8) *(esi+0xc))  # Var-type Var-type => eax
    18539         (simple-mu-type? %eax 8)  # byte => eax
    18540         3d/compare-eax-and 0/imm32/false
    18541         74/jump-if-= break/disp8
    18542         (lookup *(esi+0x18) *(esi+0x1c))  # => eax
    18543         (string-equal? %eax "esi")  # => eax
    18544         3d/compare-eax-and 0/imm32/false
    18545         0f 85/jump-if-!= $parse-mu-var-def:error-byte-registers/disp32
    18546         (lookup *(esi+0x18) *(esi+0x1c))  # => eax
    18547         (string-equal? %eax "edi")  # => eax
    18548         3d/compare-eax-and 0/imm32/false
    18549         0f 85/jump-if-!= $parse-mu-var-def:error-byte-registers/disp32
    18550       }
    18551       # TODO: vars of type 'byte' should only be initialized by clearing to 0
    18552       # ensure that the next word is '<-'
    18553       (next-mu-token *(ebp+8) %ecx)
    18554       (slice-equal? %ecx "<-")  # => eax
    18555       3d/compare-eax-and 0/imm32/false
    18556       0f 84/jump-if-= $parse-mu-var-def:error1/disp32
    18557       #
    18558       (new-reg-var-def Heap  *edx *(edx+4)  %edi)
    18559       (lookup *edi *(edi+4))  # => eax
    18560       (add-operation-and-inputs-to-stmt %eax *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
    18561     }
    18562 $parse-mu-var-def:update-vars:
    18563     # push 'v' at end of function
    18564     (push *(ebp+0xc) *edx)
    18565     (push *(ebp+0xc) *(edx+4))
    18566     (push *(ebp+0xc) 0)  # Live-var-register-spilled is unused during parsing
    18567 $parse-mu-var-def:end:
    18568     # . reclaim locals
    18569     81 0/subop/add %esp 0x10/imm32
    18570     # . restore registers
    18571     5f/pop-to-edi
    18572     5e/pop-to-esi
    18573     5a/pop-to-edx
    18574     59/pop-to-ecx
    18575     58/pop-to-eax
    18576     # . epilogue
    18577     89/<- %esp 5/r32/ebp
    18578     5d/pop-to-ebp
    18579     c3/return
    18580
    18581 $parse-mu-var-def:error1:
    18582     (rewind-stream *(ebp+8))
    18583     # error("register variable requires a valid instruction to initialize but got '" line "'\n")
    18584     (write-buffered *(ebp+0x18) "register variable requires a valid instruction to initialize but got '")
    18585     (flush *(ebp+0x18))
    18586     (write-stream-data *(ebp+0x18) *(ebp+8))
    18587     (write-buffered *(ebp+0x18) "'\n")
    18588     (flush *(ebp+0x18))
    18589     (stop *(ebp+0x1c) 1)
    18590     # never gets here
    18591
    18592 $parse-mu-var-def:error2:
    18593     # error("fn " fn ": var " var ": variables on the stack can't take an initializer\n")
    18594     (write-buffered *(ebp+0x18) "fn ")
    18595     8b/-> *(ebp+0x14) 0/r32/eax
    18596     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    18597     (write-buffered *(ebp+0x18) %eax)
    18598     (write-buffered *(ebp+0x18) ": var ")
    18599     # var v-addr/eax: (addr var) = lookup(v)
    18600     (lookup *edx *(edx+4))  # => eax
    18601     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    18602     (write-buffered *(ebp+0x18) %eax)
    18603     (write-buffered *(ebp+0x18) ": variables on the stack can't take an initializer\n")
    18604     (flush *(ebp+0x18))
    18605     (stop *(ebp+0x1c) 1)
    18606     # never gets here
    18607
    18608 $parse-mu-var-def:error-byte-on-stack:
    18609     # error("fn " fn ": var '" var "' of type 'byte' cannot be on the stack\n")
    18610     (write-buffered *(ebp+0x18) "fn ")
    18611     8b/-> *(ebp+0x14) 0/r32/eax
    18612     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    18613     (write-buffered *(ebp+0x18) %eax)
    18614     (write-buffered *(ebp+0x18) ": var '")
    18615     # var v-addr/eax: (addr var) = lookup(v)
    18616     (lookup *edx *(edx+4))  # => eax
    18617     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    18618     (write-buffered *(ebp+0x18) %eax)
    18619     (write-buffered *(ebp+0x18) "' of type 'byte' cannot be on the stack\n")
    18620     (flush *(ebp+0x18))
    18621     (stop *(ebp+0x1c) 1)
    18622     # never gets here
    18623
    18624 $parse-mu-var-def:error-byte-registers:
    18625     # error("fn " fn ": var '" var "' of type 'byte' cannot be in esi or edi\n")
    18626     (write-buffered *(ebp+0x18) "fn ")
    18627     8b/-> *(ebp+0x14) 0/r32/eax
    18628     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    18629     (write-buffered *(ebp+0x18) %eax)
    18630     (write-buffered *(ebp+0x18) ": var '")
    18631     # var v-addr/eax: (addr var) = lookup(v)
    18632     (lookup *edx *(edx+4))  # => eax
    18633     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    18634     (write-buffered *(ebp+0x18) %eax)
    18635     (write-buffered *(ebp+0x18) "' of type 'byte' cannot be in esi or edi\n")
    18636     (flush *(ebp+0x18))
    18637     (stop *(ebp+0x1c) 1)
    18638     # never gets here
    18639
    18640 test-parse-mu-var-def:
    18641     # 'var n: int'
    18642     # . prologue
    18643     55/push-ebp
    18644     89/<- %ebp 4/r32/esp
    18645     # setup
    18646     8b/-> *Primitive-type-ids 0/r32/eax
    18647     89/<- *Type-id 0/r32/eax  # stream-write
    18648     (clear-stream _test-input-stream)
    18649     (write _test-input-stream "n: int\n")  # caller has consumed the 'var'
    18650     c7 0/subop/copy *Curr-block-depth 1/imm32
    18651     # var out/esi: (handle stmt)
    18652     68/push 0/imm32
    18653     68/push 0/imm32
    18654     89/<- %esi 4/r32/esp
    18655     # var vars/ecx: (stack (addr var) 16)
    18656     81 5/subop/subtract %esp 0xc0/imm32
    18657     68/push 0xc0/imm32/size
    18658     68/push 0/imm32/top
    18659     89/<- %ecx 4/r32/esp
    18660     (clear-stack %ecx)
    18661     # convert
    18662     (parse-mu-var-def _test-input-stream %ecx %esi 0 Stderr 0)
    18663     # var out-addr/esi: (addr stmt)
    18664     (lookup *esi *(esi+4))  # => eax
    18665     89/<- %esi 0/r32/eax
    18666     #
    18667     (check-ints-equal *esi 2 "F - test-parse-mu-var-def/tag")  # Stmt-tag is var-def
    18668     # var v/ecx: (addr var) = lookup(out->var)
    18669     (lookup *(esi+4) *(esi+8))  # Vardef-var Vardef-var => eax
    18670     89/<- %ecx 0/r32/eax
    18671     # v->name
    18672     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    18673     (check-strings-equal %eax "n" "F - test-parse-mu-var-def/var-name")
    18674     # v->register
    18675     (check-ints-equal *(ecx+0x18) 0 "F - test-parse-mu-var-def/var-register")  # Var-register
    18676     # v->block-depth
    18677     (check-ints-equal *(ecx+0x10) 1 "F - test-parse-mu-var-def/output-block-depth")  # Var-block-depth
    18678     # v->type == int
    18679     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
    18680     (check-ints-equal *eax 1 "F - test-parse-mu-var-def/var-type:0")  # Type-tree-is-atom
    18681     (check-ints-equal *(eax+4) 1 "F - test-parse-mu-var-def/var-type:1")  # Type-tree-value
    18682     (check-ints-equal *(eax+0xc) 0 "F - test-parse-mu-var-def/var-type:2")  # Type-tree-right
    18683     # . epilogue
    18684     89/<- %esp 5/r32/ebp
    18685     5d/pop-to-ebp
    18686     c3/return
    18687
    18688 test-parse-mu-reg-var-def:
    18689     # 'var n/eax: int <- copy 0'
    18690     # . prologue
    18691     55/push-ebp
    18692     89/<- %ebp 4/r32/esp
    18693     # setup
    18694     8b/-> *Primitive-type-ids 0/r32/eax
    18695     89/<- *Type-id 0/r32/eax  # stream-write
    18696     (clear-stream _test-input-stream)
    18697     (write _test-input-stream "n/eax: int <- copy 0\n")  # caller has consumed the 'var'
    18698     c7 0/subop/copy *Curr-block-depth 1/imm32
    18699     # var out/esi: (handle stmt)
    18700     68/push 0/imm32
    18701     68/push 0/imm32
    18702     89/<- %esi 4/r32/esp
    18703     # var vars/ecx: (stack (addr var) 16)
    18704     81 5/subop/subtract %esp 0xc0/imm32
    18705     68/push 0xc0/imm32/size
    18706     68/push 0/imm32/top
    18707     89/<- %ecx 4/r32/esp
    18708     (clear-stack %ecx)
    18709     # convert
    18710     (parse-mu-var-def _test-input-stream %ecx %esi 0 Stderr 0)
    18711     # var out-addr/esi: (addr stmt)
    18712     (lookup *esi *(esi+4))  # => eax
    18713     89/<- %esi 0/r32/eax
    18714     #
    18715     (check-ints-equal *esi 3 "F - test-parse-mu-reg-var-def/tag")  # Stmt-tag is reg-var-def
    18716     # var v/ecx: (addr var) = lookup(out->outputs->value)
    18717     # . eax: (addr stmt-var) = lookup(out->outputs)
    18718     (lookup *(esi+0x14) *(esi+0x18))  # Regvardef-outputs Regvardef-outputs => eax
    18719     # .
    18720     (check-ints-equal *(eax+8) 0 "F - test-parse-mu-reg-var-def/single-output")  # Stmt-var-next
    18721     # . eax: (addr var) = lookup(eax->value)
    18722     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    18723     # . ecx = eax
    18724     89/<- %ecx 0/r32/eax
    18725     # v->name
    18726     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    18727     (check-strings-equal %eax "n" "F - test-parse-mu-reg-var-def/output-name")  # Var-name
    18728     # v->register
    18729     (lookup *(ecx+0x18) *(ecx+0x1c))  # Var-register Var-register => eax
    18730     (check-strings-equal %eax "eax" "F - test-parse-mu-reg-var-def/output-register")
    18731     # v->block-depth
    18732     (check-ints-equal *(ecx+0x10) 1 "F - test-parse-mu-reg-var-def/output-block-depth")  # Var-block-depth
    18733     # v->type == int
    18734     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
    18735     (check-ints-equal *eax 1 "F - test-parse-mu-reg-var-def/output-type:0")  # Type-tree-is-atom
    18736     (check-ints-equal *(eax+4) 1 "F - test-parse-mu-reg-var-def/output-type:1")  # Type-tree-value
    18737     (check-ints-equal *(eax+0xc) 0 "F - test-parse-mu-reg-var-def/output-type:2")  # Type-tree-right
    18738     # . epilogue
    18739     89/<- %esp 5/r32/ebp
    18740     5d/pop-to-ebp
    18741     c3/return
    18742
    18743 parse-mu-stmt:  # line: (addr stream byte), vars: (addr stack live-var), fn: (addr function), out: (addr handle stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
    18744     # pseudocode:
    18745     #   var name: slice
    18746     #   allocate(Heap, Stmt-size, out)
    18747     #   var out-addr: (addr stmt) = lookup(*out)
    18748     #   out-addr->tag = stmt
    18749     #   if stmt-has-outputs?(line)
    18750     #     while true
    18751     #       name = next-mu-token(line)
    18752     #       if (name == '<-') break
    18753     #       assert(identifier?(name))
    18754     #       var v: (handle var) = lookup-var(name, vars)
    18755     #       out-addr->outputs = append(v, out-addr->outputs)
    18756     #   add-operation-and-inputs-to-stmt(out-addr, line, vars)
    18757     #
    18758     # . prologue
    18759     55/push-ebp
    18760     89/<- %ebp 4/r32/esp
    18761     # . save registers
    18762     50/push-eax
    18763     51/push-ecx
    18764     52/push-edx
    18765     53/push-ebx
    18766     57/push-edi
    18767     # var name/ecx: slice
    18768     68/push 0/imm32/end
    18769     68/push 0/imm32/start
    18770     89/<- %ecx 4/r32/esp
    18771     # var is-deref?/edx: boolean = false
    18772     ba/copy-to-edx 0/imm32/false
    18773     # var v: (handle var)
    18774     68/push 0/imm32
    18775     68/push 0/imm32
    18776     89/<- %ebx 4/r32/esp
    18777     #
    18778     (allocate Heap *Stmt-size *(ebp+0x14))
    18779     # var out-addr/edi: (addr stmt) = lookup(*out)
    18780     8b/-> *(ebp+0x14) 7/r32/edi
    18781     (lookup *edi *(edi+4))  # => eax
    18782     89/<- %edi 0/r32/eax
    18783     # out-addr->tag = 1/stmt
    18784     c7 0/subop/copy *edi 1/imm32/stmt1  # Stmt-tag
    18785     {
    18786       (stmt-has-outputs? *(ebp+8))
    18787       3d/compare-eax-and 0/imm32/false
    18788       0f 84/jump-if-= break/disp32
    18789       {
    18790 $parse-mu-stmt:read-outputs:
    18791         # name = next-mu-token(line)
    18792         (next-mu-token *(ebp+8) %ecx)
    18793         # if slice-empty?(word-slice) break
    18794         (slice-empty? %ecx)  # => eax
    18795         3d/compare-eax-and 0/imm32/false
    18796         0f 85/jump-if-!= break/disp32
    18797         # if (name == "<-") break
    18798         (slice-equal? %ecx "<-")  # => eax
    18799         3d/compare-eax-and 0/imm32/false
    18800         0f 85/jump-if-!= break/disp32
    18801         # if slice-starts-with?(name, "*") abort
    18802         8b/-> *ecx 0/r32/eax  # Slice-start
    18803         8a/copy-byte *eax 0/r32/AL
    18804         81 4/subop/and %eax 0xff/imm32
    18805         3d/compare-eax-and 0x2a/imm32/asterisk
    18806         0f 84/jump-if-= $parse-mu-stmt:error-output-dereferenced/disp32
    18807         # assert(identifier?(name))
    18808         (identifier? %ecx)  # => eax
    18809         3d/compare-eax-and 0/imm32/false
    18810         0f 84/jump-if-= $parse-mu-stmt:abort/disp32
    18811         #
    18812         (lookup-var %ecx *(ebp+0xc) %ebx *(ebp+0x10) *(ebp+0x18) *(ebp+0x1c))
    18813         8d/copy-address *(edi+0x14) 0/r32/eax  # Stmt1-outputs
    18814         (append-stmt-var Heap  *ebx *(ebx+4)  *(edi+0x14) *(edi+0x18)  0  %eax)  # Stmt1-outputs
    18815         #
    18816         e9/jump loop/disp32
    18817       }
    18818     }
    18819     (add-operation-and-inputs-to-stmt %edi *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x18) *(ebp+0x1c))
    18820 $parse-mu-stmt:end:
    18821     # . reclaim locals
    18822     81 0/subop/add %esp 0x10/imm32
    18823     # . restore registers
    18824     5f/pop-to-edi
    18825     5b/pop-to-ebx
    18826     5a/pop-to-edx
    18827     59/pop-to-ecx
    18828     58/pop-to-eax
    18829     # . epilogue
    18830     89/<- %esp 5/r32/ebp
    18831     5d/pop-to-ebp
    18832     c3/return
    18833
    18834 $parse-mu-stmt:abort:
    18835     # error("invalid identifier '" name "'\n")
    18836     (write-buffered *(ebp+0x18) "fn ")
    18837     8b/-> *(ebp+0x10) 0/r32/eax
    18838     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    18839     (write-buffered *(ebp+0x18) %eax)
    18840     (write-buffered *(ebp+0x18) ": invalid identifier '")
    18841     (write-slice-buffered *(ebp+0x18) %ecx)
    18842     (write-buffered *(ebp+0x18) "'\n")
    18843     (flush *(ebp+0x18))
    18844     (stop *(ebp+0x1c) 1)
    18845     # never gets here
    18846
    18847 $parse-mu-stmt:error-output-dereferenced:
    18848     # error("invalid identifier '" name "'\n")
    18849     (write-buffered *(ebp+0x18) "fn ")
    18850     8b/-> *(ebp+0x10) 0/r32/eax
    18851     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    18852     (write-buffered *(ebp+0x18) %eax)
    18853     (write-buffered *(ebp+0x18) ": output '")
    18854     (write-slice-buffered *(ebp+0x18) %ecx)
    18855     (write-buffered *(ebp+0x18) "' should write to a register, and therefore cannot be dereferenced\n")
    18856     (flush *(ebp+0x18))
    18857     (stop *(ebp+0x1c) 1)
    18858     # never gets here
    18859
    18860 add-operation-and-inputs-to-stmt:  # stmt: (addr stmt), line: (addr stream byte), vars: (addr stack live-var), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    18861     # pseudocode:
    18862     #   stmt->name = slice-to-string(next-mu-token(line))
    18863     #   while true
    18864     #     name = next-mu-token(line)
    18865     #     v = lookup-var-or-literal(name)
    18866     #     stmt->inouts = append(v, stmt->inouts)
    18867     #
    18868     # . prologue
    18869     55/push-ebp
    18870     89/<- %ebp 4/r32/esp
    18871     # . save registers
    18872     50/push-eax
    18873     51/push-ecx
    18874     52/push-edx
    18875     53/push-ebx
    18876     56/push-esi
    18877     57/push-edi
    18878     # edi = stmt
    18879     8b/-> *(ebp+8) 7/r32/edi
    18880     # var name/ecx: slice
    18881     68/push 0/imm32/end
    18882     68/push 0/imm32/start
    18883     89/<- %ecx 4/r32/esp
    18884     # var is-deref?/edx: boolean = false
    18885     ba/copy-to-edx 0/imm32/false
    18886     # var v/esi: (handle var)
    18887     68/push 0/imm32
    18888     68/push 0/imm32
    18889     89/<- %esi 4/r32/esp
    18890 $add-operation-and-inputs-to-stmt:read-operation:
    18891     (next-mu-token *(ebp+0xc) %ecx)
    18892     8d/copy-address *(edi+4) 0/r32/eax  # Stmt1-operation or Regvardef-operationStmt1-operation or Regvardef-operation
    18893     (slice-to-string Heap %ecx %eax)
    18894     # var is-get?/ebx: boolean = (name == "get")
    18895     (slice-equal? %ecx "get")  # => eax
    18896     89/<- %ebx 0/r32/eax
    18897     {
    18898 $add-operation-and-inputs-to-stmt:read-inouts:
    18899       # name = next-mu-token(line)
    18900       (next-mu-token *(ebp+0xc) %ecx)
    18901       # if slice-empty?(word-slice) break
    18902       (slice-empty? %ecx)  # => eax
    18903       3d/compare-eax-and 0/imm32/false
    18904       0f 85/jump-if-!= break/disp32
    18905       # if (name == "<-") abort
    18906       (slice-equal? %ecx "<-")
    18907       3d/compare-eax-and 0/imm32/false
    18908       0f 85/jump-if-!= $add-operation-and-inputs-to-stmt:abort/disp32
    18909       # if (get? && second operand) lookup or create offset
    18910       {
    18911         81 7/subop/compare %ebx 0/imm32/false
    18912         74/jump-if-= break/disp8
    18913         (lookup *(edi+0xc) *(edi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    18914         3d/compare-eax-and 0/imm32
    18915         74/jump-if-= break/disp8
    18916         (lookup-or-create-constant %eax %ecx %esi)
    18917 #?         (lookup *esi *(esi+4))
    18918 #?         (write-buffered Stderr "creating new output var ")
    18919 #?         (write-int32-hex-buffered Stderr %eax)
    18920 #?         (write-buffered Stderr " for field called ")
    18921 #?         (write-slice-buffered Stderr %ecx)
    18922 #?         (write-buffered Stderr "; var name ")
    18923 #?         (lookup *eax *(eax+4))  # Var-name
    18924 #?         (write-buffered Stderr %eax)
    18925 #?         (write-buffered Stderr Newline)
    18926 #?         (flush Stderr)
    18927         e9/jump $add-operation-and-inputs-to-stmt:save-var/disp32
    18928       }
    18929       # is-deref? = false
    18930       ba/copy-to-edx 0/imm32/false
    18931       # if (slice-starts-with?(name, '*')) ++name->start and set is-deref?
    18932       8b/-> *ecx 0/r32/eax  # Slice-start
    18933       8a/copy-byte *eax 0/r32/AL
    18934       81 4/subop/and %eax 0xff/imm32
    18935       3d/compare-eax-and 0x2a/imm32/asterisk
    18936       {
    18937         75/jump-if-!= break/disp8
    18938 $add-operation-and-inputs-to-stmt:inout-is-deref:
    18939         ff 0/subop/increment *ecx
    18940         ba/copy-to-edx 1/imm32/true
    18941       }
    18942       (lookup-var-or-literal %ecx *(ebp+0x10) %esi *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
    18943       # if (deref?) some additional checks
    18944       81 7/subop/compare %edx 0/imm32/false
    18945       {
    18946         74/jump-if-= break/disp8
    18947         # if var is not in register, abort
    18948         (lookup *esi *(esi+4))  # => eax
    18949         81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
    18950         0f 84/jump-if-= $add-operation-and-inputs-to-stmt:error-deref-on-stack/disp32
    18951         # if var is not an address, abort
    18952         (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    18953         (mu-addr-type? %eax)  # => eax
    18954         3d/compare-eax-and 0/imm32/false
    18955         0f 84/jump-if-= $add-operation-and-inputs-to-stmt:error-deref-non-addr/disp32
    18956       }
    18957 $add-operation-and-inputs-to-stmt:save-var:
    18958       8d/copy-address *(edi+0xc) 0/r32/eax
    18959       (append-stmt-var Heap  *esi *(esi+4)  *(edi+0xc) *(edi+0x10)  %edx  %eax)  # Stmt1-inouts or Regvardef-inouts
    18960       #
    18961       e9/jump loop/disp32
    18962     }
    18963 $add-operation-and-inputs-to-stmt:end:
    18964     # . reclaim locals
    18965     81 0/subop/add %esp 0x10/imm32
    18966     # . restore registers
    18967     5f/pop-to-edi
    18968     5e/pop-to-esi
    18969     5b/pop-to-ebx
    18970     5a/pop-to-edx
    18971     59/pop-to-ecx
    18972     58/pop-to-eax
    18973     # . epilogue
    18974     89/<- %esp 5/r32/ebp
    18975     5d/pop-to-ebp
    18976     c3/return
    18977
    18978 $add-operation-and-inputs-to-stmt:abort:
    18979     # error("fn ___: invalid identifier in '" line "'\n")
    18980     (write-buffered *(ebp+0x18) "fn ")
    18981     8b/-> *(ebp+0x14) 0/r32/eax
    18982     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    18983     (write-buffered *(ebp+0x18) %eax)
    18984     (rewind-stream *(ebp+0xc))
    18985     (write-buffered *(ebp+0x18) ": invalid identifier in '")
    18986     (write-stream-data *(ebp+0x18) *(ebp+0xc))
    18987     (write-buffered *(ebp+0x18) "'\n")
    18988     (flush *(ebp+0x18))
    18989     (stop *(ebp+0x1c) 1)
    18990     # never gets here
    18991
    18992 $add-operation-and-inputs-to-stmt:error-deref-on-stack:
    18993     # error("fn ___: cannot dereference var ___ on stack\n")
    18994     (write-buffered *(ebp+0x18) "fn ")
    18995     8b/-> *(ebp+0x14) 0/r32/eax
    18996     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    18997     (write-buffered *(ebp+0x18) %eax)
    18998     (rewind-stream *(ebp+0xc))
    18999     (write-buffered *(ebp+0x18) ": cannot dereference var '")
    19000     (lookup *esi *(esi+4))  # => eax
    19001     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    19002     (write-buffered *(ebp+0x18) %eax)
    19003     (write-buffered *(ebp+0x18) "' on stack\n")
    19004     (flush *(ebp+0x18))
    19005     (stop *(ebp+0x1c) 1)
    19006     # never gets here
    19007
    19008 $add-operation-and-inputs-to-stmt:error-deref-non-addr:
    19009     # error("fn ___: cannot dereference non-addr var ___\n")
    19010     (write-buffered *(ebp+0x18) "fn ")
    19011     8b/-> *(ebp+0x14) 0/r32/eax
    19012     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    19013     (write-buffered *(ebp+0x18) %eax)
    19014     (rewind-stream *(ebp+0xc))
    19015     (write-buffered *(ebp+0x18) ": cannot dereference non-addr var '")
    19016     (lookup *esi *(esi+4))  # => eax
    19017     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    19018     (write-buffered *(ebp+0x18) %eax)
    19019     (write-buffered *(ebp+0x18) "'\n")
    19020     (flush *(ebp+0x18))
    19021     (stop *(ebp+0x1c) 1)
    19022     # never gets here
    19023
    19024 stmt-has-outputs?:  # line: (addr stream byte) -> result/eax: boolean
    19025     # . prologue
    19026     55/push-ebp
    19027     89/<- %ebp 4/r32/esp
    19028     # . save registers
    19029     51/push-ecx
    19030     # var word-slice/ecx: slice
    19031     68/push 0/imm32/end
    19032     68/push 0/imm32/start
    19033     89/<- %ecx 4/r32/esp
    19034     # result = false
    19035     b8/copy-to-eax 0/imm32/false
    19036     (rewind-stream *(ebp+8))
    19037     {
    19038       (next-mu-token *(ebp+8) %ecx)
    19039       # if slice-empty?(word-slice) break
    19040       (slice-empty? %ecx)
    19041       3d/compare-eax-and 0/imm32/false
    19042       b8/copy-to-eax 0/imm32/false/result  # restore result (if we're here it's still false)
    19043       0f 85/jump-if-!= break/disp32
    19044       # if slice-starts-with?(word-slice, '#') break
    19045       # . eax = *word-slice->start
    19046       8b/-> *ecx 0/r32/eax
    19047       8a/copy-byte *eax 0/r32/AL
    19048       81 4/subop/and %eax 0xff/imm32
    19049       # . if (eax == '#') break
    19050       3d/compare-eax-and 0x23/imm32/hash
    19051       b8/copy-to-eax 0/imm32/false/result  # restore result (if we're here it's still false)
    19052       0f 84/jump-if-= break/disp32
    19053       # if slice-equal?(word-slice, '<-') return true
    19054       (slice-equal? %ecx "<-")
    19055       3d/compare-eax-and 0/imm32/false
    19056       74/jump-if-= loop/disp8
    19057       b8/copy-to-eax 1/imm32/true
    19058     }
    19059 $stmt-has-outputs:end:
    19060     (rewind-stream *(ebp+8))
    19061     # . reclaim locals
    19062     81 0/subop/add %esp 8/imm32
    19063     # . restore registers
    19064     59/pop-to-ecx
    19065     # . epilogue
    19066     89/<- %esp 5/r32/ebp
    19067     5d/pop-to-ebp
    19068     c3/return
    19069
    19070 # if 'name' starts with a digit, create a new literal var for it
    19071 # otherwise return first 'name' from the top (back) of 'vars' and abort if not found
    19072 lookup-var-or-literal:  # name: (addr slice), vars: (addr stack live-var), out: (addr handle var), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    19073     # . prologue
    19074     55/push-ebp
    19075     89/<- %ebp 4/r32/esp
    19076     # . save registers
    19077     50/push-eax
    19078     51/push-ecx
    19079     56/push-esi
    19080     # esi = name
    19081     8b/-> *(ebp+8) 6/r32/esi
    19082     # if slice-empty?(name) abort
    19083     (slice-empty? %esi)  # => eax
    19084     3d/compare-eax-and 0/imm32/false
    19085     0f 85/jump-if-!= $lookup-var-or-literal:abort/disp32
    19086     # var c/ecx: byte = *name->start
    19087     8b/-> *esi 1/r32/ecx
    19088     8a/copy-byte *ecx 1/r32/CL
    19089     81 4/subop/and %ecx 0xff/imm32
    19090     # if (decimal-digit?(c) || c == '-') return new var(name)
    19091     {
    19092       81 7/subop/compare %ecx 0x2d/imm32/dash
    19093       74/jump-if-= $lookup-var-or-literal:literal/disp8
    19094       (decimal-digit? %ecx)  # => eax
    19095       3d/compare-eax-and 0/imm32/false
    19096       74/jump-if-= break/disp8
    19097 $lookup-var-or-literal:literal:
    19098       (new-literal-integer Heap %esi *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
    19099       eb/jump $lookup-var-or-literal:end/disp8
    19100     }
    19101     # else if (c == '"') return new var(name)
    19102     {
    19103       81 7/subop/compare %ecx 0x22/imm32/dquote
    19104       75/jump-if-!= break/disp8
    19105 $lookup-var-or-literal:literal-string:
    19106       (new-literal-string Heap %esi *(ebp+0x10))
    19107       eb/jump $lookup-var-or-literal:end/disp8
    19108     }
    19109     # otherwise return lookup-var(name, vars)
    19110     {
    19111 $lookup-var-or-literal:var:
    19112       (lookup-var %esi *(ebp+0xc) *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
    19113     }
    19114 $lookup-var-or-literal:end:
    19115     # . restore registers
    19116     5e/pop-to-esi
    19117     59/pop-to-ecx
    19118     58/pop-to-eax
    19119     # . epilogue
    19120     89/<- %esp 5/r32/ebp
    19121     5d/pop-to-ebp
    19122     c3/return
    19123
    19124 $lookup-var-or-literal:abort:
    19125     (write-buffered *(ebp+0x18) "fn ")
    19126     8b/-> *(ebp+0x14) 0/r32/eax
    19127     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    19128     (write-buffered *(ebp+0x18) %eax)
    19129     (write-buffered *(ebp+0x18) ": empty variable!")
    19130     (flush *(ebp+0x18))
    19131     (stop *(ebp+0x1c) 1)
    19132     # never gets here
    19133
    19134 # return first 'name' from the top (back) of 'vars' and abort if not found
    19135 lookup-var:  # name: (addr slice), vars: (addr stack live-var), out: (addr handle var), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    19136     # . prologue
    19137     55/push-ebp
    19138     89/<- %ebp 4/r32/esp
    19139     # . save registers
    19140     50/push-eax
    19141     #
    19142     (lookup-var-helper *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
    19143     # if (*out == 0) abort
    19144     8b/-> *(ebp+0x10) 0/r32/eax
    19145     81 7/subop/compare *eax 0/imm32
    19146     74/jump-if-= $lookup-var:abort/disp8
    19147 $lookup-var:end:
    19148     # . restore registers
    19149     58/pop-to-eax
    19150     # . epilogue
    19151     89/<- %esp 5/r32/ebp
    19152     5d/pop-to-ebp
    19153     c3/return
    19154
    19155 $lookup-var:abort:
    19156     (write-buffered *(ebp+0x18) "fn ")
    19157     8b/-> *(ebp+0x14) 0/r32/eax
    19158     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    19159     (write-buffered *(ebp+0x18) %eax)
    19160     (write-buffered *(ebp+0x18) ": unknown variable '")
    19161     (write-slice-buffered *(ebp+0x18) *(ebp+8))
    19162     (write-buffered *(ebp+0x18) "'\n")
    19163     (flush *(ebp+0x18))
    19164     (stop *(ebp+0x1c) 1)
    19165     # never gets here
    19166
    19167 # return first 'name' from the top (back) of 'vars', and 0/null if not found
    19168 # ensure that 'name' if in a register is the topmost variable in that register
    19169 lookup-var-helper:  # name: (addr slice), vars: (addr stack live-var), out: (addr handle var), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    19170     # pseudocode:
    19171     #   var curr: (addr handle var) = &vars->data[vars->top - 12]
    19172     #   var min = vars->data
    19173     #   while curr >= min
    19174     #     var v: (handle var) = *curr
    19175     #     if v->name == name
    19176     #       return
    19177     #     curr -= 12
    19178     #
    19179     # . prologue
    19180     55/push-ebp
    19181     89/<- %ebp 4/r32/esp
    19182     # . save registers
    19183     50/push-eax
    19184     51/push-ecx
    19185     52/push-edx
    19186     53/push-ebx
    19187     56/push-esi
    19188     57/push-edi
    19189     # clear out
    19190     (zero-out *(ebp+0x10) *Handle-size)
    19191     # esi = vars
    19192     8b/-> *(ebp+0xc) 6/r32/esi
    19193     # ebx = vars->top
    19194     8b/-> *esi 3/r32/ebx
    19195     # if (vars->top > vars->size) abort
    19196     3b/compare<- *(esi+4) 0/r32/eax
    19197     0f 8f/jump-if-> $lookup-var-helper:error1/disp32
    19198     # var min/edx: (addr handle var) = vars->data
    19199     8d/copy-address *(esi+8) 2/r32/edx
    19200     # var curr/ebx: (addr handle var) = &vars->data[vars->top - 12]
    19201     8d/copy-address *(esi+ebx-4) 3/r32/ebx  # vars + 8 + vars->type - 12
    19202     # var var-in-reg/edi: 16 addrs
    19203     68/push 0/imm32
    19204     68/push 0/imm32
    19205     68/push 0/imm32
    19206     68/push 0/imm32
    19207     68/push 0/imm32
    19208     68/push 0/imm32
    19209     68/push 0/imm32
    19210     68/push 0/imm32
    19211     68/push 0/imm32
    19212     68/push 0/imm32
    19213     68/push 0/imm32
    19214     68/push 0/imm32
    19215     68/push 0/imm32
    19216     68/push 0/imm32
    19217     68/push 0/imm32
    19218     68/push 0/imm32
    19219     89/<- %edi 4/r32/esp
    19220     {
    19221 $lookup-var-helper:loop:
    19222       # if (curr < min) return
    19223       39/compare %ebx 2/r32/edx
    19224       0f 82/jump-if-addr< break/disp32
    19225       # var v/ecx: (addr var) = lookup(*curr)
    19226       (lookup *ebx *(ebx+4))  # => eax
    19227       89/<- %ecx 0/r32/eax
    19228       # var vn/eax: (addr array byte) = lookup(v->name)
    19229       (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    19230       # if (vn == name) return curr
    19231       (slice-equal? *(ebp+8) %eax)  # => eax
    19232       3d/compare-eax-and 0/imm32/false
    19233       {
    19234         74/jump-if-= break/disp8
    19235 $lookup-var-helper:found:
    19236         # var vr/eax: (addr array byte) = lookup(v->register)
    19237         (lookup *(ecx+0x18) *(ecx+0x1c))  # Var-register Var-register => eax
    19238         3d/compare-eax-and 0/imm32
    19239         {
    19240           74/jump-if-= break/disp8
    19241 $lookup-var-helper:found-register:
    19242           # var reg/eax: int = get(Registers, vr)
    19243           (get Mu-registers-unique %eax 0xc "Mu-registers-unique")  # => eax
    19244           8b/-> *eax 0/r32/eax
    19245           # if (var-in-reg[reg]) error
    19246           8b/-> *(edi+eax<<2) 0/r32/eax
    19247           3d/compare-eax-and 0/imm32
    19248           0f 85/jump-if-!= $lookup-var-helper:error2/disp32
    19249         }
    19250 $lookup-var-helper:return:
    19251         # esi = out
    19252         8b/-> *(ebp+0x10) 6/r32/esi
    19253         # *out = *curr
    19254         8b/-> *ebx 0/r32/eax
    19255         89/<- *esi 0/r32/eax
    19256         8b/-> *(ebx+4) 0/r32/eax
    19257         89/<- *(esi+4) 0/r32/eax
    19258         # return
    19259         eb/jump $lookup-var-helper:end/disp8
    19260       }
    19261       # 'name' not yet found; update var-in-reg if v in register
    19262       # . var vr/eax: (addr array byte) = lookup(v->register)
    19263       (lookup *(ecx+0x18) *(ecx+0x1c))  # Var-register Var-register => eax
    19264       # . if (vr == 0) continue
    19265       3d/compare-eax-and 0/imm32
    19266       74/jump-if-= $lookup-var-helper:continue/disp8
    19267       # . var reg/eax: int = get(Registers, vr)
    19268       (get Mu-registers-unique %eax 0xc "Mu-registers-unique")  # => eax
    19269       8b/-> *eax 0/r32/eax
    19270       # . var-in-reg[reg] = v
    19271       89/<- *(edi+eax<<2) 1/r32/ecx
    19272 $lookup-var-helper:continue:
    19273       # curr -= 12
    19274       81 5/subop/subtract %ebx 0xc/imm32
    19275       e9/jump loop/disp32
    19276     }
    19277 $lookup-var-helper:end:
    19278     # . reclaim locals
    19279     81 0/subop/add %esp 0x40/imm32
    19280     # . restore registers
    19281     5f/pop-to-edi
    19282     5e/pop-to-esi
    19283     5b/pop-to-ebx
    19284     5a/pop-to-edx
    19285     59/pop-to-ecx
    19286     58/pop-to-eax
    19287     # . epilogue
    19288     89/<- %esp 5/r32/ebp
    19289     5d/pop-to-ebp
    19290     c3/return
    19291
    19292 $lookup-var-helper:error1:
    19293     (write-buffered *(ebp+0x18) "fn ")
    19294     8b/-> *(ebp+0x14) 0/r32/eax
    19295     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    19296     (write-buffered *(ebp+0x18) %eax)
    19297     (write-buffered *(ebp+0x18) ": malformed stack when looking up '")
    19298     (write-slice-buffered *(ebp+0x18) *(ebp+8))
    19299     (write-buffered *(ebp+0x18) "'\n")
    19300     (flush *(ebp+0x18))
    19301     (stop *(ebp+0x1c) 1)
    19302     # never gets here
    19303
    19304 $lookup-var-helper:error2:
    19305     # eax contains the conflicting var at this point
    19306     (write-buffered *(ebp+0x18) "fn ")
    19307     50/push-eax
    19308     8b/-> *(ebp+0x14) 0/r32/eax
    19309     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    19310     (write-buffered *(ebp+0x18) %eax)
    19311     58/pop-eax
    19312     (write-buffered *(ebp+0x18) ": register ")
    19313     50/push-eax
    19314     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    19315     (write-buffered *(ebp+0x18) %eax)
    19316     58/pop-to-eax
    19317     (write-buffered *(ebp+0x18) " reads var '")
    19318     (write-slice-buffered *(ebp+0x18) *(ebp+8))
    19319     (write-buffered *(ebp+0x18) "' after writing var '")
    19320     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    19321     (write-buffered *(ebp+0x18) %eax)
    19322     (write-buffered *(ebp+0x18) "'\n")
    19323     (flush *(ebp+0x18))
    19324     (stop *(ebp+0x1c) 1)
    19325     # never gets here
    19326
    19327 dump-vars:  # vars: (addr stack live-var)
    19328     # pseudocode:
    19329     #   var curr: (addr handle var) = &vars->data[vars->top - 12]
    19330     #   var min = vars->data
    19331     #   while curr >= min
    19332     #     var v: (handle var) = *curr
    19333     #     print v
    19334     #     curr -= 12
    19335     #
    19336     # . prologue
    19337     55/push-ebp
    19338     89/<- %ebp 4/r32/esp
    19339     # . save registers
    19340     52/push-edx
    19341     53/push-ebx
    19342     56/push-esi
    19343     # esi = vars
    19344     8b/-> *(ebp+8) 6/r32/esi
    19345     # ebx = vars->top
    19346     8b/-> *esi 3/r32/ebx
    19347     # var min/edx: (addr handle var) = vars->data
    19348     8d/copy-address *(esi+8) 2/r32/edx
    19349     # var curr/ebx: (addr handle var) = &vars->data[vars->top - 12]
    19350     8d/copy-address *(esi+ebx-4) 3/r32/ebx  # vars + 8 + vars->type - 12
    19351     {
    19352 $dump-vars:loop:
    19353       # if (curr < min) return
    19354       39/compare %ebx 2/r32/edx
    19355       0f 82/jump-if-addr< break/disp32
    19356       #
    19357       (write-buffered Stderr "  var@")
    19358       (dump-var 2 %ebx)
    19359       # curr -= 12
    19360       81 5/subop/subtract %ebx 0xc/imm32
    19361       e9/jump loop/disp32
    19362     }
    19363 $dump-vars:end:
    19364     # . restore registers
    19365     5e/pop-to-esi
    19366     5b/pop-to-ebx
    19367     5a/pop-to-edx
    19368     # . epilogue
    19369     89/<- %esp 5/r32/ebp
    19370     5d/pop-to-ebp
    19371     c3/return
    19372
    19373 == data
    19374 # Like Registers, but no esp or ebp
    19375 Mu-registers:  # (addr stream {(handle array byte), int})
    19376   # a table is a stream
    19377   0xa8/imm32/write
    19378   0/imm32/read
    19379   0xa8/imm32/length
    19380   # data
    19381   # general-purpose registers
    19382   # it is perfectly ok to use fake alloc-ids -- as long as you never try to reclaim them
    19383   0x11/imm32/alloc-id $Mu-register-eax/imm32 0/imm32
    19384   0x11/imm32/alloc-id $Mu-register-ecx/imm32 1/imm32
    19385   0x11/imm32/alloc-id $Mu-register-edx/imm32 2/imm32
    19386   0x11/imm32/alloc-id $Mu-register-ebx/imm32 3/imm32
    19387   0x11/imm32/alloc-id $Mu-register-esi/imm32 6/imm32
    19388   0x11/imm32/alloc-id $Mu-register-edi/imm32 7/imm32
    19389   # floating-point registers
    19390   0x11/imm32/alloc-id $Mu-register-xmm0/imm32 0/imm32
    19391   0x11/imm32/alloc-id $Mu-register-xmm1/imm32 1/imm32
    19392   0x11/imm32/alloc-id $Mu-register-xmm2/imm32 2/imm32
    19393   0x11/imm32/alloc-id $Mu-register-xmm3/imm32 3/imm32
    19394   0x11/imm32/alloc-id $Mu-register-xmm4/imm32 4/imm32
    19395   0x11/imm32/alloc-id $Mu-register-xmm5/imm32 5/imm32
    19396   0x11/imm32/alloc-id $Mu-register-xmm6/imm32 6/imm32
    19397   0x11/imm32/alloc-id $Mu-register-xmm7/imm32 7/imm32
    19398
    19399 # Like Mu-registers, but with unique codes for integer and floating-point
    19400 # registers.
    19401 # Don't use this for code-generation, only for checking.
    19402 Mu-registers-unique:  # (addr stream {(handle array byte), int})
    19403   # a table is a stream
    19404   0xa8/imm32/write
    19405   0/imm32/read
    19406   0xa8/imm32/length
    19407   # data
    19408   # general-purpose registers
    19409   0x11/imm32/alloc-id $Mu-register-eax/imm32 0/imm32
    19410   0x11/imm32/alloc-id $Mu-register-ecx/imm32 1/imm32
    19411   0x11/imm32/alloc-id $Mu-register-edx/imm32 2/imm32
    19412   0x11/imm32/alloc-id $Mu-register-ebx/imm32 3/imm32
    19413   0x11/imm32/alloc-id $Mu-register-esi/imm32 6/imm32
    19414   0x11/imm32/alloc-id $Mu-register-edi/imm32 7/imm32
    19415   # floating-point registers
    19416   0x11/imm32/alloc-id $Mu-register-xmm0/imm32 8/imm32
    19417   0x11/imm32/alloc-id $Mu-register-xmm1/imm32 9/imm32
    19418   0x11/imm32/alloc-id $Mu-register-xmm2/imm32 0xa/imm32
    19419   0x11/imm32/alloc-id $Mu-register-xmm3/imm32 0xb/imm32
    19420   0x11/imm32/alloc-id $Mu-register-xmm4/imm32 0xc/imm32
    19421   0x11/imm32/alloc-id $Mu-register-xmm5/imm32 0xd/imm32
    19422   0x11/imm32/alloc-id $Mu-register-xmm6/imm32 0xe/imm32
    19423   0x11/imm32/alloc-id $Mu-register-xmm7/imm32 0xf/imm32
    19424
    19425 $Mu-register-eax:
    19426   0x11/imm32/alloc-id
    19427   3/imm32/size
    19428   0x65/e 0x61/a 0x78/x
    19429
    19430 $Mu-register-ecx:
    19431   0x11/imm32/alloc-id
    19432   3/imm32/size
    19433   0x65/e 0x63/c 0x78/x
    19434
    19435 $Mu-register-edx:
    19436   0x11/imm32/alloc-id
    19437   3/imm32/size
    19438   0x65/e 0x64/d 0x78/x
    19439
    19440 $Mu-register-ebx:
    19441   0x11/imm32/alloc-id
    19442   3/imm32/size
    19443   0x65/e 0x62/b 0x78/x
    19444
    19445 $Mu-register-esi:
    19446   0x11/imm32/alloc-id
    19447   3/imm32/size
    19448   0x65/e 0x73/s 0x69/i
    19449
    19450 $Mu-register-edi:
    19451   0x11/imm32/alloc-id
    19452   3/imm32/size
    19453   0x65/e 0x64/d 0x69/i
    19454
    19455 $Mu-register-xmm0:
    19456   0x11/imm32/alloc-id:fake:payload
    19457   # "xmm0"
    19458   0x4/imm32/size
    19459   0x78/x 0x6d/m 0x6d/m 0x30/0
    19460
    19461 $Mu-register-xmm1:
    19462   0x11/imm32/alloc-id:fake:payload
    19463   # "xmm1"
    19464   0x4/imm32/size
    19465   0x78/x 0x6d/m 0x6d/m 0x31/1
    19466
    19467 $Mu-register-xmm2:
    19468   0x11/imm32/alloc-id:fake:payload
    19469   # "xmm2"
    19470   0x4/imm32/size
    19471   0x78/x 0x6d/m 0x6d/m 0x32/2
    19472
    19473 $Mu-register-xmm3:
    19474   0x11/imm32/alloc-id:fake:payload
    19475   # "xmm3"
    19476   0x4/imm32/size
    19477   0x78/x 0x6d/m 0x6d/m 0x33/3
    19478
    19479 $Mu-register-xmm4:
    19480   0x11/imm32/alloc-id:fake:payload
    19481   # "xmm4"
    19482   0x4/imm32/size
    19483   0x78/x 0x6d/m 0x6d/m 0x34/4
    19484
    19485 $Mu-register-xmm5:
    19486   0x11/imm32/alloc-id:fake:payload
    19487   # "xmm5"
    19488   0x4/imm32/size
    19489   0x78/x 0x6d/m 0x6d/m 0x35/5
    19490
    19491 $Mu-register-xmm6:
    19492   0x11/imm32/alloc-id:fake:payload
    19493   # "xmm6"
    19494   0x4/imm32/size
    19495   0x78/x 0x6d/m 0x6d/m 0x36/6
    19496
    19497 $Mu-register-xmm7:
    19498   0x11/imm32/alloc-id:fake:payload
    19499   # "xmm7"
    19500   0x4/imm32/size
    19501   0x78/x 0x6d/m 0x6d/m 0x37/7
    19502
    19503 == code
    19504
    19505 # push 'out' to 'vars' if not already there; it's assumed to be a fn output
    19506 maybe-define-var:  # out: (handle var), vars: (addr stack live-var)
    19507     # . prologue
    19508     55/push-ebp
    19509     89/<- %ebp 4/r32/esp
    19510     # . save registers
    19511     50/push-eax
    19512     # var out-addr/eax: (addr var)
    19513     (lookup *(ebp+8) *(ebp+0xc))  # => eax
    19514     #
    19515     (binding-exists? %eax *(ebp+0x10))  # => eax
    19516     3d/compare-eax-and 0/imm32/false
    19517     75/jump-if-!= $maybe-define-var:end/disp8
    19518     # otherwise update vars
    19519     (push *(ebp+0x10) *(ebp+8))
    19520     (push *(ebp+0x10) *(ebp+0xc))
    19521     (push *(ebp+0x10) 0)  # 'out' is always a fn output; never spill it
    19522 $maybe-define-var:end:
    19523     # . restore registers
    19524     58/pop-to-eax
    19525     # . epilogue
    19526     89/<- %esp 5/r32/ebp
    19527     5d/pop-to-ebp
    19528     c3/return
    19529
    19530 # simpler version of lookup-var-helper
    19531 binding-exists?:  # target: (addr var), vars: (addr stack live-var) -> result/eax: boolean
    19532     # pseudocode:
    19533     #   var curr: (addr handle var) = &vars->data[vars->top - 12]
    19534     #   var min = vars->data
    19535     #   while curr >= min
    19536     #     var v: (handle var) = *curr
    19537     #     if v->name == target->name
    19538     #       return true
    19539     #     curr -= 12
    19540     #   return false
    19541     #
    19542     # . prologue
    19543     55/push-ebp
    19544     89/<- %ebp 4/r32/esp
    19545     # . save registers
    19546     51/push-ecx
    19547     52/push-edx
    19548     56/push-esi
    19549     # var target-name/ecx: (addr array byte) = lookup(target->name)
    19550     8b/-> *(ebp+8) 0/r32/eax
    19551     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    19552     89/<- %ecx 0/r32/eax
    19553     # esi = vars
    19554     8b/-> *(ebp+0xc) 6/r32/esi
    19555     # eax = vars->top
    19556     8b/-> *esi 0/r32/eax
    19557     # var min/edx: (addr handle var) = vars->data
    19558     8d/copy-address *(esi+8) 2/r32/edx
    19559     # var curr/esi: (addr handle var) = &vars->data[vars->top - 12]
    19560     8d/copy-address *(esi+eax-4) 6/r32/esi  # vars + 8 + vars->type - 12
    19561     {
    19562 $binding-exists?:loop:
    19563       # if (curr < min) return
    19564       39/compare %esi 2/r32/edx
    19565       0f 82/jump-if-addr< break/disp32
    19566       # var v/eax: (addr var) = lookup(*curr)
    19567       (lookup *esi *(esi+4))  # => eax
    19568       # var vn/eax: (addr array byte) = lookup(v->name)
    19569       (lookup *eax *(eax+4))  # Var-name Var-name => eax
    19570       # if (vn == target-name) return true
    19571       (string-equal? %ecx %eax)  # => eax
    19572       3d/compare-eax-and 0/imm32/false
    19573       75/jump-if-!= $binding-exists?:end/disp8  # eax already contains true
    19574       # curr -= 12
    19575       81 5/subop/subtract %esi 0xc/imm32
    19576       e9/jump loop/disp32
    19577     }
    19578     b8/copy-to-eax 0/imm32/false
    19579 $binding-exists?:end:
    19580     # . restore registers
    19581     5e/pop-to-esi
    19582     5a/pop-to-edx
    19583     59/pop-to-ecx
    19584     # . epilogue
    19585     89/<- %esp 5/r32/ebp
    19586     5d/pop-to-ebp
    19587     c3/return
    19588
    19589 test-parse-mu-stmt:
    19590     # . prologue
    19591     55/push-ebp
    19592     89/<- %ebp 4/r32/esp
    19593     # setup
    19594     8b/-> *Primitive-type-ids 0/r32/eax
    19595     89/<- *Type-id 0/r32/eax  # stream-write
    19596     (clear-stream _test-input-stream)
    19597     (write _test-input-stream "increment n\n")
    19598     # var vars/ecx: (stack (addr var) 16)
    19599     81 5/subop/subtract %esp 0xc0/imm32
    19600     68/push 0xc0/imm32/size
    19601     68/push 0/imm32/top
    19602     89/<- %ecx 4/r32/esp
    19603     (clear-stack %ecx)
    19604     # var v/edx: (handle var)
    19605     68/push 0/imm32
    19606     68/push 0/imm32
    19607     89/<- %edx 4/r32/esp
    19608     # var s/eax: (handle array byte)
    19609     68/push 0/imm32
    19610     68/push 0/imm32
    19611     89/<- %eax 4/r32/esp
    19612     # v = new var("n")
    19613     (copy-array Heap "n" %eax)
    19614     (new-var Heap *eax *(eax+4) %edx)
    19615     #
    19616     (push %ecx *edx)
    19617     (push %ecx *(edx+4))
    19618     (push %ecx 0)
    19619     # var out/eax: (handle stmt)
    19620     68/push 0/imm32
    19621     68/push 0/imm32
    19622     89/<- %eax 4/r32/esp
    19623     # convert
    19624     (parse-mu-stmt _test-input-stream %ecx 0 %eax Stderr 0)
    19625     # var out-addr/edx: (addr stmt) = lookup(*out)
    19626     (lookup *eax *(eax+4))  # => eax
    19627     89/<- %edx 0/r32/eax
    19628     # out->tag
    19629     (check-ints-equal *edx 1 "F - test-parse-mu-stmt/tag")  # Stmt-tag is Stmt1
    19630     # out->operation
    19631     (lookup *(edx+4) *(edx+8))  # Stmt1-operation Stmt1-operation => eax
    19632     (check-strings-equal %eax "increment" "F - test-parse-mu-stmt/name")  # Stmt1-operation
    19633     # out->inouts->value->name
    19634     # . eax = out->inouts
    19635     (lookup *(edx+0xc) *(edx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    19636     # . eax = out->inouts->value
    19637     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    19638     # . eax = out->inouts->value->name
    19639     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    19640     # .
    19641     (check-strings-equal %eax "n" "F - test-parse-mu-stmt/inout:0")
    19642     # . epilogue
    19643     89/<- %esp 5/r32/ebp
    19644     5d/pop-to-ebp
    19645     c3/return
    19646
    19647 test-parse-mu-stmt-with-comma:
    19648     # . prologue
    19649     55/push-ebp
    19650     89/<- %ebp 4/r32/esp
    19651     # setup
    19652     8b/-> *Primitive-type-ids 0/r32/eax
    19653     89/<- *Type-id 0/r32/eax  # stream-write
    19654     (clear-stream _test-input-stream)
    19655     (write _test-input-stream "copy-to n, 3\n")
    19656     # var vars/ecx: (stack (addr var) 16)
    19657     81 5/subop/subtract %esp 0xc0/imm32
    19658     68/push 0xc0/imm32/size
    19659     68/push 0/imm32/top
    19660     89/<- %ecx 4/r32/esp
    19661     (clear-stack %ecx)
    19662     # var v/edx: (handle var)
    19663     68/push 0/imm32
    19664     68/push 0/imm32
    19665     89/<- %edx 4/r32/esp
    19666     # var s/eax: (handle array byte)
    19667     68/push 0/imm32
    19668     68/push 0/imm32
    19669     89/<- %eax 4/r32/esp
    19670     # v = new var("n")
    19671     (copy-array Heap "n" %eax)
    19672     (new-var Heap *eax *(eax+4) %edx)
    19673     #
    19674     (push %ecx *edx)
    19675     (push %ecx *(edx+4))
    19676     (push %ecx 0)
    19677     # var out/eax: (handle stmt)
    19678     68/push 0/imm32
    19679     68/push 0/imm32
    19680     89/<- %eax 4/r32/esp
    19681     # convert
    19682     (parse-mu-stmt _test-input-stream %ecx 0 %eax Stderr 0)
    19683     # var out-addr/edx: (addr stmt) = lookup(*out)
    19684     (lookup *eax *(eax+4))  # => eax
    19685     89/<- %edx 0/r32/eax
    19686     # out->tag
    19687     (check-ints-equal *edx 1 "F - test-parse-mu-stmt-with-comma/tag")  # Stmt-tag is Stmt1
    19688     # out->operation
    19689     (lookup *(edx+4) *(edx+8))  # Stmt1-operation Stmt1-operation => eax
    19690     (check-strings-equal %eax "copy-to" "F - test-parse-mu-stmt-with-comma/name")  # Stmt1-operation
    19691     # out->inouts->value->name
    19692     # . eax = out->inouts
    19693     (lookup *(edx+0xc) *(edx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    19694     # . eax = out->inouts->value
    19695     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    19696     # . eax = out->inouts->value->name
    19697     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    19698     # .
    19699     (check-strings-equal %eax "n" "F - test-parse-mu-stmt-with-comma/inout:0")
    19700     # . epilogue
    19701     89/<- %esp 5/r32/ebp
    19702     5d/pop-to-ebp
    19703     c3/return
    19704
    19705 new-var:  # ad: (addr allocation-descriptor), name: (handle array byte), out: (addr handle var)
    19706     # . prologue
    19707     55/push-ebp
    19708     89/<- %ebp 4/r32/esp
    19709     # . save registers
    19710     50/push-eax
    19711     51/push-ecx
    19712     # ecx = out
    19713     8b/-> *(ebp+0x14) 1/r32/ecx
    19714     #
    19715     (allocate *(ebp+8) *Var-size %ecx)
    19716     # var out-addr/eax: (addr var)
    19717     (lookup *ecx *(ecx+4))  # => eax
    19718     # out-addr->name = name
    19719     8b/-> *(ebp+0xc) 1/r32/ecx
    19720     89/<- *eax 1/r32/ecx  # Var-name
    19721     8b/-> *(ebp+0x10) 1/r32/ecx
    19722     89/<- *(eax+4) 1/r32/ecx  # Var-name
    19723 #?     (write-buffered Stderr "var ")
    19724 #?     (lookup *(ebp+0xc) *(ebp+0x10))
    19725 #?     (write-buffered Stderr %eax)
    19726 #?     (write-buffered Stderr " at ")
    19727 #?     8b/-> *(ebp+0x14) 1/r32/ecx
    19728 #?     (lookup *ecx *(ecx+4))  # => eax
    19729 #?     (write-int32-hex-buffered Stderr %eax)
    19730 #?     (write-buffered Stderr Newline)
    19731 #?     (flush Stderr)
    19732 $new-var:end:
    19733     # . restore registers
    19734     59/pop-to-ecx
    19735     58/pop-to-eax
    19736     # . epilogue
    19737     89/<- %esp 5/r32/ebp
    19738     5d/pop-to-ebp
    19739     c3/return
    19740
    19741 # WARNING: modifies name
    19742 new-literal-integer:  # ad: (addr allocation-descriptor), name: (addr slice), out: (addr handle var), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    19743     # . prologue
    19744     55/push-ebp
    19745     89/<- %ebp 4/r32/esp
    19746     # . save registers
    19747     50/push-eax
    19748     51/push-ecx
    19749     # first strip out metadata
    19750     8b/-> *(ebp+0xc) 1/r32/ecx
    19751     (next-token-from-slice *ecx *(ecx+4) 0x2f *(ebp+0xc))
    19752     # if (!is-hex-int?(name)) abort
    19753     (hex-int? *(ebp+0xc))  # => eax
    19754     3d/compare-eax-and 0/imm32/false
    19755     0f 84/jump-if-= $new-literal-integer:abort/disp32
    19756     # a little more error-checking
    19757     (check-mu-hex-int *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
    19758     # out = new var(s)
    19759     (new-var-from-slice *(ebp+8) *(ebp+0xc) *(ebp+0x10))
    19760     # var out-addr/ecx: (addr var) = lookup(*out)
    19761     8b/-> *(ebp+0x10) 0/r32/eax
    19762     (lookup *eax *(eax+4))  # => eax
    19763     89/<- %ecx 0/r32/eax
    19764     # out-addr->block-depth = *Curr-block-depth
    19765     8b/-> *Curr-block-depth 0/r32/eax
    19766     89/<- *(ecx+0x10) 0/r32/eax  # Var-block-depth
    19767     # out-addr->type = new tree()
    19768     8d/copy-address *(ecx+8) 0/r32/eax  # Var-type
    19769     (allocate *(ebp+8) *Type-tree-size %eax)
    19770     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
    19771     c7 0/subop/copy *eax 1/imm32/true  # Type-tree-is-atom
    19772     # nothing else to do; default type is 'literal'
    19773 $new-literal-integer:end:
    19774     # . reclaim locals
    19775     81 0/subop/add %esp 8/imm32
    19776     # . restore registers
    19777     59/pop-to-ecx
    19778     58/pop-to-eax
    19779     # . epilogue
    19780     89/<- %esp 5/r32/ebp
    19781     5d/pop-to-ebp
    19782     c3/return
    19783
    19784 $new-literal-integer:abort:
    19785     (write-buffered *(ebp+0x18) "fn ")
    19786     8b/-> *(ebp+0x14) 0/r32/eax
    19787     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    19788     (write-buffered *(ebp+0x18) %eax)
    19789     (write-buffered *(ebp+0x18) ": variable '")
    19790     (write-slice-buffered *(ebp+0x18) *(ebp+0xc))
    19791     (write-buffered *(ebp+0x18) "' cannot begin with a digit (or do you have a typo in a number?)\n")
    19792     (flush *(ebp+0x18))
    19793     (stop *(ebp+0x1c) 1)
    19794     # never gets here
    19795
    19796 # precondition: name is a valid hex integer; require a '0x' prefix
    19797 check-mu-hex-int:  # name: (addr slice), err: (addr buffered-file), ed: (addr exit-descriptor)
    19798     # . prologue
    19799     55/push-ebp
    19800     89/<- %ebp 4/r32/esp
    19801     # . save registers
    19802     50/push-eax
    19803     51/push-ecx
    19804     52/push-edx
    19805     # ecx = name
    19806     8b/-> *(ebp+8) 1/r32/ecx
    19807     # var start/edx: (addr byte) = name->start
    19808     8b/-> *ecx 2/r32/edx
    19809     # if (*start == '-') ++start
    19810     b8/copy-to-eax 0/imm32
    19811     8a/copy-byte *edx 0/r32/AL
    19812     3d/compare-eax-and 0x2d/imm32/dash
    19813     {
    19814       75/jump-if-!= break/disp8
    19815       42/increment-edx
    19816     }
    19817     # var end/ecx: (addr byte) = name->end
    19818     8b/-> *(ecx+4) 1/r32/ecx
    19819     # var len/eax: int = name->end - name->start
    19820     89/<- %eax 1/r32/ecx
    19821     29/subtract-from %eax 2/r32/edx
    19822     # if (len <= 1) return
    19823     3d/compare-eax-with 1/imm32
    19824     0f 8e/jump-if-<= $check-mu-hex-int:end/disp32
    19825 $check-mu-hex-int:length->-1:
    19826     # if slice-starts-with?({start, end}, "0x") return
    19827     # . var tmp = {start, end}
    19828     51/push-ecx
    19829     52/push-edx
    19830     89/<- %eax 4/r32/esp
    19831     # .
    19832     (slice-starts-with? %eax "0x")  # => eax
    19833     # . reclaim tmp
    19834     81 0/subop/add %esp 8/imm32
    19835     # .
    19836     3d/compare-eax-with 0/imm32/false
    19837     75/jump-if-!= $check-mu-hex-int:end/disp8
    19838 $check-mu-hex-int:abort:
    19839     # otherwise abort
    19840     (write-buffered *(ebp+0xc) "literal integers are always hex in Mu; start '")
    19841     (write-slice-buffered *(ebp+0xc) *(ebp+8))
    19842     (write-buffered *(ebp+0xc) "' with a '0x' to be unambiguous, converting it to hexadecimal as necessary.\n")
    19843     (flush *(ebp+0xc))
    19844     (stop *(ebp+0x10) 1)
    19845 $check-mu-hex-int:end:
    19846     # . restore registers
    19847     5a/pop-to-edx
    19848     59/pop-to-ecx
    19849     58/pop-to-eax
    19850     # . epilogue
    19851     89/<- %esp 5/r32/ebp
    19852     5d/pop-to-ebp
    19853     c3/return
    19854
    19855 new-literal:  # ad: (addr allocation-descriptor), name: (addr slice), out: (addr handle var)
    19856     # . prologue
    19857     55/push-ebp
    19858     89/<- %ebp 4/r32/esp
    19859     # . save registers
    19860     50/push-eax
    19861     51/push-ecx
    19862     # var s/ecx: (handle array byte)
    19863     68/push 0/imm32
    19864     68/push 0/imm32
    19865     89/<- %ecx 4/r32/esp
    19866     # s = slice-to-string(name)
    19867     (slice-to-string Heap *(ebp+0xc) %ecx)
    19868     # allocate to out
    19869     (new-var *(ebp+8) *ecx *(ecx+4) *(ebp+0x10))
    19870     # var out-addr/ecx: (addr var) = lookup(*out)
    19871     8b/-> *(ebp+0x10) 1/r32/ecx
    19872     (lookup *ecx *(ecx+4))  # => eax
    19873     89/<- %ecx 0/r32/eax
    19874     # out-addr->block-depth = *Curr-block-depth
    19875     8b/-> *Curr-block-depth 0/r32/eax
    19876     89/<- *(ecx+0x10) 0/r32/eax  # Var-block-depth
    19877     # out-addr->type/eax = new type
    19878     8d/copy-address *(ecx+8) 0/r32/eax  # Var-type
    19879     (allocate *(ebp+8) *Type-tree-size %eax)
    19880     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
    19881     # nothing else to do; default type is 'literal'
    19882     c7 0/subop/copy *eax 1/imm32/true  # Type-tree-is-atom
    19883 $new-literal:end:
    19884     # . reclaim locals
    19885     81 0/subop/add %esp 8/imm32
    19886     # . restore registers
    19887     59/pop-to-ecx
    19888     58/pop-to-eax
    19889     # . epilogue
    19890     89/<- %esp 5/r32/ebp
    19891     5d/pop-to-ebp
    19892     c3/return
    19893
    19894 new-literal-string:  # ad: (addr allocation-descriptor), name: (addr slice), out: (addr handle var)
    19895     # . prologue
    19896     55/push-ebp
    19897     89/<- %ebp 4/r32/esp
    19898     # . save registers
    19899     50/push-eax
    19900     51/push-ecx
    19901     # var s/ecx: (handle array byte)
    19902     68/push 0/imm32
    19903     68/push 0/imm32
    19904     89/<- %ecx 4/r32/esp
    19905     # s = slice-to-string(name)
    19906     (slice-to-string Heap *(ebp+0xc) %ecx)
    19907     # allocate to out
    19908     (new-var *(ebp+8) *ecx *(ecx+4) *(ebp+0x10))
    19909     # var out-addr/ecx: (addr var) = lookup(*out)
    19910     8b/-> *(ebp+0x10) 1/r32/ecx
    19911     (lookup *ecx *(ecx+4))  # => eax
    19912     89/<- %ecx 0/r32/eax
    19913     # out-addr->block-depth = *Curr-block-depth
    19914     8b/-> *Curr-block-depth 0/r32/eax
    19915     89/<- *(ecx+0x10) 0/r32/eax  # Var-block-depth
    19916     # out-addr->type/eax = new type
    19917     8d/copy-address *(ecx+8) 0/r32/eax  # Var-type
    19918     (allocate *(ebp+8) *Type-tree-size %eax)
    19919     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
    19920     # out-addr->type->value = literal-string
    19921     c7 0/subop/copy *(eax+4) 0x10/imm32/type-id-string-literal  # Type-tree-value
    19922     # out-addr->type->is-atom? = true
    19923     c7 0/subop/copy *eax 1/imm32/true  # Type-tree-is-atom
    19924 $new-literal-string:end:
    19925     # . reclaim locals
    19926     81 0/subop/add %esp 8/imm32
    19927     # . restore registers
    19928     59/pop-to-ecx
    19929     58/pop-to-eax
    19930     # . epilogue
    19931     89/<- %esp 5/r32/ebp
    19932     5d/pop-to-ebp
    19933     c3/return
    19934
    19935 new-var-from-slice:  # ad: (addr allocation-descriptor), name: (addr slice), out: (addr handle var)
    19936     # . prologue
    19937     55/push-ebp
    19938     89/<- %ebp 4/r32/esp
    19939     # . save registers
    19940     51/push-ecx
    19941     # var tmp/ecx: (handle array byte)
    19942     68/push 0/imm32
    19943     68/push 0/imm32
    19944     89/<- %ecx 4/r32/esp
    19945     # tmp = slice-to-string(name)
    19946     (slice-to-string Heap *(ebp+0xc) %ecx)
    19947     # out = new-var(tmp)
    19948     (new-var *(ebp+8) *ecx *(ecx+4) *(ebp+0x10))
    19949 $new-var-from-slice:end:
    19950     # . reclaim locals
    19951     81 0/subop/add %esp 8/imm32
    19952     # . restore registers
    19953     59/pop-to-ecx
    19954     # . epilogue
    19955     89/<- %esp 5/r32/ebp
    19956     5d/pop-to-ebp
    19957     c3/return
    19958
    19959 new-var-def:  # ad: (addr allocation-descriptor), var: (handle var), out: (addr handle stmt)
    19960     # . prologue
    19961     55/push-ebp
    19962     89/<- %ebp 4/r32/esp
    19963     # . save registers
    19964     50/push-eax
    19965     51/push-ecx
    19966     #
    19967     (allocate *(ebp+8) *Stmt-size *(ebp+0x14))
    19968     # var out-addr/eax: (addr stmt) = lookup(*out)
    19969     8b/-> *(ebp+0x14) 0/r32/eax
    19970     (lookup *eax *(eax+4))  # => eax
    19971     # out-addr->tag = stmt
    19972     c7 0/subop/copy *eax 2/imm32/tag/var-on-stack  # Stmt-tag
    19973     # result->var = var
    19974     8b/-> *(ebp+0xc) 1/r32/ecx
    19975     89/<- *(eax+4) 1/r32/ecx  # Vardef-var
    19976     8b/-> *(ebp+0x10) 1/r32/ecx
    19977     89/<- *(eax+8) 1/r32/ecx  # Vardef-var
    19978 $new-var-def:end:
    19979     # . restore registers
    19980     59/pop-to-ecx
    19981     58/pop-to-eax
    19982     # . epilogue
    19983     89/<- %esp 5/r32/ebp
    19984     5d/pop-to-ebp
    19985     c3/return
    19986
    19987 new-reg-var-def:  # ad: (addr allocation-descriptor), var: (handle var), out: (addr handle stmt)
    19988     # . prologue
    19989     55/push-ebp
    19990     89/<- %ebp 4/r32/esp
    19991     # . save registers
    19992     50/push-eax
    19993     # eax = out
    19994     8b/-> *(ebp+0x14) 0/r32/eax
    19995     #
    19996     (allocate *(ebp+8) *Stmt-size %eax)
    19997     # var out-addr/eax: (addr stmt) = lookup(*out)
    19998     (lookup *eax *(eax+4))  # => eax
    19999     # set tag
    20000     c7 0/subop/copy *eax 3/imm32/tag/var-in-register  # Stmt-tag
    20001     # set output
    20002     8d/copy-address *(eax+0x14) 0/r32/eax  # Regvardef-outputs
    20003     (append-stmt-var Heap  *(ebp+0xc) *(ebp+0x10)  0 0  0  %eax)
    20004 $new-reg-var-def:end:
    20005     # . restore registers
    20006     58/pop-to-eax
    20007     # . epilogue
    20008     89/<- %esp 5/r32/ebp
    20009     5d/pop-to-ebp
    20010     c3/return
    20011
    20012 append-list:  # ad: (addr allocation-descriptor), value: (handle _type), list: (handle list _type), out: (addr handle list _type)
    20013     # . prologue
    20014     55/push-ebp
    20015     89/<- %ebp 4/r32/esp
    20016     # . save registers
    20017     50/push-eax
    20018     51/push-ecx
    20019     57/push-edi
    20020     # edi = out
    20021     8b/-> *(ebp+0x1c) 7/r32/edi
    20022     # *out = new list
    20023     (allocate *(ebp+8) *List-size %edi)
    20024     # var out-addr/edi: (addr list _type) = lookup(*out)
    20025     (lookup *edi *(edi+4))  # => eax
    20026     89/<- %edi 0/r32/eax
    20027     # out-addr->value = value
    20028     8b/-> *(ebp+0xc) 0/r32/eax
    20029     89/<- *edi 0/r32/eax  # List-value
    20030     8b/-> *(ebp+0x10) 0/r32/eax
    20031     89/<- *(edi+4) 0/r32/eax  # List-value
    20032     # if (list == null) return
    20033     81 7/subop/compare *(ebp+0x14) 0/imm32
    20034     74/jump-if-= $append-list:end/disp8
    20035     # otherwise append
    20036 $append-list:non-empty-list:
    20037     # var curr/eax: (addr list _type) = lookup(list)
    20038     (lookup *(ebp+0x14) *(ebp+0x18))  # => eax
    20039     # while (curr->next != null) curr = curr->next
    20040     {
    20041       81 7/subop/compare *(eax+8) 0/imm32  # List-next
    20042       74/jump-if-= break/disp8
    20043       # curr = lookup(curr->next)
    20044       (lookup *(eax+8) *(eax+0xc))  # List-next, List-next => eax
    20045       #
    20046       eb/jump loop/disp8
    20047     }
    20048     # edi = out
    20049     8b/-> *(ebp+0x1c) 7/r32/edi
    20050     # curr->next = out
    20051     8b/-> *edi 1/r32/ecx
    20052     89/<- *(eax+8) 1/r32/ecx  # List-next
    20053     8b/-> *(edi+4) 1/r32/ecx
    20054     89/<- *(eax+0xc) 1/r32/ecx  # List-next
    20055     # out = list
    20056     8b/-> *(ebp+0x14) 1/r32/ecx
    20057     89/<- *edi 1/r32/ecx
    20058     8b/-> *(ebp+0x18) 1/r32/ecx
    20059     89/<- *(edi+4) 1/r32/ecx
    20060 $append-list:end:
    20061     # . restore registers
    20062     5f/pop-to-edi
    20063     59/pop-to-ecx
    20064     58/pop-to-eax
    20065     # . epilogue
    20066     89/<- %esp 5/r32/ebp
    20067     5d/pop-to-ebp
    20068     c3/return
    20069
    20070 append-stmt-var:  # ad: (addr allocation-descriptor), v: (handle var), vars: (handle stmt-var), is-deref?: boolean, out: (addr handle stmt-var)
    20071     # . prologue
    20072     55/push-ebp
    20073     89/<- %ebp 4/r32/esp
    20074     # . save registers
    20075     50/push-eax
    20076     51/push-ecx
    20077     57/push-edi
    20078     # edi = out
    20079     8b/-> *(ebp+0x20) 7/r32/edi
    20080     # out = new stmt-var
    20081     (allocate *(ebp+8) *Stmt-var-size %edi)
    20082     # var out-addr/ecx: (addr stmt-var) = lookup(*out)
    20083     (lookup *edi *(edi+4))  # => eax
    20084     89/<- %ecx 0/r32/eax
    20085     # out-addr->value = v
    20086     8b/-> *(ebp+0xc) 0/r32/eax
    20087     89/<- *ecx 0/r32/eax  # Stmt-var-value
    20088     8b/-> *(ebp+0x10) 0/r32/eax
    20089     89/<- *(ecx+4) 0/r32/eax  # Stmt-var-value
    20090     # out-addr->is-deref? = is-deref?
    20091     8b/-> *(ebp+0x1c) 0/r32/eax
    20092     89/<- *(ecx+0x10) 0/r32/eax  # Stmt-var-is-deref
    20093     # if (vars == null) return result
    20094     81 7/subop/compare *(ebp+0x14) 0/imm32/null
    20095     74/jump-if-= $append-stmt-var:end/disp8
    20096     # otherwise append
    20097     # var curr/eax: (addr stmt-var) = lookup(vars)
    20098     (lookup *(ebp+0x14) *(ebp+0x18))  # => eax
    20099     # while (curr->next != null) curr = curr->next
    20100     {
    20101       81 7/subop/compare *(eax+8) 0/imm32  # Stmt-var-next
    20102       74/jump-if-= break/disp8
    20103       # curr = lookup(curr->next)
    20104       (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next, Stmt-var-next => eax
    20105       #
    20106       eb/jump loop/disp8
    20107     }
    20108     # curr->next = out
    20109     8b/-> *edi 1/r32/ecx
    20110     89/<- *(eax+8) 1/r32/ecx  # Stmt-var-next
    20111     8b/-> *(edi+4) 1/r32/ecx
    20112     89/<- *(eax+0xc) 1/r32/ecx  # Stmt-var-next
    20113     # out = vars
    20114     8b/-> *(ebp+0x14) 1/r32/ecx
    20115     89/<- *edi 1/r32/ecx
    20116     8b/-> *(ebp+0x18) 1/r32/ecx
    20117     89/<- *(edi+4) 1/r32/ecx
    20118 $append-stmt-var:end:
    20119     # . restore registers
    20120     5f/pop-to-edi
    20121     59/pop-to-ecx
    20122     58/pop-to-eax
    20123     # . epilogue
    20124     89/<- %esp 5/r32/ebp
    20125     5d/pop-to-ebp
    20126     c3/return
    20127
    20128 append-to-block:  # ad: (addr allocation-descriptor), block: (addr block), x: (handle stmt)
    20129     # . prologue
    20130     55/push-ebp
    20131     89/<- %ebp 4/r32/esp
    20132     # . save registers
    20133     50/push-eax
    20134     56/push-esi
    20135     # esi = block
    20136     8b/-> *(ebp+0xc) 6/r32/esi
    20137     # block->stmts = append(x, block->stmts)
    20138     8d/copy-address *(esi+4) 0/r32/eax  # Block-stmts
    20139     (append-list *(ebp+8)  *(ebp+0x10) *(ebp+0x14)  *(esi+4) *(esi+8)  %eax)  # ad, x, x, Block-stmts, Block-stmts
    20140 $append-to-block:end:
    20141     # . restore registers
    20142     5e/pop-to-esi
    20143     58/pop-to-eax
    20144     # . epilogue
    20145     89/<- %esp 5/r32/ebp
    20146     5d/pop-to-ebp
    20147     c3/return
    20148
    20149 ## Parsing types
    20150 # We need to create metadata on user-defined types, and we need to use this
    20151 # metadata as we parse instructions.
    20152 # However, we also want to allow types to be used before their definitions.
    20153 # This means we can't ever assume any type data structures exist.
    20154
    20155 lookup-or-create-constant:  # container: (addr stmt-var), field-name: (addr slice), out: (addr handle var)
    20156     # . prologue
    20157     55/push-ebp
    20158     89/<- %ebp 4/r32/esp
    20159     # . save registers
    20160     50/push-eax
    20161     56/push-esi
    20162     # var container-type/esi: type-id
    20163     (container-type *(ebp+8))  # => eax
    20164     89/<- %esi 0/r32/eax
    20165     # var tmp/eax: (handle typeinfo) = find-or-create-typeinfo(container-type)
    20166     68/push 0/imm32
    20167     68/push 0/imm32
    20168     89/<- %eax 4/r32/esp
    20169     (find-or-create-typeinfo %esi %eax)
    20170     # var tmp-addr/eax: (addr typeinfo) = lookup(tmp)
    20171     (lookup *eax *(eax+4))  # => eax
    20172     # result = find-or-create-typeinfo-output-var(typeinfo, field-name)
    20173 #?     (write-buffered Stderr "constant: ")
    20174 #?     (write-slice-buffered Stderr *(ebp+0xc))
    20175 #?     (write-buffered Stderr Newline)
    20176 #?     (flush Stderr)
    20177     (find-or-create-typeinfo-output-var %eax *(ebp+0xc) *(ebp+0x10))
    20178 #?     8b/-> *(ebp+0x10) 0/r32/eax
    20179 #?     (write-buffered Stderr "@")
    20180 #?     (lookup *eax *(eax+4))
    20181 #?     (write-int32-hex-buffered Stderr %eax)
    20182 #?     (lookup *eax *(eax+4))
    20183 #?     (write-buffered Stderr %eax)
    20184 #?     (write-buffered Stderr Newline)
    20185 #?     (flush Stderr)
    20186 #?     (write-buffered Stderr "offset: ")
    20187 #?     8b/-> *(eax+0x14) 0/r32/eax
    20188 #?     (write-int32-hex-buffered Stderr %eax)
    20189 #?     (write-buffered Stderr Newline)
    20190 #?     (flush Stderr)
    20191 $lookup-or-create-constant:end:
    20192     # . reclaim locals
    20193     81 0/subop/add %esp 8/imm32
    20194     # . restore registers
    20195     5e/pop-to-esi
    20196     58/pop-to-eax
    20197     # . epilogue
    20198     89/<- %esp 5/r32/ebp
    20199     5d/pop-to-ebp
    20200     c3/return
    20201
    20202 # if addr var:
    20203 #   container->var->type->right->left->value
    20204 # otherwise
    20205 #   container->var->type->value
    20206 container-type:  # container: (addr stmt-var) -> result/eax: type-id
    20207     # . prologue
    20208     55/push-ebp
    20209     89/<- %ebp 4/r32/esp
    20210     #
    20211     8b/-> *(ebp+8) 0/r32/eax
    20212     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    20213     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    20214     {
    20215       81 7/subop/compare *(eax+8) 0/imm32  # Type-tree-right
    20216       74/jump-if-= break/disp8
    20217       (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
    20218       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    20219     }
    20220     8b/-> *(eax+4) 0/r32/eax  # Type-tree-value
    20221 $container-type:end:
    20222     # . epilogue
    20223     89/<- %esp 5/r32/ebp
    20224     5d/pop-to-ebp
    20225     c3/return
    20226
    20227 container?:  # t: type-id -> result/eax: boolean
    20228     # . prologue
    20229     55/push-ebp
    20230     89/<- %ebp 4/r32/esp
    20231     #
    20232     8b/-> *(ebp+8) 0/r32/eax
    20233     c1/shift 4/subop/left %eax 2/imm8
    20234     3b/compare 0/r32/eax *Primitive-type-ids
    20235     0f 9d/set-if->= %al
    20236     81 4/subop/and %eax 0xff/imm32
    20237 $container?:end:
    20238     # . epilogue
    20239     89/<- %esp 5/r32/ebp
    20240     5d/pop-to-ebp
    20241     c3/return
    20242
    20243 find-or-create-typeinfo:  # t: type-id, out: (addr handle typeinfo)
    20244     # . prologue
    20245     55/push-ebp
    20246     89/<- %ebp 4/r32/esp
    20247     # . save registers
    20248     50/push-eax
    20249     51/push-ecx
    20250     52/push-edx
    20251     57/push-edi
    20252     # edi = out
    20253     8b/-> *(ebp+0xc) 7/r32/edi
    20254     # var fields/ecx: (handle table (handle array byte) (handle typeinfo-entry))
    20255     68/push 0/imm32
    20256     68/push 0/imm32
    20257     89/<- %ecx 4/r32/esp
    20258     # find-typeinfo(t, out)
    20259     (find-typeinfo *(ebp+8) %edi)
    20260     {
    20261       # if (*out != 0) break
    20262       81 7/subop/compare *edi 0/imm32
    20263       0f 85/jump-if-!= break/disp32
    20264 $find-or-create-typeinfo:create:
    20265       # *out = allocate
    20266       (allocate Heap *Typeinfo-size %edi)
    20267       # var tmp/eax: (addr typeinfo) = lookup(*out)
    20268       (lookup *edi *(edi+4))  # => eax
    20269 #?     (write-buffered Stderr "created typeinfo at ")
    20270 #?     (write-int32-hex-buffered Stderr %eax)
    20271 #?     (write-buffered Stderr " for type-id ")
    20272 #?     (write-int32-hex-buffered Stderr *(ebp+8))
    20273 #?     (write-buffered Stderr Newline)
    20274 #?     (flush Stderr)
    20275       # tmp->id = t
    20276       8b/-> *(ebp+8) 2/r32/edx
    20277       89/<- *eax 2/r32/edx  # Typeinfo-id
    20278       # tmp->fields = new table
    20279       # . fields = new table
    20280       (new-stream Heap 0x40 *Typeinfo-fields-row-size %ecx)
    20281       # . tmp->fields = fields
    20282       8b/-> *ecx 2/r32/edx
    20283       89/<- *(eax+4) 2/r32/edx  # Typeinfo-fields
    20284       8b/-> *(ecx+4) 2/r32/edx
    20285       89/<- *(eax+8) 2/r32/edx  # Typeinfo-fields
    20286       # tmp->next = Program->types
    20287       8b/-> *_Program-types 1/r32/ecx
    20288       89/<- *(eax+0x10) 1/r32/ecx  # Typeinfo-next
    20289       8b/-> *_Program-types->payload 1/r32/ecx
    20290       89/<- *(eax+0x14) 1/r32/ecx  # Typeinfo-next
    20291       # Program->types = out
    20292       8b/-> *edi 1/r32/ecx
    20293       89/<- *_Program-types 1/r32/ecx
    20294       8b/-> *(edi+4) 1/r32/ecx
    20295       89/<- *_Program-types->payload 1/r32/ecx
    20296     }
    20297 $find-or-create-typeinfo:end:
    20298     # . reclaim locals
    20299     81 0/subop/add %esp 8/imm32
    20300     # . restore registers
    20301     5f/pop-to-edi
    20302     5a/pop-to-edx
    20303     59/pop-to-ecx
    20304     58/pop-to-eax
    20305     # . epilogue
    20306     89/<- %esp 5/r32/ebp
    20307     5d/pop-to-ebp
    20308     c3/return
    20309
    20310 find-typeinfo:  # t: type-id, out: (addr handle typeinfo)
    20311     # . prologue
    20312     55/push-ebp
    20313     89/<- %ebp 4/r32/esp
    20314     # . save registers
    20315     50/push-eax
    20316     51/push-ecx
    20317     52/push-edx
    20318     57/push-edi
    20319     # ecx = t
    20320     8b/-> *(ebp+8) 1/r32/ecx
    20321     # edi = out
    20322     8b/-> *(ebp+0xc) 7/r32/edi
    20323     # *out = Program->types
    20324     8b/-> *_Program-types 0/r32/eax
    20325     89/<- *edi 0/r32/eax
    20326     8b/-> *_Program-types->payload 0/r32/eax
    20327     89/<- *(edi+4) 0/r32/eax
    20328     {
    20329 $find-typeinfo:loop:
    20330       # if (*out == 0) break
    20331       81 7/subop/compare *edi 0/imm32
    20332       74/jump-if-= break/disp8
    20333 $find-typeinfo:check:
    20334       # var tmp/eax: (addr typeinfo) = lookup(*out)
    20335       (lookup *edi *(edi+4))  # => eax
    20336       # if (tmp->id == t) break
    20337       39/compare *eax 1/r32/ecx  # Typeinfo-id
    20338       74/jump-if-= break/disp8
    20339 $find-typeinfo:continue:
    20340       # *out = tmp->next
    20341       8b/-> *(eax+0x10) 2/r32/edx  # Typeinfo-next
    20342       89/<- *edi 2/r32/edx
    20343       8b/-> *(eax+0x14) 2/r32/edx  # Typeinfo-next
    20344       89/<- *(edi+4) 2/r32/edx
    20345       #
    20346       eb/jump loop/disp8
    20347     }
    20348 $find-typeinfo:end:
    20349     # . restore registers
    20350     5f/pop-to-edi
    20351     5a/pop-to-edx
    20352     59/pop-to-ecx
    20353     58/pop-to-eax
    20354     # . epilogue
    20355     89/<- %esp 5/r32/ebp
    20356     5d/pop-to-ebp
    20357     c3/return
    20358
    20359 find-or-create-typeinfo-output-var:  # T: (addr typeinfo), f: (addr slice), out: (addr handle var)
    20360     # . prologue
    20361     55/push-ebp
    20362     89/<- %ebp 4/r32/esp
    20363     # . save registers
    20364     50/push-eax
    20365     52/push-edx
    20366     57/push-edi
    20367     # var dest/edi: (handle typeinfo-entry)
    20368     68/push 0/imm32
    20369     68/push 0/imm32
    20370     89/<- %edi 4/r32/esp
    20371     # find-or-create-typeinfo-fields(T, f, dest)
    20372     (find-or-create-typeinfo-fields *(ebp+8) *(ebp+0xc) %edi)
    20373     # var dest-addr/edi: (addr typeinfo-entry) = lookup(dest)
    20374     (lookup *edi *(edi+4))  # => eax
    20375     89/<- %edi 0/r32/eax
    20376     # if dest-addr->output-var doesn't exist, create it
    20377     {
    20378       81 7/subop/compare *(edi+0xc) 0/imm32  # Typeinfo-entry-output-var
    20379       0f 85/jump-if-!= break/disp32
    20380       # dest-addr->output-var = new var(dummy name, type, -1 offset)
    20381       # . var name/eax: (handle array byte) = "field"
    20382       68/push 0/imm32
    20383       68/push 0/imm32
    20384       89/<- %eax 4/r32/esp
    20385       (slice-to-string Heap *(ebp+0xc) %eax)
    20386       # . new var
    20387       8d/copy-address *(edi+0xc) 2/r32/edx
    20388       (new-var Heap  *eax *(eax+4)  %edx)
    20389       # . reclaim name
    20390       81 0/subop/add %esp 8/imm32
    20391       # var result/edx: (addr var) = lookup(dest-addr->output-var)
    20392       (lookup *(edi+0xc) *(edi+0x10))  # => eax
    20393       89/<- %edx 0/r32/eax
    20394       # result->type = new constant type
    20395       8d/copy-address *(edx+8) 0/r32/eax  # Var-type
    20396       (allocate Heap *Type-tree-size %eax)
    20397       (lookup *(edx+8) *(edx+0xc))  # => eax
    20398       c7 0/subop/copy *eax 1/imm32/true  # Type-tree-is-atom
    20399       c7 0/subop/copy *(eax+4) 6/imm32/constant  # Type-tree-value
    20400       c7 0/subop/copy *(eax+8) 0/imm32  # Type-tree-left
    20401       c7 0/subop/copy *(eax+0xc) 0/imm32  # Type-tree-right
    20402       c7 0/subop/copy *(eax+0x10) 0/imm32  # Type-tree-right
    20403       # result->offset isn't filled out yet
    20404       c7 0/subop/copy *(edx+0x14) -1/imm32/uninitialized  # Var-offset
    20405     }
    20406     # out = dest-addr->output-var
    20407     8b/-> *(ebp+0x10) 2/r32/edx
    20408     8b/-> *(edi+0xc) 0/r32/eax  # Typeinfo-entry-output-var
    20409     89/<- *edx 0/r32/eax
    20410     8b/-> *(edi+0x10) 0/r32/eax  # Typeinfo-entry-output-var
    20411     89/<- *(edx+4) 0/r32/eax
    20412 $find-or-create-typeinfo-output-var:end:
    20413     # . reclaim locals
    20414     81 0/subop/add %esp 8/imm32
    20415     # . restore registers
    20416     5f/pop-to-edi
    20417     5a/pop-to-edx
    20418     58/pop-to-eax
    20419     # . epilogue
    20420     89/<- %esp 5/r32/ebp
    20421     5d/pop-to-ebp
    20422     c3/return
    20423
    20424 find-or-create-typeinfo-fields:  # T: (addr typeinfo), f: (addr slice), out: (addr handle typeinfo-entry)
    20425     # . prologue
    20426     55/push-ebp
    20427     89/<- %ebp 4/r32/esp
    20428     # . save registers
    20429     50/push-eax
    20430     56/push-esi
    20431     57/push-edi
    20432     # eax = lookup(T->fields)
    20433     8b/-> *(ebp+8) 0/r32/eax
    20434     (lookup *(eax+4) *(eax+8))  # Typeinfo-fields Typeinfo-fields => eax
    20435     # edi = out
    20436     8b/-> *(ebp+0x10) 7/r32/edi
    20437     # var src/esi: (addr handle typeinfo-entry) = get-or-insert-slice(T->fields, f)
    20438     (get-or-insert-slice %eax *(ebp+0xc) *Typeinfo-fields-row-size Heap)  # => eax
    20439     89/<- %esi 0/r32/eax
    20440     # if src doesn't exist, allocate it
    20441     {
    20442       81 7/subop/compare *esi 0/imm32
    20443       75/jump-if-!= break/disp8
    20444       (allocate Heap *Typeinfo-entry-size %esi)
    20445 #?       (write-buffered Stderr "handle at ")
    20446 #?       (write-int32-hex-buffered Stderr %esi)
    20447 #?       (write-buffered Stderr ": ")
    20448 #?       (write-int32-hex-buffered Stderr *esi)
    20449 #?       (write-buffered Stderr " ")
    20450 #?       (write-int32-hex-buffered Stderr *(esi+4))
    20451 #?       (write-buffered Stderr Newline)
    20452 #?       (flush Stderr)
    20453 #?       (lookup *esi *(esi+4))
    20454 #?       (write-buffered Stderr "created typeinfo fields at ")
    20455 #?       (write-int32-hex-buffered Stderr %esi)
    20456 #?       (write-buffered Stderr " for ")
    20457 #?       (write-int32-hex-buffered Stderr *(ebp+8))
    20458 #?       (write-buffered Stderr Newline)
    20459 #?       (flush Stderr)
    20460     }
    20461     # *out = src
    20462     # . *edi = *src
    20463     8b/-> *esi 0/r32/eax
    20464     89/<- *edi 0/r32/eax
    20465     8b/-> *(esi+4) 0/r32/eax
    20466     89/<- *(edi+4) 0/r32/eax
    20467 $find-or-create-typeinfo-fields:end:
    20468     # . restore registers
    20469     5f/pop-to-edi
    20470     5e/pop-to-esi
    20471     58/pop-to-eax
    20472     # . epilogue
    20473     89/<- %esp 5/r32/ebp
    20474     5d/pop-to-ebp
    20475     c3/return
    20476
    20477 populate-mu-type:  # in: (addr stream byte), t: (addr typeinfo), err: (addr buffered-file), ed: (addr exit-descriptor)
    20478     # pseudocode:
    20479     #   var line: (stream byte 512)
    20480     #   curr-index = 0
    20481     #   while true
    20482     #     clear-stream(line)
    20483     #     read-line-buffered(in, line)
    20484     #     if line->write == 0
    20485     #       abort
    20486     #     word-slice = next-mu-token(line)
    20487     #     if slice-empty?(word-slice)               # end of line
    20488     #       continue
    20489     #     if slice-equal?(word-slice, "}")
    20490     #       break
    20491     #     var v: (handle var) = parse-var-with-type(word-slice, line)
    20492     #     var r: (handle typeinfo-fields) = find-or-create-typeinfo-fields(t, word-slice/v->name)
    20493     #     TODO: ensure that r->first is null
    20494     #     r->index = curr-index
    20495     #     curr-index++
    20496     #     r->input-var = v
    20497     #     if r->output-var == 0
    20498     #       r->output-var = new literal
    20499     #     TODO: ensure nothing else in line
    20500     # t->total-size-in-bytes = -2 (not yet initialized)
    20501     #
    20502     # . prologue
    20503     55/push-ebp
    20504     89/<- %ebp 4/r32/esp
    20505     # var curr-index: int at *(ebp-4)
    20506     68/push 0/imm32
    20507     # . save registers
    20508     50/push-eax
    20509     51/push-ecx
    20510     52/push-edx
    20511     53/push-ebx
    20512     56/push-esi
    20513     57/push-edi
    20514     # edi = t
    20515     8b/-> *(ebp+0xc) 7/r32/edi
    20516     # var line/ecx: (stream byte 512)
    20517     81 5/subop/subtract %esp 0x200/imm32
    20518     68/push 0x200/imm32/size
    20519     68/push 0/imm32/read
    20520     68/push 0/imm32/write
    20521     89/<- %ecx 4/r32/esp
    20522     # var word-slice/edx: slice
    20523     68/push 0/imm32/end
    20524     68/push 0/imm32/start
    20525     89/<- %edx 4/r32/esp
    20526     # var v/esi: (handle var)
    20527     68/push 0/imm32
    20528     68/push 0/imm32
    20529     89/<- %esi 4/r32/esp
    20530     # var r/ebx: (handle typeinfo-entry)
    20531     68/push 0/imm32
    20532     68/push 0/imm32
    20533     89/<- %ebx 4/r32/esp
    20534     {
    20535 $populate-mu-type:line-loop:
    20536       (clear-stream %ecx)
    20537       (read-line-buffered *(ebp+8) %ecx)
    20538       # if (line->write == 0) abort
    20539       81 7/subop/compare *ecx 0/imm32
    20540       0f 84/jump-if-= $populate-mu-type:error1/disp32
    20541 +--  6 lines: #?       # dump line ------------------------------------------------------------------------------------------------------------------------------------------------------
    20547       (next-mu-token %ecx %edx)
    20548       # if slice-empty?(word-slice) continue
    20549       (slice-empty? %edx)  # => eax
    20550       3d/compare-eax-and 0/imm32
    20551       0f 85/jump-if-!= loop/disp32
    20552       # if slice-equal?(word-slice, "}") break
    20553       (slice-equal? %edx "}")
    20554       3d/compare-eax-and 0/imm32
    20555       0f 85/jump-if-!= break/disp32
    20556 $populate-mu-type:parse-element:
    20557       # v = parse-var-with-type(word-slice, first-line)
    20558       # must do this first to strip the trailing ':' from word-slice before
    20559       # using it in find-or-create-typeinfo-fields below
    20560       # TODO: clean up that mutation in parse-var-with-type
    20561       (type-name *edi)  # Typeinfo-id => eax
    20562       (parse-var-with-type %edx %ecx %esi %eax *(ebp+0x10) *(ebp+0x14))
    20563       # if v is an addr, abort
    20564       (lookup *esi *(esi+4))  # => eax
    20565       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    20566       (mu-addr-type? %eax)  # => eax
    20567       3d/compare-eax-and 0/imm32/false
    20568       0f 85/jump-if-!= $populate-mu-type:error2/disp32
    20569       # if v is an array, abort  (we could support it, but initialization gets complex)
    20570       (lookup *esi *(esi+4))  # => eax
    20571       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    20572       (mu-array-type? %eax)  # => eax
    20573       3d/compare-eax-and 0/imm32/false
    20574       0f 85/jump-if-!= $populate-mu-type:error3/disp32
    20575       # if v is a byte, abort
    20576       (lookup *esi *(esi+4))  # => eax
    20577       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    20578       (simple-mu-type? %eax 8)  # byte => eax
    20579       3d/compare-eax-and 0/imm32/false
    20580       0f 85/jump-if-!= $populate-mu-type:error4/disp32
    20581       # if v is a slice, abort
    20582       (lookup *esi *(esi+4))  # => eax
    20583       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    20584       (simple-mu-type? %eax 0xc)  # slice => eax
    20585       3d/compare-eax-and 0/imm32/false
    20586       0f 85/jump-if-!= $populate-mu-type:error5/disp32
    20587       # if v is a stream, abort  (we could support it, but initialization gets even more complex)
    20588       (lookup *esi *(esi+4))  # => eax
    20589       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    20590       (mu-stream-type? %eax)  # => eax
    20591       3d/compare-eax-and 0/imm32/false
    20592       0f 85/jump-if-!= $populate-mu-type:error6/disp32
    20593       # var tmp/ecx
    20594       51/push-ecx
    20595 $populate-mu-type:create-typeinfo-fields:
    20596       # var r/ebx: (handle typeinfo-entry)
    20597       (find-or-create-typeinfo-fields %edi %edx %ebx)
    20598       # r->index = curr-index
    20599       (lookup *ebx *(ebx+4))  # => eax
    20600       8b/-> *(ebp-4) 1/r32/ecx
    20601 #?       (write-buffered Stderr "saving index ")
    20602 #?       (write-int32-hex-buffered Stderr %ecx)
    20603 #?       (write-buffered Stderr " at ")
    20604 #?       (write-int32-hex-buffered Stderr %edi)
    20605 #?       (write-buffered Stderr Newline)
    20606 #?       (flush Stderr)
    20607       89/<- *(eax+8) 1/r32/ecx  # Typeinfo-entry-index
    20608       # ++curr-index
    20609       ff 0/subop/increment *(ebp-4)
    20610 $populate-mu-type:set-input-type:
    20611       # r->input-var = v
    20612       8b/-> *esi 1/r32/ecx
    20613       89/<- *eax 1/r32/ecx  # Typeinfo-entry-input-var
    20614       8b/-> *(esi+4) 1/r32/ecx
    20615       89/<- *(eax+4) 1/r32/ecx  # Typeinfo-entry-input-var
    20616       # restore line
    20617       59/pop-to-ecx
    20618       {
    20619 $populate-mu-type:create-output-type:
    20620         # if (r->output-var == 0) create a new var with some placeholder data
    20621         81 7/subop/compare *(eax+0xc) 0/imm32  # Typeinfo-entry-output-var
    20622         75/jump-if-!= break/disp8
    20623         8d/copy-address *(eax+0xc) 0/r32/eax  # Typeinfo-entry-output-var
    20624         (new-literal Heap %edx %eax)
    20625       }
    20626       e9/jump loop/disp32
    20627     }
    20628 $populate-mu-type:invalidate-total-size-in-bytes:
    20629     # Offsets and total size may not be accurate here since we may not yet
    20630     # have encountered the element types.
    20631     # We'll recompute them separately after parsing the entire program.
    20632     c7 0/subop/copy *(edi+0xc) -2/imm32/uninitialized  # Typeinfo-total-size-in-bytes
    20633 $populate-mu-type:end:
    20634     # . reclaim locals
    20635     81 0/subop/add %esp 0x224/imm32
    20636     # . restore registers
    20637     5f/pop-to-edi
    20638     5e/pop-to-esi
    20639     5b/pop-to-ebx
    20640     5a/pop-to-edx
    20641     59/pop-to-ecx
    20642     58/pop-to-eax
    20643     # reclaim curr-index
    20644     81 0/subop/add %esp 4/imm32
    20645     # . epilogue
    20646     89/<- %esp 5/r32/ebp
    20647     5d/pop-to-ebp
    20648     c3/return
    20649
    20650 $populate-mu-type:error1:
    20651     # error("incomplete type definition '" t->name "'\n")
    20652     (write-buffered *(ebp+0x10) "incomplete type definition '")
    20653     (type-name *edi)  # Typeinfo-id => eax
    20654     (write-buffered *(ebp+0x10) %eax)
    20655     (write-buffered *(ebp+0x10) "\n")
    20656     (flush *(ebp+0x10))
    20657     (stop *(ebp+0x14) 1)
    20658     # never gets here
    20659
    20660 $populate-mu-type:error2:
    20661     (write-buffered *(ebp+0x10) "type ")
    20662     (type-name *edi)  # Typeinfo-id => eax
    20663     (write-buffered *(ebp+0x10) %eax)
    20664     (write-buffered *(ebp+0x10) ": 'addr' elements not allowed\n")
    20665     (flush *(ebp+0x10))
    20666     (stop *(ebp+0x14) 1)
    20667     # never gets here
    20668
    20669 $populate-mu-type:error3:
    20670     (write-buffered *(ebp+0x10) "type ")
    20671     (type-name *edi)  # Typeinfo-id => eax
    20672     (write-buffered *(ebp+0x10) %eax)
    20673     (write-buffered *(ebp+0x10) ": 'array' elements not allowed for now\n")
    20674     (flush *(ebp+0x10))
    20675     (stop *(ebp+0x14) 1)
    20676     # never gets here
    20677
    20678 $populate-mu-type:error4:
    20679     (write-buffered *(ebp+0x10) "type ")
    20680     (type-name *edi)  # Typeinfo-id => eax
    20681     (write-buffered *(ebp+0x10) %eax)
    20682     (write-buffered *(ebp+0x10) ": 'byte' elements not allowed\n")
    20683     (flush *(ebp+0x10))
    20684     (stop *(ebp+0x14) 1)
    20685     # never gets here
    20686
    20687 $populate-mu-type:error5:
    20688     (write-buffered *(ebp+0x10) "type ")
    20689     (type-name *edi)  # Typeinfo-id => eax
    20690     (write-buffered *(ebp+0x10) %eax)
    20691     (write-buffered *(ebp+0x10) ": 'slice' elements not allowed\n")
    20692     (flush *(ebp+0x10))
    20693     (stop *(ebp+0x14) 1)
    20694     # never gets here
    20695
    20696 $populate-mu-type:error6:
    20697     (write-buffered *(ebp+0x10) "type ")
    20698     (type-name *edi)  # Typeinfo-id => eax
    20699     (write-buffered *(ebp+0x10) %eax)
    20700     (write-buffered *(ebp+0x10) ": 'stream' elements not allowed for now\n")
    20701     (flush *(ebp+0x10))
    20702     (stop *(ebp+0x14) 1)
    20703     # never gets here
    20704
    20705 type-name:  # index: int -> result/eax: (addr array byte)
    20706     # . prologue
    20707     55/push-ebp
    20708     89/<- %ebp 4/r32/esp
    20709     #
    20710     (index Type-id *(ebp+8))
    20711 $type-name:end:
    20712     # . epilogue
    20713     89/<- %esp 5/r32/ebp
    20714     5d/pop-to-ebp
    20715     c3/return
    20716
    20717 index:  # arr: (addr stream (handle array byte)), index: int -> result/eax: (addr array byte)
    20718     # . prologue
    20719     55/push-ebp
    20720     89/<- %ebp 4/r32/esp
    20721     # . save registers
    20722     56/push-esi
    20723     # TODO: bounds-check index
    20724     # esi = arr
    20725     8b/-> *(ebp+8) 6/r32/esi
    20726     # eax = index
    20727     8b/-> *(ebp+0xc) 0/r32/eax
    20728     # eax = *(arr + 12 + index)
    20729     8b/-> *(esi+eax<<2+0xc) 0/r32/eax
    20730 $index:end:
    20731     # . restore registers
    20732     5e/pop-to-esi
    20733     # . epilogue
    20734     89/<- %esp 5/r32/ebp
    20735     5d/pop-to-ebp
    20736     c3/return
    20737
    20738 #######################################################
    20739 # Compute type sizes
    20740 #######################################################
    20741
    20742 # Compute the sizes of all user-defined types.
    20743 # We'll need the sizes of their elements, which may be other user-defined
    20744 # types, which we will compute as needed.
    20745
    20746 # Initially, all user-defined types have their sizes set to -2 (invalid)
    20747 populate-mu-type-sizes:  # err: (addr buffered-file), ed: (addr exit-descriptor)
    20748     # . prologue
    20749     55/push-ebp
    20750     89/<- %ebp 4/r32/esp
    20751 $populate-mu-type-sizes:total-sizes:
    20752     # var curr/eax: (addr typeinfo) = lookup(Program->types)
    20753     (lookup *_Program-types *_Program-types->payload)  # => eax
    20754     {
    20755       # if (curr == null) break
    20756       3d/compare-eax-and 0/imm32/null
    20757       74/jump-if-= break/disp8
    20758       (populate-mu-type-sizes-in-type %eax *(ebp+8) *(ebp+0xc))
    20759       # curr = lookup(curr->next)
    20760       (lookup *(eax+0x10) *(eax+0x14))  # Typeinfo-next Typeinfo-next => eax
    20761       eb/jump loop/disp8
    20762     }
    20763 $populate-mu-type-sizes:offsets:
    20764     # curr = *Program->types
    20765     (lookup *_Program-types *_Program-types->payload)  # => eax
    20766     {
    20767       # if (curr == null) break
    20768       3d/compare-eax-and 0/imm32/null
    20769       74/jump-if-= break/disp8
    20770       (populate-mu-type-offsets %eax *(ebp+8) *(ebp+0xc))
    20771       # curr = curr->next
    20772       (lookup *(eax+0x10) *(eax+0x14))  # Typeinfo-next Typeinfo-next => eax
    20773       eb/jump loop/disp8
    20774     }
    20775 $populate-mu-type-sizes:end:
    20776     # . epilogue
    20777     89/<- %esp 5/r32/ebp
    20778     5d/pop-to-ebp
    20779     c3/return
    20780
    20781 # compute sizes of all fields, recursing as necessary
    20782 # sum up all their sizes to arrive at total size
    20783 # fields may be out of order, but that doesn't affect the answer
    20784 populate-mu-type-sizes-in-type:  # T: (addr typeinfo), err: (addr buffered-file), ed: (addr exit-descriptor)
    20785     # . prologue
    20786     55/push-ebp
    20787     89/<- %ebp 4/r32/esp
    20788     # . save registers
    20789     50/push-eax
    20790     51/push-ecx
    20791     52/push-edx
    20792     56/push-esi
    20793     57/push-edi
    20794     # esi = T
    20795     8b/-> *(ebp+8) 6/r32/esi
    20796     # if T is already computed, return
    20797     81 7/subop/compare *(esi+0xc) 0/imm32  # Typeinfo-total-size-in-bytes
    20798     0f 8d/jump-if->= $populate-mu-type-sizes-in-type:end/disp32
    20799     # if T is being computed, abort
    20800     81 7/subop/compare *(esi+0xc) -1/imm32/being-computed  # Typeinfo-total-size-in-bytes
    20801     0f 84/jump-if-= $populate-mu-type-sizes-in-type:abort/disp32
    20802     # tag T (-2 to -1) to avoid infinite recursion
    20803     c7 0/subop/copy *(esi+0xc) -1/imm32/being-computed  # Typeinfo-total-size-in-bytes
    20804     # var total-size/edi: int = 0
    20805     bf/copy-to-edi 0/imm32
    20806     # - for every field, if it's a user-defined type, compute its size
    20807     # var table/ecx: (addr table (handle array byte) (handle typeinfo-entry)) = lookup(T->fields)
    20808     (lookup *(esi+4) *(esi+8))  # Typeinfo-fields Typeinfo-fields => eax
    20809     89/<- %ecx 0/r32/eax
    20810     # var table-size/edx: int = table->write
    20811     8b/-> *ecx 2/r32/edx  # stream-write
    20812     # var curr/ecx: (addr table_row) = table->data
    20813     8d/copy-address *(ecx+0xc) 1/r32/ecx
    20814     # var max/edx: (addr table_row) = table->data + table->write
    20815     8d/copy-address *(ecx+edx) 2/r32/edx
    20816     {
    20817 $populate-mu-type-sizes-in-type:loop:
    20818       # if (curr >= max) break
    20819       39/compare %ecx 2/r32/edx
    20820       73/jump-if-addr>= break/disp8
    20821       # var t/eax: (addr typeinfo-entry) = lookup(curr->value)
    20822       (lookup *(ecx+8) *(ecx+0xc))  # => eax
    20823       # if (t->input-var == 0) silently ignore it; we'll emit a nice error message while type-checking
    20824       81 7/subop/compare *eax 0/imm32  # Typeinfo-entry-input-var
    20825       74/jump-if-= $populate-mu-type-sizes-in-type:end/disp8
    20826       # compute size of t->input-var
    20827       (lookup *eax *(eax+4))  # Typeinfo-entry-input-var Typeinfo-entry-input-var => eax
    20828       (compute-size-of-var %eax *(ebp+0xc) *(ebp+0x10))  # => eax
    20829       # result += eax
    20830       01/add-to %edi 0/r32/eax
    20831       # curr += row-size
    20832       81 0/subop/add %ecx 0x10/imm32  # Typeinfo-fields-row-size
    20833       #
    20834       eb/jump loop/disp8
    20835     }
    20836     # - save result
    20837     89/<- *(esi+0xc) 7/r32/edi  # Typeinfo-total-size-in-bytes
    20838 $populate-mu-type-sizes-in-type:end:
    20839     # . restore registers
    20840     5f/pop-to-edi
    20841     5e/pop-to-esi
    20842     5a/pop-to-edx
    20843     59/pop-to-ecx
    20844     58/pop-to-eax
    20845     # . epilogue
    20846     89/<- %esp 5/r32/ebp
    20847     5d/pop-to-ebp
    20848     c3/return
    20849
    20850 $populate-mu-type-sizes-in-type:abort:
    20851     (write-buffered *(ebp+0xc) "cycle in type definitions\n")
    20852     (flush *(ebp+0xc))
    20853     (stop *(ebp+0x10) 1)
    20854     # never gets here
    20855
    20856 # Analogous to size-of, except we need to compute what size-of can just read
    20857 # off the right data structures.
    20858 compute-size-of-var:  # in: (addr var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
    20859     # . prologue
    20860     55/push-ebp
    20861     89/<- %ebp 4/r32/esp
    20862     # . push registers
    20863     51/push-ecx
    20864     # var t/ecx: (addr type-tree) = lookup(v->type)
    20865     8b/-> *(ebp+8) 1/r32/ecx
    20866     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
    20867     89/<- %ecx 0/r32/eax
    20868     # if (t->is-atom == false) t = lookup(t->left)
    20869     {
    20870       81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
    20871       75/jump-if-!= break/disp8
    20872       (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
    20873       89/<- %ecx 0/r32/eax
    20874     }
    20875     # TODO: ensure t is an atom
    20876     (compute-size-of-type-id *(ecx+4) *(ebp+0xc) *(ebp+0x10))  # Type-tree-value => eax
    20877 $compute-size-of-var:end:
    20878     # . restore registers
    20879     59/pop-to-ecx
    20880     # . epilogue
    20881     89/<- %esp 5/r32/ebp
    20882     5d/pop-to-ebp
    20883     c3/return
    20884
    20885 compute-size-of-type-id:  # t: type-id, err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
    20886     # . prologue
    20887     55/push-ebp
    20888     89/<- %ebp 4/r32/esp
    20889     # . save registers
    20890     51/push-ecx
    20891     # var out/ecx: (handle typeinfo)
    20892     68/push 0/imm32
    20893     68/push 0/imm32
    20894     89/<- %ecx 4/r32/esp
    20895     # eax = t
    20896     8b/-> *(ebp+8) 0/r32/eax
    20897     # if t is a literal, return 0
    20898     3d/compare-eax-and 0/imm32/literal
    20899     0f 84/jump-if-= $compute-size-of-type-id:end/disp32  # eax changes type from type-id to int
    20900     # if t is a byte, return 4 (because we don't really support non-multiples of 4)
    20901     3d/compare-eax-and 8/imm32/byte
    20902     {
    20903       75/jump-if-!= break/disp8
    20904       b8/copy-to-eax 4/imm32
    20905       eb/jump $compute-size-of-type-id:end/disp8
    20906     }
    20907     # if t is a handle, return 8
    20908     3d/compare-eax-and 4/imm32/handle
    20909     {
    20910       75/jump-if-!= break/disp8
    20911       b8/copy-to-eax 8/imm32
    20912       eb/jump $compute-size-of-type-id:end/disp8  # eax changes type from type-id to int
    20913     }
    20914     # if t is a slice, return 8
    20915     3d/compare-eax-and 0xc/imm32/slice
    20916     {
    20917       75/jump-if-!= break/disp8
    20918       b8/copy-to-eax 8/imm32
    20919       eb/jump $compute-size-of-type-id:end/disp8  # eax changes type from type-id to int
    20920     }
    20921     # if t is a user-defined type, compute its size
    20922     # TODO: support non-atom type
    20923     (find-typeinfo %eax %ecx)
    20924     {
    20925       81 7/subop/compare *ecx 0/imm32
    20926       74/jump-if-= break/disp8
    20927 $compute-size-of-type-id:user-defined:
    20928       (lookup *ecx *(ecx+4))  # => eax
    20929       (populate-mu-type-sizes-in-type %eax *(ebp+0xc) *(ebp+0x10))
    20930       8b/-> *(eax+0xc) 0/r32/eax  # Typeinfo-total-size-in-bytes
    20931       eb/jump $compute-size-of-type-id:end/disp8
    20932     }
    20933     # otherwise return the word size
    20934     b8/copy-to-eax 4/imm32
    20935 $compute-size-of-type-id:end:
    20936     # . reclaim locals
    20937     81 0/subop/add %esp 8/imm32
    20938     # . restore registers
    20939     59/pop-to-ecx
    20940     # . epilogue
    20941     89/<- %esp 5/r32/ebp
    20942     5d/pop-to-ebp
    20943     c3/return
    20944
    20945 # at this point we have total sizes for all user-defined types
    20946 # compute offsets for each element
    20947 # complication: fields may be out of order
    20948 populate-mu-type-offsets:  # in: (addr typeinfo), err: (addr buffered-file), ed: (addr exit-descriptor)
    20949     # . prologue
    20950     55/push-ebp
    20951     89/<- %ebp 4/r32/esp
    20952     # . save registers
    20953     50/push-eax
    20954     51/push-ecx
    20955     52/push-edx
    20956     53/push-ebx
    20957     56/push-esi
    20958     57/push-edi
    20959 #?     (dump-typeinfos "aaa\n")
    20960     # var curr-offset/edi: int = 0
    20961     bf/copy-to-edi 0/imm32
    20962     # var table/ecx: (addr table string_key (handle typeinfo-entry)) = lookup(in->fields)
    20963     8b/-> *(ebp+8) 1/r32/ecx
    20964     (lookup *(ecx+4) *(ecx+8))  # Typeinfo-fields Typeinfo-fields => eax
    20965     89/<- %ecx 0/r32/eax
    20966     # var num-elems/edx: int = table->write / Typeinfo-fields-row-size
    20967     8b/-> *ecx 2/r32/edx  # stream-write
    20968     c1 5/subop/shift-right-logical  %edx 4/imm8
    20969     # var i/ebx: int = 0
    20970     bb/copy-to-ebx 0/imm32
    20971     {
    20972 $populate-mu-type-offsets:loop:
    20973       39/compare %ebx 2/r32/edx
    20974       0f 8d/jump-if->= break/disp32
    20975 #?       (write-buffered Stderr "looking up index ")
    20976 #?       (write-int32-hex-buffered Stderr %ebx)
    20977 #?       (write-buffered Stderr " in ")
    20978 #?       (write-int32-hex-buffered Stderr *(ebp+8))
    20979 #?       (write-buffered Stderr Newline)
    20980 #?       (flush Stderr)
    20981       # var v/esi: (addr typeinfo-entry)
    20982       (locate-typeinfo-entry-with-index %ecx %ebx *(ebp+0xc) *(ebp+0x10))  # => eax
    20983       89/<- %esi 0/r32/eax
    20984       # if v is null, silently move on; we'll emit a nice error message while type-checking
    20985       81 7/subop/compare %esi 0/imm32  # Typeinfo-entry-input-var
    20986       74/jump-if-= $populate-mu-type-offsets:end/disp8
    20987       # if (v->input-var == 0) silently ignore v; we'll emit a nice error message while type-checking
    20988       81 7/subop/compare *esi 0/imm32  # Typeinfo-entry-input-var
    20989       74/jump-if-= $populate-mu-type-offsets:end/disp8
    20990       # v->output-var->offset = curr-offset
    20991       # . eax: (addr var)
    20992       (lookup *(esi+0xc) *(esi+0x10))  # Typeinfo-entry-output-var Typeinfo-entry-output-var => eax
    20993       89/<- *(eax+0x14) 7/r32/edi  # Var-offset
    20994       # curr-offset += size-of(v->input-var)
    20995       (lookup *esi *(esi+4))  # Typeinfo-entry-input-var Typeinfo-entry-input-var => eax
    20996       (size-of %eax)  # => eax
    20997       01/add-to %edi 0/r32/eax
    20998       # ++i
    20999       43/increment-ebx
    21000       e9/jump loop/disp32
    21001     }
    21002 $populate-mu-type-offsets:end:
    21003     # . restore registers
    21004     5f/pop-to-edi
    21005     5e/pop-to-esi
    21006     5b/pop-to-ebx
    21007     5a/pop-to-edx
    21008     59/pop-to-ecx
    21009     58/pop-to-eax
    21010     # . epilogue
    21011     89/<- %esp 5/r32/ebp
    21012     5d/pop-to-ebp
    21013     c3/return
    21014
    21015 locate-typeinfo-entry-with-index:  # table: (addr table (handle array byte) (handle typeinfo-entry)), idx: int, err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: (addr typeinfo-entry)
    21016     # . prologue
    21017     55/push-ebp
    21018     89/<- %ebp 4/r32/esp
    21019     # . save registers
    21020     51/push-ecx
    21021     52/push-edx
    21022     53/push-ebx
    21023     56/push-esi
    21024     57/push-edi
    21025     # esi = table
    21026     8b/-> *(ebp+8) 6/r32/esi
    21027     # var curr/ecx: (addr row (handle array byte) (handle typeinfo-entry)) = table->data
    21028     8d/copy-address *(esi+0xc) 1/r32/ecx
    21029     # var max/edx: (addr byte) = &table->data[table->write]
    21030     8b/-> *esi 2/r32/edx
    21031     8d/copy-address *(ecx+edx) 2/r32/edx
    21032     {
    21033 $locate-typeinfo-entry-with-index:loop:
    21034       39/compare %ecx 2/r32/edx
    21035       73/jump-if-addr>= break/disp8
    21036       # var v/eax: (addr typeinfo-entry)
    21037       (lookup *(ecx+8) *(ecx+0xc))  # => eax
    21038       # if (v->index == idx) return v
    21039       8b/-> *(eax+8) 3/r32/ebx  # Typeinfo-entry-index
    21040 #?       (write-buffered Stderr "comparing ")
    21041 #?       (write-int32-hex-buffered Stderr %ebx)
    21042 #?       (write-buffered Stderr " and ")
    21043 #?       (write-int32-hex-buffered Stderr *(ebp+0xc))
    21044 #?       (write-buffered Stderr Newline)
    21045 #?       (flush Stderr)
    21046       39/compare *(ebp+0xc) 3/r32/ebx
    21047       74/jump-if-= $locate-typeinfo-entry-with-index:end/disp8
    21048       # curr += Typeinfo-entry-size
    21049       81 0/subop/add %ecx 0x10/imm32  # Typeinfo-entry-size
    21050       #
    21051       eb/jump loop/disp8
    21052     }
    21053     # return 0
    21054     b8/copy-to-eax 0/imm32
    21055 $locate-typeinfo-entry-with-index:end:
    21056 #?     (write-buffered Stderr "returning ")
    21057 #?     (write-int32-hex-buffered Stderr %eax)
    21058 #?     (write-buffered Stderr Newline)
    21059 #?     (flush Stderr)
    21060     # . restore registers
    21061     5f/pop-to-edi
    21062     5e/pop-to-esi
    21063     5b/pop-to-ebx
    21064     5a/pop-to-edx
    21065     59/pop-to-ecx
    21066     # . epilogue
    21067     89/<- %esp 5/r32/ebp
    21068     5d/pop-to-ebp
    21069     c3/return
    21070
    21071 dump-typeinfos:  # hdr: (addr array byte)
    21072     # . prologue
    21073     55/push-ebp
    21074     89/<- %ebp 4/r32/esp
    21075     # . save registers
    21076     50/push-eax
    21077     #
    21078     (write-buffered Stderr *(ebp+8))
    21079     (flush Stderr)
    21080     # var curr/eax: (addr typeinfo) = lookup(Program->types)
    21081     (lookup *_Program-types *_Program-types->payload)  # => eax
    21082     {
    21083       # if (curr == null) break
    21084       3d/compare-eax-and 0/imm32
    21085       74/jump-if-= break/disp8
    21086       (write-buffered Stderr "---\n")
    21087       (flush Stderr)
    21088       (dump-typeinfo %eax)
    21089       # curr = lookup(curr->next)
    21090       (lookup *(eax+0x10) *(eax+0x14))  # Typeinfo-next Typeinfo-next => eax
    21091       eb/jump loop/disp8
    21092     }
    21093 $dump-typeinfos:end:
    21094     # . restore registers
    21095     58/pop-to-eax
    21096     # . epilogue
    21097     89/<- %esp 5/r32/ebp
    21098     5d/pop-to-ebp
    21099     c3/return
    21100
    21101 dump-typeinfo:  # in: (addr typeinfo)
    21102     # . prologue
    21103     55/push-ebp
    21104     89/<- %ebp 4/r32/esp
    21105     # . save registers
    21106     50/push-eax
    21107     51/push-ecx
    21108     52/push-edx
    21109     53/push-ebx
    21110     56/push-esi
    21111     57/push-edi
    21112     # esi = in
    21113     8b/-> *(ebp+8) 6/r32/esi
    21114     # var table/ecx: (addr table (handle array byte) (handle typeinfo-entry)) = lookup(T->fields)
    21115     (lookup *(esi+4) *(esi+8))  # Typeinfo-fields Typeinfo-fields => eax
    21116     89/<- %ecx 0/r32/eax
    21117     (write-buffered Stderr "id:")
    21118     (write-int32-hex-buffered Stderr *esi)
    21119     (write-buffered Stderr "\n")
    21120     (write-buffered Stderr "fields @ ")
    21121     (write-int32-hex-buffered Stderr %ecx)
    21122     (write-buffered Stderr Newline)
    21123     (flush Stderr)
    21124     (write-buffered Stderr "  write: ")
    21125     (write-int32-hex-buffered Stderr *ecx)
    21126     (write-buffered Stderr Newline)
    21127     (flush Stderr)
    21128     (write-buffered Stderr "  read: ")
    21129     (write-int32-hex-buffered Stderr *(ecx+4))
    21130     (write-buffered Stderr Newline)
    21131     (flush Stderr)
    21132     (write-buffered Stderr "  size: ")
    21133     (write-int32-hex-buffered Stderr *(ecx+8))
    21134     (write-buffered Stderr Newline)
    21135     (flush Stderr)
    21136     # var table-size/edx: int = table->write
    21137     8b/-> *ecx 2/r32/edx  # stream-write
    21138     # var curr/ecx: (addr table_row) = table->data
    21139     8d/copy-address *(ecx+0xc) 1/r32/ecx
    21140     # var max/edx: (addr table_row) = table->data + table->write
    21141     8d/copy-address *(ecx+edx) 2/r32/edx
    21142     {
    21143 $dump-typeinfo:loop:
    21144       # if (curr >= max) break
    21145       39/compare %ecx 2/r32/edx
    21146       0f 83/jump-if-addr>= break/disp32
    21147       (write-buffered Stderr "  row:\n")
    21148       (write-buffered Stderr "    key: ")
    21149       (write-int32-hex-buffered Stderr *ecx)
    21150       (write-buffered Stderr ",")
    21151       (write-int32-hex-buffered Stderr *(ecx+4))
    21152       (write-buffered Stderr " = '")
    21153       (lookup *ecx *(ecx+4))
    21154       (write-buffered Stderr %eax)
    21155       (write-buffered Stderr "' @ ")
    21156       (write-int32-hex-buffered Stderr %eax)
    21157       (write-buffered Stderr Newline)
    21158       (flush Stderr)
    21159       (write-buffered Stderr "    value: ")
    21160       (write-int32-hex-buffered Stderr *(ecx+8))
    21161       (write-buffered Stderr ",")
    21162       (write-int32-hex-buffered Stderr *(ecx+0xc))
    21163       (write-buffered Stderr " = typeinfo-entry@")
    21164       (lookup *(ecx+8) *(ecx+0xc))
    21165       (write-int32-hex-buffered Stderr %eax)
    21166       (write-buffered Stderr Newline)
    21167       (flush Stderr)
    21168       (write-buffered Stderr "        input var@")
    21169       (dump-var 5 %eax)
    21170       (lookup *(ecx+8) *(ecx+0xc))
    21171       (write-buffered Stderr "        index: ")
    21172       (write-int32-hex-buffered Stderr *(eax+8))
    21173       (write-buffered Stderr Newline)
    21174       (flush Stderr)
    21175       (write-buffered Stderr "        output var@")
    21176       8d/copy-address *(eax+0xc) 0/r32/eax  # Typeinfo-entry-output-var
    21177       (dump-var 5 %eax)
    21178       (flush Stderr)
    21179       # curr += row-size
    21180       81 0/subop/add %ecx 0x10/imm32  # Typeinfo-fields-row-size
    21181       #
    21182       e9/jump loop/disp32
    21183     }
    21184 $dump-typeinfo:end:
    21185     # . restore registers
    21186     5f/pop-to-edi
    21187     5e/pop-to-esi
    21188     5b/pop-to-ebx
    21189     5a/pop-to-edx
    21190     59/pop-to-ecx
    21191     58/pop-to-eax
    21192     # . epilogue
    21193     89/<- %esp 5/r32/ebp
    21194     5d/pop-to-ebp
    21195     c3/return
    21196
    21197 dump-var:  # indent: int, v: (addr handle var)
    21198     # . prologue
    21199     55/push-ebp
    21200     89/<- %ebp 4/r32/esp
    21201     # . save registers
    21202     50/push-eax
    21203     53/push-ebx
    21204     # eax = v
    21205     8b/-> *(ebp+0xc) 0/r32/eax
    21206     #
    21207     (write-int32-hex-buffered Stderr *eax)
    21208     (write-buffered Stderr ",")
    21209     (write-int32-hex-buffered Stderr *(eax+4))
    21210     (write-buffered Stderr "->")
    21211     (lookup *eax *(eax+4))
    21212     (write-int32-hex-buffered Stderr %eax)
    21213     (write-buffered Stderr Newline)
    21214     (flush Stderr)
    21215     {
    21216       3d/compare-eax-and 0/imm32
    21217       0f 84/jump-if-= break/disp32
    21218       (emit-indent Stderr *(ebp+8))
    21219       (write-buffered Stderr "name: ")
    21220       89/<- %ebx 0/r32/eax
    21221       (write-int32-hex-buffered Stderr *ebx)  # Var-name
    21222       (write-buffered Stderr ",")
    21223       (write-int32-hex-buffered Stderr *(ebx+4))  # Var-name
    21224       (write-buffered Stderr "->")
    21225       (lookup *ebx *(ebx+4))  # Var-name
    21226       (write-int32-hex-buffered Stderr %eax)
    21227       {
    21228         3d/compare-eax-and 0/imm32
    21229         74/jump-if-= break/disp8
    21230         (write-buffered Stderr Space)
    21231         (write-buffered Stderr %eax)
    21232       }
    21233       (write-buffered Stderr Newline)
    21234       (flush Stderr)
    21235       (emit-indent Stderr *(ebp+8))
    21236       (write-buffered Stderr "block depth: ")
    21237       (write-int32-hex-buffered Stderr *(ebx+0x10))  # Var-block-depth
    21238       (write-buffered Stderr Newline)
    21239       (flush Stderr)
    21240       (emit-indent Stderr *(ebp+8))
    21241       (write-buffered Stderr "stack offset: ")
    21242       (write-int32-hex-buffered Stderr *(ebx+0x14))  # Var-offset
    21243       (write-buffered Stderr Newline)
    21244       (flush Stderr)
    21245       (emit-indent Stderr *(ebp+8))
    21246       (write-buffered Stderr "reg: ")
    21247       (write-int32-hex-buffered Stderr *(ebx+0x18))  # Var-register
    21248       (write-buffered Stderr ",")
    21249       (write-int32-hex-buffered Stderr *(ebx+0x1c))  # Var-register
    21250       (write-buffered Stderr "->")
    21251       (flush Stderr)
    21252       (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register
    21253       (write-int32-hex-buffered Stderr %eax)
    21254       {
    21255         3d/compare-eax-and 0/imm32
    21256         74/jump-if-= break/disp8
    21257         (write-buffered Stderr Space)
    21258         (write-buffered Stderr %eax)
    21259       }
    21260       (write-buffered Stderr Newline)
    21261       (flush Stderr)
    21262     }
    21263 $dump-var:end:
    21264     # . restore registers
    21265     5b/pop-to-ebx
    21266     58/pop-to-eax
    21267     # . epilogue
    21268     89/<- %esp 5/r32/ebp
    21269     5d/pop-to-ebp
    21270     c3/return
    21271
    21272 #######################################################
    21273 # Type-checking
    21274 #######################################################
    21275
    21276 check-mu-types:  # err: (addr buffered-file), ed: (addr exit-descriptor)
    21277     # . prologue
    21278     55/push-ebp
    21279     89/<- %ebp 4/r32/esp
    21280     # . save registers
    21281     50/push-eax
    21282     # var curr/eax: (addr function) = lookup(Program->functions)
    21283     (lookup *_Program-functions *_Program-functions->payload)  # => eax
    21284     {
    21285 $check-mu-types:loop:
    21286       # if (curr == null) break
    21287       3d/compare-eax-and 0/imm32
    21288       0f 84/jump-if-= break/disp32
    21289 +--  8 lines: #?       # dump curr->name ------------------------------------------------------------------------------------------------------------------------------------------------
    21297       (check-mu-function %eax *(ebp+8) *(ebp+0xc))
    21298       # curr = lookup(curr->next)
    21299       (lookup *(eax+0x20) *(eax+0x24))  # Function-next Function-next => eax
    21300       e9/jump loop/disp32
    21301     }
    21302 $check-mu-types:end:
    21303     # . restore registers
    21304     58/pop-to-eax
    21305     # . epilogue
    21306     89/<- %esp 5/r32/ebp
    21307     5d/pop-to-ebp
    21308     c3/return
    21309
    21310 check-mu-function:  # fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    21311     # . prologue
    21312     55/push-ebp
    21313     89/<- %ebp 4/r32/esp
    21314     # . save registers
    21315     50/push-eax
    21316     56/push-esi
    21317     # esi = f
    21318     8b/-> *(ebp+8) 6/r32/esi
    21319     # outputs
    21320     (lookup *(esi+0x10) *(esi+0x14))  # Function-outputs Function-outputs => eax
    21321     (check-all-unique-registers %eax %esi *(ebp+0xc) *(ebp+0x10))
    21322     # body
    21323     (lookup *(esi+0x18) *(esi+0x1c))  # Function-body Function-body => eax
    21324     (check-mu-block %eax *(ebp+8) *(ebp+0xc) *(ebp+0x10))
    21325     # if function has no outputs, we're done
    21326     81 7/subop/compare *(esi+0x10) 0/imm32
    21327     74/jump-if-= $check-mu-function:end/disp8
    21328     # some final checks on body
    21329     (check-final-stmt-is-return %eax %esi *(ebp+0xc) *(ebp+0x10))
    21330     (check-no-breaks %eax %esi *(ebp+0xc) *(ebp+0x10))
    21331 $check-mu-function:end:
    21332     # . restore registers
    21333     5e/pop-to-esi
    21334     58/pop-to-eax
    21335     # . epilogue
    21336     89/<- %esp 5/r32/ebp
    21337     5d/pop-to-ebp
    21338     c3/return
    21339
    21340 check-mu-block:  # block: (addr block), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    21341     # . prologue
    21342     55/push-ebp
    21343     89/<- %ebp 4/r32/esp
    21344     # . save registers
    21345     50/push-eax
    21346     # eax = block
    21347     8b/-> *(ebp+8) 0/r32/eax
    21348     # var stmts/eax: (addr list stmt) = lookup(block->statements)
    21349     (lookup *(eax+4) *(eax+8))  # Block-stmts Block-stmts => eax
    21350     #
    21351     {
    21352 $check-mu-block:check-empty:
    21353       3d/compare-eax-and 0/imm32
    21354       0f 84/jump-if-= break/disp32
    21355       # emit block->statements
    21356       (check-mu-stmt-list %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21357     }
    21358 $check-mu-block:end:
    21359     # . restore registers
    21360     58/pop-to-eax
    21361     # . epilogue
    21362     89/<- %esp 5/r32/ebp
    21363     5d/pop-to-ebp
    21364     c3/return
    21365
    21366 check-mu-stmt-list:  # stmts: (addr list stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    21367     # . prologue
    21368     55/push-ebp
    21369     89/<- %ebp 4/r32/esp
    21370     # . save registers
    21371     50/push-eax
    21372     56/push-esi
    21373     # esi = stmts
    21374     8b/-> *(ebp+8) 6/r32/esi
    21375     {
    21376 $check-mu-stmt-list:loop:
    21377       81 7/subop/compare %esi 0/imm32
    21378       0f 84/jump-if-= break/disp32
    21379       # var curr-stmt/eax: (addr stmt) = lookup(stmts->value)
    21380       (lookup *esi *(esi+4))  # List-value List-value => eax
    21381       {
    21382 $check-mu-stmt-list:check-for-block:
    21383         81 7/subop/compare *eax 0/imm32/block  # Stmt-tag
    21384         75/jump-if-!= break/disp8
    21385 $check-mu-stmt-list:block:
    21386         (check-mu-block %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21387         eb/jump $check-mu-stmt-list:continue/disp8
    21388       }
    21389       {
    21390 $check-mu-stmt-list:check-for-stmt1:
    21391         81 7/subop/compare *eax 1/imm32/stmt1  # Stmt-tag
    21392         0f 85/jump-if-!= break/disp32
    21393 $check-mu-stmt-list:stmt1:
    21394         (check-mu-stmt %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21395         eb/jump $check-mu-stmt-list:continue/disp8
    21396       }
    21397       {
    21398 $check-mu-stmt-list:check-for-reg-var-def:
    21399         81 7/subop/compare *eax 3/imm32/reg-var-def  # Stmt-tag
    21400         0f 85/jump-if-!= break/disp32
    21401 $check-mu-stmt-list:reg-var-def:
    21402         (check-mu-stmt %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21403         eb/jump $check-mu-stmt-list:continue/disp8
    21404       }
    21405 $check-mu-stmt-list:continue:
    21406       # TODO: raise an error on unrecognized Stmt-tag
    21407       (lookup *(esi+8) *(esi+0xc))  # List-next List-next => eax
    21408       89/<- %esi 0/r32/eax
    21409       e9/jump loop/disp32
    21410     }
    21411 $check-mu-stmt-list:end:
    21412     # . restore registers
    21413     5e/pop-to-esi
    21414     58/pop-to-eax
    21415     # . epilogue
    21416     89/<- %esp 5/r32/ebp
    21417     5d/pop-to-ebp
    21418     c3/return
    21419
    21420 check-mu-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    21421     # . prologue
    21422     55/push-ebp
    21423     89/<- %ebp 4/r32/esp
    21424     # . save registers
    21425     50/push-eax
    21426     # - if stmt's operation matches a primitive, check against it
    21427     (has-primitive-name? *(ebp+8))  # => eax
    21428     3d/compare-eax-and 0/imm32/false
    21429     {
    21430       74/jump-if-= break/disp8
    21431       (check-mu-primitive *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21432       e9/jump $check-mu-stmt:end/disp32
    21433     }
    21434     # - otherwise find a function to check against
    21435     # var f/eax: (addr function) = lookup(*Program->functions)
    21436     (lookup *_Program-functions *_Program-functions->payload)  # => eax
    21437     (find-matching-function %eax *(ebp+8))  # => eax
    21438     3d/compare-eax-and 0/imm32
    21439     {
    21440       74/jump-if-= break/disp8
    21441       (check-mu-call *(ebp+8) %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21442       eb/jump $check-mu-stmt:end/disp8
    21443     }
    21444     # var f/eax: (addr function) = lookup(*Program->signatures)
    21445     (lookup *_Program-signatures *_Program-signatures->payload)  # => eax
    21446     (find-matching-function %eax *(ebp+8))  # => eax
    21447     3d/compare-eax-and 0/imm32
    21448     {
    21449       74/jump-if-= break/disp8
    21450       (check-mu-call *(ebp+8) %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21451       eb/jump $check-mu-stmt:end/disp8
    21452     }
    21453     # - otherwise abort
    21454     e9/jump $check-mu-stmt:unknown-call/disp32
    21455 $check-mu-stmt:end:
    21456     # . restore registers
    21457     58/pop-to-eax
    21458     # . epilogue
    21459     89/<- %esp 5/r32/ebp
    21460     5d/pop-to-ebp
    21461     c3/return
    21462
    21463 $check-mu-stmt:unknown-call:
    21464     (write-buffered *(ebp+0x10) "unknown function '")
    21465     8b/-> *(ebp+8) 0/r32/eax
    21466     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
    21467     (write-buffered *(ebp+0x10) %eax)
    21468     (write-buffered *(ebp+0x10) "'\n")
    21469     (flush *(ebp+0x10))
    21470     (stop *(ebp+0x14) 1)
    21471     # never gets here
    21472
    21473 has-primitive-name?:  # stmt: (addr stmt) -> result/eax: boolean
    21474     # . prologue
    21475     55/push-ebp
    21476     89/<- %ebp 4/r32/esp
    21477     # . save registers
    21478     51/push-ecx
    21479     56/push-esi
    21480     # var name/esi: (addr array byte) = lookup(stmt->operation)
    21481     8b/-> *(ebp+8) 6/r32/esi
    21482     (lookup *(esi+4) *(esi+8))  # Stmt1-operation Stmt1-operation => eax
    21483     89/<- %esi 0/r32/eax
    21484     # if (name == "return") return true
    21485     (string-equal? %esi "return")  # => eax
    21486     3d/compare-eax-and 0/imm32/false
    21487     0f 85/jump-if-!= $has-primitive-name?:end/disp32
    21488     # if (name == "get") return true
    21489     (string-equal? %esi "get")  # => eax
    21490     3d/compare-eax-and 0/imm32/false
    21491     0f 85/jump-if-!= $has-primitive-name?:end/disp32
    21492     # if (name == "index") return true
    21493     (string-equal? %esi "index")  # => eax
    21494     3d/compare-eax-and 0/imm32/false
    21495     0f 85/jump-if-!= $has-primitive-name?:end/disp32
    21496     # if (name == "length") return true
    21497     (string-equal? %esi "length")  # => eax
    21498     3d/compare-eax-and 0/imm32/false
    21499     0f 85/jump-if-!= $has-primitive-name?:end/disp32
    21500     # if (name == "compute-offset") return true
    21501     (string-equal? %esi "compute-offset")  # => eax
    21502     3d/compare-eax-and 0/imm32/false
    21503     0f 85/jump-if-!= $has-primitive-name?:end/disp32
    21504     # if (name == "copy-object") return true
    21505     (string-equal? %esi "copy-object")  # => eax
    21506     3d/compare-eax-and 0/imm32/false
    21507     0f 85/jump-if-!= $has-primitive-name?:end/disp32
    21508     # if (name == "clear-object") return true
    21509     (string-equal? %esi "clear-object")  # => eax
    21510     3d/compare-eax-and 0/imm32/false
    21511     0f 85/jump-if-!= $has-primitive-name?:end/disp32
    21512     # if (name == "allocate") return true
    21513     (string-equal? %esi "allocate")  # => eax
    21514     3d/compare-eax-and 0/imm32/false
    21515     0f 85/jump-if-!= $has-primitive-name?:end/disp32
    21516     # if (name == "populate") return true
    21517     (string-equal? %esi "populate")  # => eax
    21518     3d/compare-eax-and 0/imm32/false
    21519     0f 85/jump-if-!= $has-primitive-name?:end/disp32
    21520     # if (name == "populate-stream") return true
    21521     (string-equal? %esi "populate-stream")  # => eax
    21522     3d/compare-eax-and 0/imm32/false
    21523     0f 85/jump-if-!= $has-primitive-name?:end/disp32
    21524     # if (name == "read-from-stream") return true
    21525     (string-equal? %esi "read-from-stream")  # => eax
    21526     3d/compare-eax-and 0/imm32/false
    21527     0f 85/jump-if-!= $has-primitive-name?:end/disp32
    21528     # if (name == "write-to-stream") return true
    21529     (string-equal? %esi "write-to-stream")  # => eax
    21530     3d/compare-eax-and 0/imm32/false
    21531     0f 85/jump-if-!= $has-primitive-name?:end/disp32
    21532     # var curr/ecx: (addr primitive) = Primitives
    21533     b9/copy-to-ecx Primitives/imm32
    21534     {
    21535 $has-primitive-name?:loop:
    21536       # if (curr == null) break
    21537       81 7/subop/compare %ecx 0/imm32
    21538       74/jump-if-= break/disp8
    21539       # if (primitive->name == name) return true
    21540       (lookup *ecx *(ecx+4))  # Primitive-name Primitive-name => eax
    21541 #?       (write-buffered Stderr %eax)
    21542 #?       (write-buffered Stderr Newline)
    21543 #?       (flush Stderr)
    21544       (string-equal? %esi %eax)  # => eax
    21545       3d/compare-eax-and 0/imm32/false
    21546       75/jump-if-!= $has-primitive-name?:end/disp8
    21547 $has-primitive-name?:next-primitive:
    21548       # curr = curr->next
    21549       (lookup *(ecx+0x3c) *(ecx+0x40))  # Primitive-next Primitive-next => eax
    21550       89/<- %ecx 0/r32/eax
    21551       #
    21552       e9/jump loop/disp32
    21553     }
    21554     # return null
    21555     b8/copy-to-eax 0/imm32
    21556 $has-primitive-name?:end:
    21557     # . restore registers
    21558     5e/pop-to-esi
    21559     59/pop-to-ecx
    21560     # . epilogue
    21561     89/<- %esp 5/r32/ebp
    21562     5d/pop-to-ebp
    21563     c3/return
    21564
    21565 check-mu-primitive:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    21566     # . prologue
    21567     55/push-ebp
    21568     89/<- %ebp 4/r32/esp
    21569     # . save registers
    21570     50/push-eax
    21571     51/push-ecx
    21572     # var op/ecx: (addr array byte) = lookup(stmt->operation)
    21573     8b/-> *(ebp+8) 0/r32/eax
    21574     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
    21575     89/<- %ecx 0/r32/eax
    21576     # if (op == "copy") check-mu-copy-stmt
    21577     {
    21578       (string-equal? %ecx "copy")  # => eax
    21579       3d/compare-eax-and 0/imm32/false
    21580       74/jump-if-= break/disp8
    21581       (check-mu-copy-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21582       e9/jump $check-mu-primitive:end/disp32
    21583     }
    21584     # if (op == "copy-to") check-mu-copy-to-stmt
    21585     {
    21586       (string-equal? %ecx "copy-to")  # => eax
    21587       3d/compare-eax-and 0/imm32/false
    21588       74/jump-if-= break/disp8
    21589       (check-mu-copy-to-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21590       e9/jump $check-mu-primitive:end/disp32
    21591     }
    21592     # if (op == "copy-byte") check-mu-copy-byte-stmt
    21593     {
    21594       (string-equal? %ecx "copy-byte")  # => eax
    21595       3d/compare-eax-and 0/imm32/false
    21596       74/jump-if-= break/disp8
    21597       (check-mu-copy-byte-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21598       e9/jump $check-mu-primitive:end/disp32
    21599     }
    21600     # if (op == "copy-byte-to") check-mu-copy-byte-to-stmt
    21601     {
    21602       (string-equal? %ecx "copy-byte-to")  # => eax
    21603       3d/compare-eax-and 0/imm32/false
    21604       74/jump-if-= break/disp8
    21605       (check-mu-copy-byte-to-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21606       e9/jump $check-mu-primitive:end/disp32
    21607     }
    21608     # if (op == "compare") check-mu-compare-stmt
    21609     {
    21610       (string-equal? %ecx "compare")  # => eax
    21611       3d/compare-eax-and 0/imm32/false
    21612       74/jump-if-= break/disp8
    21613       (check-mu-compare-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21614       e9/jump $check-mu-primitive:end/disp32
    21615     }
    21616     # if (op == "address") check-mu-address-stmt
    21617     {
    21618       (string-equal? %ecx "address")  # => eax
    21619       3d/compare-eax-and 0/imm32/false
    21620       74/jump-if-= break/disp8
    21621       (check-mu-address-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21622       e9/jump $check-mu-primitive:end/disp32
    21623     }
    21624     # if (op == "return") check-mu-return-stmt
    21625     {
    21626       (string-equal? %ecx "return")  # => eax
    21627       3d/compare-eax-and 0/imm32/false
    21628       74/jump-if-= break/disp8
    21629       (check-mu-return-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21630       e9/jump $check-mu-primitive:end/disp32
    21631     }
    21632     # if (op == "get") check-mu-get-stmt
    21633     {
    21634       (string-equal? %ecx "get")  # => eax
    21635       3d/compare-eax-and 0/imm32/false
    21636       74/jump-if-= break/disp8
    21637       (check-mu-get-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21638       e9/jump $check-mu-primitive:end/disp32
    21639     }
    21640     # if (op == "index") check-mu-index-stmt
    21641     {
    21642       (string-equal? %ecx "index")  # => eax
    21643       3d/compare-eax-and 0/imm32/false
    21644       74/jump-if-= break/disp8
    21645       (check-mu-index-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21646       e9/jump $check-mu-primitive:end/disp32
    21647     }
    21648     # if (op == "length") check-mu-length-stmt
    21649     {
    21650       (string-equal? %ecx "length")  # => eax
    21651       3d/compare-eax-and 0/imm32/false
    21652       74/jump-if-= break/disp8
    21653       (check-mu-length-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21654       e9/jump $check-mu-primitive:end/disp32
    21655     }
    21656     # if (op == "compute-offset") check-mu-compute-offset-stmt
    21657     {
    21658       (string-equal? %ecx "compute-offset")  # => eax
    21659       3d/compare-eax-and 0/imm32/false
    21660       74/jump-if-= break/disp8
    21661       (check-mu-compute-offset-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21662       e9/jump $check-mu-primitive:end/disp32
    21663     }
    21664     # if (op == "copy-object") check-mu-copy-object-stmt
    21665     {
    21666       (string-equal? %ecx "copy-object")  # => eax
    21667       3d/compare-eax-and 0/imm32/false
    21668       74/jump-if-= break/disp8
    21669       (check-mu-copy-object-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21670       e9/jump $check-mu-primitive:end/disp32
    21671     }
    21672     # if (op == "clear-object") check-mu-clear-object-stmt
    21673     {
    21674       (string-equal? %ecx "clear-object")  # => eax
    21675       3d/compare-eax-and 0/imm32/false
    21676       74/jump-if-= break/disp8
    21677       (check-mu-clear-object-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21678       e9/jump $check-mu-primitive:end/disp32
    21679     }
    21680     # if (op == "allocate") check-mu-allocate-stmt
    21681     {
    21682       (string-equal? %ecx "allocate")  # => eax
    21683       3d/compare-eax-and 0/imm32/false
    21684       74/jump-if-= break/disp8
    21685       (check-mu-allocate-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21686       e9/jump $check-mu-primitive:end/disp32
    21687     }
    21688     # if (op == "populate") check-mu-populate-stmt
    21689     {
    21690       (string-equal? %ecx "populate")  # => eax
    21691       3d/compare-eax-and 0/imm32/false
    21692       74/jump-if-= break/disp8
    21693       (check-mu-populate-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21694       e9/jump $check-mu-primitive:end/disp32
    21695     }
    21696     # if (op == "populate-stream") check-mu-populate-stream-stmt
    21697     {
    21698       (string-equal? %ecx "populate-stream")  # => eax
    21699       3d/compare-eax-and 0/imm32/false
    21700       74/jump-if-= break/disp8
    21701       (check-mu-populate-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21702       e9/jump $check-mu-primitive:end/disp32
    21703     }
    21704     # if (op == "read-from-stream") check-mu-read-from-stream-stmt
    21705     {
    21706       (string-equal? %ecx "read-from-stream")  # => eax
    21707       3d/compare-eax-and 0/imm32/false
    21708       74/jump-if-= break/disp8
    21709       (check-mu-read-from-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21710       e9/jump $check-mu-primitive:end/disp32
    21711     }
    21712     # if (op == "write-to-stream") check-mu-write-to-stream-stmt
    21713     {
    21714       (string-equal? %ecx "write-to-stream")  # => eax
    21715       3d/compare-eax-and 0/imm32/false
    21716       74/jump-if-= break/disp8
    21717       (check-mu-write-to-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21718       e9/jump $check-mu-primitive:end/disp32
    21719     }
    21720     # if (op == "convert") check-mu-convert-stmt
    21721     {
    21722       (string-equal? %ecx "convert")  # => eax
    21723       3d/compare-eax-and 0/imm32/false
    21724       74/jump-if-= break/disp8
    21725       (check-mu-convert-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21726       e9/jump $check-mu-primitive:end/disp32
    21727     }
    21728     # otherwise check-numberlike-stmt
    21729     (check-mu-numberlike-primitive *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21730 $check-mu-primitive:end:
    21731     # . restore registers
    21732     59/pop-to-ecx
    21733     58/pop-to-eax
    21734     # . epilogue
    21735     89/<- %esp 5/r32/ebp
    21736     5d/pop-to-ebp
    21737     c3/return
    21738
    21739 # by default, Mu primitives should only operate on 'number-like' types
    21740 check-mu-numberlike-primitive:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    21741     # . prologue
    21742     55/push-ebp
    21743     89/<- %ebp 4/r32/esp
    21744     # . save registers
    21745     50/push-eax
    21746     51/push-ecx
    21747     56/push-esi
    21748     # esi = stmt
    21749     8b/-> *(ebp+8) 6/r32/esi
    21750     # var gas/ecx: int = 2
    21751     b9/copy-to-ecx 2/imm32
    21752     # - check at most 1 output
    21753     # var output/eax: (addr stmt-var) = stmt->outputs
    21754     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    21755     {
    21756       3d/compare-eax-and 0/imm32
    21757       74/jump-if-= break/disp8
    21758 $check-mu-numberlike-primitive:output:
    21759       (check-mu-numberlike-output %eax *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21760       (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    21761       3d/compare-eax-and 0/imm32
    21762       0f 85/jump-if-!= $check-mu-numberlike-primitive:error-too-many-outputs/disp32
    21763       # check output is in a register
    21764       # --gas
    21765       49/decrement-ecx
    21766     }
    21767     # - check first inout
    21768     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    21769     {
    21770       3d/compare-eax-and 0/imm32
    21771       0f 84/jump-if-= $check-mu-numberlike-primitive:end/disp32
    21772 $check-mu-numberlike-primitive:first-inout:
    21773       (check-mu-numberlike-arg %eax *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21774       # --gas
    21775       49/decrement-ecx
    21776     }
    21777     # - check second inout
    21778     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    21779     {
    21780       3d/compare-eax-and 0/imm32
    21781       74/jump-if-= $check-mu-numberlike-primitive:end/disp8
    21782 $check-mu-numberlike-primitive:second-inout:
    21783       # is a second inout allowed?
    21784       81 7/subop/compare %ecx 0/imm32
    21785       0f 84/jump-if-= $check-mu-numberlike-primitive:error-too-many-inouts/disp32
    21786 $check-mu-numberlike-primitive:second-inout-permitted:
    21787       (check-mu-numberlike-arg %eax *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21788     }
    21789 $check-mu-numberlike-primitive:third-inout:
    21790     # if there's a third arg, raise an error
    21791     81 7/subop/compare *(eax+8) 0/imm32  # Stmt-var-next
    21792     0f 85/jump-if-!= $check-mu-numberlike-primitive:error-too-many-inouts/disp32
    21793 $check-mu-numberlike-primitive:end:
    21794     # . restore registers
    21795     5e/pop-to-esi
    21796     59/pop-to-ecx
    21797     58/pop-to-eax
    21798     # . epilogue
    21799     89/<- %esp 5/r32/ebp
    21800     5d/pop-to-ebp
    21801     c3/return
    21802
    21803 $check-mu-numberlike-primitive:error-too-many-inouts:
    21804     (write-buffered *(ebp+0x10) "fn ")
    21805     8b/-> *(ebp+0xc) 0/r32/eax
    21806     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    21807     (write-buffered *(ebp+0x10) %eax)
    21808     (write-buffered *(ebp+0x10) ": stmt ")
    21809     (lookup *(esi+4) *(esi+8))  # Stmt1-operation Stmt1-operation => eax
    21810     (write-buffered *(ebp+0x10) %eax)
    21811     (write-buffered *(ebp+0x10) ": too many inouts; most primitives support at most two arguments, across inouts and outputs\n")
    21812     (flush *(ebp+0x10))
    21813     (stop *(ebp+0x14) 1)
    21814     # never gets here
    21815
    21816 $check-mu-numberlike-primitive:error-too-many-outputs:
    21817     (write-buffered *(ebp+0x10) "fn ")
    21818     8b/-> *(ebp+0xc) 0/r32/eax
    21819     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    21820     (write-buffered *(ebp+0x10) %eax)
    21821     (write-buffered *(ebp+0x10) ": stmt ")
    21822     (lookup *(esi+4) *(esi+8))  # Stmt1-operation Stmt1-operation => eax
    21823     (write-buffered *(ebp+0x10) %eax)
    21824     (write-buffered *(ebp+0x10) ": too many outputs; most primitives support at most one output\n")
    21825     (flush *(ebp+0x10))
    21826     (stop *(ebp+0x14) 1)
    21827     # never gets here
    21828
    21829 check-mu-numberlike-arg:  # v: (addr stmt-var), stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    21830     # . prologue
    21831     55/push-ebp
    21832     89/<- %ebp 4/r32/esp
    21833     # . save registers
    21834     50/push-eax
    21835     56/push-esi
    21836     # var t/esi: (addr type-tree) = lookup(v->value->type)
    21837     8b/-> *(ebp+8) 0/r32/eax
    21838     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    21839     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    21840     89/<- %esi 0/r32/eax
    21841 $check-mu-numberlike-arg:check-literal:
    21842     # if t is an int, return
    21843     (simple-mu-type? %esi 0)  # literal => eax
    21844     3d/compare-eax-and 0/imm32/false
    21845     0f 85/jump-if-!= $check-mu-numberlike-arg:end/disp32
    21846 $check-mu-numberlike-arg:check-addr:
    21847     # if t is an addr and v is dereferenced, return whether t->payload is an addr
    21848     {
    21849       (mu-addr-type? %esi)  # => eax
    21850       3d/compare-eax-and 0/imm32/false
    21851       74/jump-if-= break/disp8
    21852       8b/-> *(ebp+8) 0/r32/eax
    21853       8b/-> *(eax+0x10) 0/r32/eax  # Stmt-var-is-deref
    21854       3d/compare-eax-and 0/imm32/false
    21855       {
    21856         74/jump-if-= break/disp8
    21857         (lookup *(esi+0xc) *(esi+0x10))  # Type-tree-right Type-tree-right => eax
    21858         # if t->right is null, t = t->left
    21859         81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
    21860         {
    21861           75/jump-if-!= break/disp8
    21862           (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    21863         }
    21864         (mu-addr-type? %eax)  # => eax
    21865         3d/compare-eax-and 0/imm32/false
    21866         74/jump-if-= $check-mu-numberlike-arg:end/disp8
    21867       }
    21868     }
    21869 $check-mu-numberlike-arg:output-checks:
    21870     (check-mu-numberlike-output *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14) *(ebp+0x18))
    21871 $check-mu-numberlike-arg:end:
    21872     # . restore registers
    21873     5e/pop-to-esi
    21874     58/pop-to-eax
    21875     # . epilogue
    21876     89/<- %esp 5/r32/ebp
    21877     5d/pop-to-ebp
    21878     c3/return
    21879
    21880 check-mu-numberlike-output:  # v: (addr stmt-var), stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    21881     # . prologue
    21882     55/push-ebp
    21883     89/<- %ebp 4/r32/esp
    21884     # . save registers
    21885     50/push-eax
    21886     #
    21887     (mu-numberlike-output-var? *(ebp+8))  # => eax
    21888     3d/compare-eax-and 0/imm32/false
    21889     0f 84/jump-if-= $check-mu-numberlike-output:fail/disp32
    21890 $check-mu-numberlike-output:end:
    21891     # . restore registers
    21892     58/pop-to-eax
    21893     # . epilogue
    21894     89/<- %esp 5/r32/ebp
    21895     5d/pop-to-ebp
    21896     c3/return
    21897
    21898 $check-mu-numberlike-output:fail:
    21899     # otherwise raise an error
    21900     (write-buffered *(ebp+0x14) "fn ")
    21901     8b/-> *(ebp+0x10) 0/r32/eax
    21902     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    21903     (write-buffered *(ebp+0x14) %eax)
    21904     (write-buffered *(ebp+0x14) ": stmt ")
    21905     8b/-> *(ebp+0xc) 0/r32/eax
    21906     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
    21907     (write-buffered *(ebp+0x14) %eax)
    21908     (write-buffered *(ebp+0x14) ": '")
    21909     8b/-> *(ebp+8) 0/r32/eax
    21910     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    21911     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    21912     (write-buffered *(ebp+0x14) %eax)
    21913     (write-buffered *(ebp+0x14) "' must be a non-addr non-offset scalar\n")
    21914     (flush *(ebp+0x14))
    21915     (stop *(ebp+0x18) 1)
    21916     # never gets here
    21917
    21918 mu-numberlike-output-var?:  # v: (addr stmt-var) -> result/eax: boolean
    21919     # . prologue
    21920     55/push-ebp
    21921     89/<- %ebp 4/r32/esp
    21922     #
    21923     8b/-> *(ebp+8) 0/r32/eax
    21924     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    21925     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    21926     (mu-numberlike-output? %eax)  # => eax
    21927 $mu-numberlike-output-var?:end:
    21928     # . epilogue
    21929     89/<- %esp 5/r32/ebp
    21930     5d/pop-to-ebp
    21931     c3/return
    21932
    21933 mu-numberlike-output?:  # v: (addr type-tree) -> result/eax: boolean
    21934     # . prologue
    21935     55/push-ebp
    21936     89/<- %ebp 4/r32/esp
    21937     # . save registers
    21938     56/push-esi
    21939     # var t/esi: (addr type-tree) = lookup(v->value->type)
    21940     8b/-> *(ebp+8) 6/r32/esi
    21941 $mu-numberlike-output?:check-int:
    21942     # if t is an int, return
    21943     (simple-mu-type? %esi 1)  # int => eax
    21944     3d/compare-eax-and 0/imm32/false
    21945     0f 85/jump-if-!= $mu-numberlike-output?:return-true/disp32
    21946 $mu-numberlike-output?:check-float:
    21947     # if t is a float, return
    21948     (simple-mu-type? %esi 0xf)  # float => eax
    21949     3d/compare-eax-and 0/imm32/false
    21950     75/jump-if-!= $mu-numberlike-output?:return-true/disp8
    21951 $mu-numberlike-output?:check-boolean:
    21952     # if t is a boolean, return
    21953     (simple-mu-type? %esi 5)  # boolean => eax
    21954     3d/compare-eax-and 0/imm32/false
    21955     75/jump-if-!= $mu-numberlike-output?:return-true/disp8
    21956 $mu-numberlike-output?:check-byte:
    21957     # if t is a byte, return
    21958     (simple-mu-type? %esi 8)  # byte => eax
    21959     3d/compare-eax-and 0/imm32/false
    21960     75/jump-if-!= $mu-numberlike-output?:return-true/disp8
    21961 $mu-numberlike-output?:check-code-point:
    21962     # if t is a code-point, return
    21963     (simple-mu-type? %esi 0xd)  # code-point => eax
    21964     3d/compare-eax-and 0/imm32/false
    21965     75/jump-if-!= $mu-numberlike-output?:return-true/disp8
    21966 $mu-numberlike-output?:check-grapheme:
    21967     # if t is a grapheme, return
    21968     (simple-mu-type? %esi 0xe)  # grapheme => eax
    21969     3d/compare-eax-and 0/imm32/false
    21970     75/jump-if-!= $mu-numberlike-output?:return-true/disp8
    21971 $mu-numberlike-output?:return-false:
    21972     b8/copy-to-eax 0/imm32/false
    21973     eb/jump $mu-numberlike-output?:end/disp8
    21974 $mu-numberlike-output?:return-true:
    21975     b8/copy-to-eax 1/imm32/true
    21976 $mu-numberlike-output?:end:
    21977     # . restore registers
    21978     5e/pop-to-esi
    21979     # . epilogue
    21980     89/<- %esp 5/r32/ebp
    21981     5d/pop-to-ebp
    21982     c3/return
    21983
    21984 check-mu-copy-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    21985     # . prologue
    21986     55/push-ebp
    21987     89/<- %ebp 4/r32/esp
    21988     # . save registers
    21989     50/push-eax
    21990     51/push-ecx
    21991     52/push-edx
    21992     56/push-esi
    21993     57/push-edi
    21994     # var type-parameters/edx: (addr table (handle array byte) (addr type-tree) 8)
    21995     81 5/subop/subtract %esp 0x60/imm32
    21996     68/push 0x60/imm32/size
    21997     68/push 0/imm32/read
    21998     68/push 0/imm32/write
    21999     89/<- %edx 4/r32/esp
    22000 $check-mu-copy-stmt:get-output:
    22001     # esi = stmt
    22002     8b/-> *(ebp+8) 6/r32/esi
    22003     # var output/edi: (addr stmt-var) = stmt->outputs
    22004     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    22005     89/<- %edi 0/r32/eax
    22006     # zero outputs
    22007     3d/compare-eax-and 0/imm32
    22008     0f 84/jump-if-= $check-mu-copy-stmt:error-no-output/disp32
    22009     # > 1 output
    22010     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
    22011     3d/compare-eax-and 0/imm32
    22012     0f 85/jump-if-!= $check-mu-copy-stmt:error-too-many-outputs/disp32
    22013 $check-mu-copy-stmt:get-inout:
    22014     # var inout/esi: (addr stmt-var) = stmt->inouts
    22015     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    22016     89/<- %esi 0/r32/eax
    22017     # zero inouts
    22018     3d/compare-eax-and 0/imm32
    22019     0f 84/jump-if-= $check-mu-copy-stmt:error-no-inout/disp32
    22020     # > 1 inout
    22021     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
    22022     3d/compare-eax-and 0/imm32
    22023     0f 85/jump-if-!= $check-mu-copy-stmt:error-too-many-inouts/disp32
    22024 $check-mu-copy-stmt:types:
    22025     # if inout is not a scalar, abort
    22026     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    22027     (size-of %eax)  # => eax
    22028     3d/compare-eax-and 4/imm32
    22029     0f 8f/jump-if-> $check-mu-copy-stmt:error-inout-too-large/disp32
    22030     # var inout-type/ecx: (addr type-tree) = inout->value->type
    22031     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    22032     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    22033     89/<- %ecx 0/r32/eax
    22034     # if (inout->is-deref?) inout-type = inout-type->payload
    22035     8b/-> *(esi+0x10) 0/r32/eax  # Stmt-var-is-deref
    22036     3d/compare-eax-and 0/imm32/false
    22037     {
    22038       74/jump-if-= break/disp8
    22039       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
    22040       # if inout-type->right is null, t = inout-type->left
    22041       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
    22042       {
    22043         75/jump-if-!= break/disp8
    22044         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    22045       }
    22046       89/<- %ecx 0/r32/eax
    22047     }
    22048     # if output not in register, abort
    22049     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    22050     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    22051     3d/compare-eax-and 0/imm32
    22052     0f 84/jump-if-= $check-mu-copy-stmt:error-output-not-in-register/disp32
    22053     # var output-type/eax: (addr type-tree) = output->value->type
    22054     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    22055     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    22056     # if (inout-type == output-type) return
    22057     (type-match? %eax %ecx %edx)  # => eax
    22058     3d/compare-eax-and 0/imm32
    22059     0f 85/jump-if-!= $check-mu-copy-stmt:end/disp32
    22060     # if output is an addr and inout is 0, return
    22061     {
    22062       (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    22063       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    22064       (mu-addr-type? %eax)  # => eax
    22065       3d/compare-eax-and 0/imm32/false
    22066       74/jump-if-= break/disp8
    22067       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    22068       (lookup *eax *(eax+4))  # Var-name Var-name => eax
    22069       (string-equal? %eax "0")  # => eax
    22070       3d/compare-eax-and 0/imm32/false
    22071       74/jump-if-= break/disp8
    22072       e9/jump $check-mu-copy-stmt:end/disp32
    22073     }
    22074     # if output is an offset and inout is 0, return
    22075     {
    22076       (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    22077       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    22078       81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
    22079       75/jump-if-!= break/disp8
    22080       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    22081       (simple-mu-type? %eax 7)  # offset => eax
    22082       3d/compare-eax-and 0/imm32/false
    22083       74/jump-if-= break/disp8
    22084       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    22085       (lookup *eax *(eax+4))  # Var-name Var-name => eax
    22086       (string-equal? %eax "0")  # => eax
    22087       3d/compare-eax-and 0/imm32/false
    22088       74/jump-if-= break/disp8
    22089       e9/jump $check-mu-copy-stmt:end/disp32
    22090     }
    22091     # if output is a byte, abort if inout is not a literal. Otherwise return.
    22092     {
    22093       (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    22094       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    22095       (simple-mu-type? %eax 8)  # byte => eax
    22096       3d/compare-eax-and 0/imm32/false
    22097       74/jump-if-= break/disp8
    22098       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    22099       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    22100       (simple-mu-type? %eax 0)  # literal => eax
    22101       3d/compare-eax-and 0/imm32/false
    22102       0f 84/jump-if-= $check-mu-copy-stmt:error-non-literal-to-byte/disp32
    22103       eb/jump $check-mu-copy-stmt:end/disp8
    22104     }
    22105     # if output is not number-like, abort
    22106     (check-mu-numberlike-output %edi *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    22107 $check-mu-copy-stmt:end:
    22108     # . reclaim locals
    22109     81 0/subop/add %esp 0x6c/imm32
    22110     # . restore registers
    22111     5f/pop-to-edi
    22112     5e/pop-to-esi
    22113     5a/pop-to-edx
    22114     59/pop-to-ecx
    22115     58/pop-to-eax
    22116     # . epilogue
    22117     89/<- %esp 5/r32/ebp
    22118     5d/pop-to-ebp
    22119     c3/return
    22120
    22121 $check-mu-copy-stmt:error-no-inout:
    22122     (write-buffered *(ebp+0x10) "fn ")
    22123     8b/-> *(ebp+0xc) 0/r32/eax
    22124     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22125     (write-buffered *(ebp+0x10) %eax)
    22126     (write-buffered *(ebp+0x10) ": stmt 'copy' expects an inout\n")
    22127     (flush *(ebp+0x10))
    22128     (stop *(ebp+0x14) 1)
    22129     # never gets here
    22130
    22131 $check-mu-copy-stmt:error-too-many-inouts:
    22132     (write-buffered *(ebp+0x10) "fn ")
    22133     8b/-> *(ebp+0xc) 0/r32/eax
    22134     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22135     (write-buffered *(ebp+0x10) %eax)
    22136     (write-buffered *(ebp+0x10) ": stmt 'copy' must have just one inout\n")
    22137     (flush *(ebp+0x10))
    22138     (stop *(ebp+0x14) 1)
    22139     # never gets here
    22140
    22141 $check-mu-copy-stmt:error-no-output:
    22142     (write-buffered *(ebp+0x10) "fn ")
    22143     8b/-> *(ebp+0xc) 0/r32/eax
    22144     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22145     (write-buffered *(ebp+0x10) %eax)
    22146     (write-buffered *(ebp+0x10) ": stmt 'copy' expects an output\n")
    22147     (flush *(ebp+0x10))
    22148     (stop *(ebp+0x14) 1)
    22149     # never gets here
    22150
    22151 $check-mu-copy-stmt:error-output-not-in-register:
    22152     (write-buffered *(ebp+0x10) "fn ")
    22153     8b/-> *(ebp+0xc) 0/r32/eax
    22154     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22155     (write-buffered *(ebp+0x10) %eax)
    22156     (write-buffered *(ebp+0x10) ": stmt copy: output '")
    22157     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    22158     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    22159     (write-buffered *(ebp+0x10) %eax)
    22160     (write-buffered *(ebp+0x10) "' not in a register\n")
    22161     (flush *(ebp+0x10))
    22162     (stop *(ebp+0x14) 1)
    22163     # never gets here
    22164
    22165 $check-mu-copy-stmt:error-too-many-outputs:
    22166     (write-buffered *(ebp+0x10) "fn ")
    22167     8b/-> *(ebp+0xc) 0/r32/eax
    22168     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22169     (write-buffered *(ebp+0x10) %eax)
    22170     (write-buffered *(ebp+0x10) ": stmt 'copy' must have just one output\n")
    22171     (flush *(ebp+0x10))
    22172     (stop *(ebp+0x14) 1)
    22173     # never gets here
    22174
    22175 $check-mu-copy-stmt:error-inout-too-large:
    22176     (write-buffered *(ebp+0x10) "fn ")
    22177     8b/-> *(ebp+0xc) 0/r32/eax
    22178     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22179     (write-buffered *(ebp+0x10) %eax)
    22180     (write-buffered *(ebp+0x10) ": stmt copy: '")
    22181     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    22182     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    22183     (write-buffered *(ebp+0x10) %eax)
    22184     (write-buffered *(ebp+0x10) "' is too large to fit in a register\n")
    22185     (flush *(ebp+0x10))
    22186     (stop *(ebp+0x14) 1)
    22187     # never gets here
    22188
    22189 $check-mu-copy-stmt:error-non-literal-to-byte:
    22190     (write-buffered *(ebp+0x10) "fn ")
    22191     8b/-> *(ebp+0xc) 0/r32/eax
    22192     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22193     (write-buffered *(ebp+0x10) %eax)
    22194     (write-buffered *(ebp+0x10) ": stmt copy: cannot copy non-literal to '")
    22195     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    22196     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    22197     (write-buffered *(ebp+0x10) %eax)
    22198     (write-buffered *(ebp+0x10) "' of type byte; use copy-byte\n")
    22199     (flush *(ebp+0x10))
    22200     (stop *(ebp+0x14) 1)
    22201     # never gets here
    22202
    22203 check-mu-copy-to-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    22204     # . prologue
    22205     55/push-ebp
    22206     89/<- %ebp 4/r32/esp
    22207     # . save registers
    22208     50/push-eax
    22209     51/push-ecx
    22210     52/push-edx
    22211     53/push-ebx
    22212     56/push-esi
    22213     57/push-edi
    22214     # var type-parameters/edx: (addr table (handle array byte) (addr type-tree) 8)
    22215     81 5/subop/subtract %esp 0x60/imm32
    22216     68/push 0x60/imm32/size
    22217     68/push 0/imm32/read
    22218     68/push 0/imm32/write
    22219     89/<- %edx 4/r32/esp
    22220     # esi = stmt
    22221     8b/-> *(ebp+8) 6/r32/esi
    22222 $check-mu-copy-to-stmt:check-for-output:
    22223     # if stmt->outputs abort
    22224     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    22225     3d/compare-eax-and 0/imm32
    22226     0f 85/jump-if-!= $check-mu-copy-to-stmt:error-too-many-outputs/disp32
    22227 $check-mu-copy-to-stmt:get-dest:
    22228     # var dest/edi: (addr stmt-var) = stmt->inouts
    22229     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    22230     89/<- %edi 0/r32/eax
    22231     # zero inouts
    22232     3d/compare-eax-and 0/imm32
    22233     0f 84/jump-if-= $check-mu-copy-to-stmt:error-incorrect-inouts/disp32
    22234 $check-mu-copy-to-stmt:get-src:
    22235     # var src/esi: (addr stmt-var) = dest->next
    22236     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
    22237     89/<- %esi 0/r32/eax
    22238     # 1 inout
    22239     3d/compare-eax-and 0/imm32
    22240     0f 84/jump-if-= $check-mu-copy-to-stmt:error-incorrect-inouts/disp32
    22241     # > 2 inouts
    22242     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
    22243     3d/compare-eax-and 0/imm32
    22244     0f 85/jump-if-!= $check-mu-copy-to-stmt:error-incorrect-inouts/disp32
    22245 $check-mu-copy-to-stmt:types:
    22246     # if src is not a scalar, abort
    22247     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    22248     (size-of %eax)  # => eax
    22249     3d/compare-eax-and 4/imm32
    22250     0f 8f/jump-if-> $check-mu-copy-to-stmt:error-src-too-large/disp32
    22251     # var src-type/ecx: (addr type-tree) = src->value->type
    22252     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    22253     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    22254     89/<- %ecx 0/r32/eax
    22255     # if src not in register or literal, abort
    22256     # (we can't use stack-offset because it hasn't been computed yet)
    22257     {
    22258       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    22259       (lookup *(eax+0x8) *(eax+0xc))  # Var-type Var-type => eax
    22260       (simple-mu-type? %eax 0)  # => eax
    22261       3d/compare-eax-and 0/imm32
    22262       75/jump-if-!= break/disp8
    22263       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    22264       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    22265       3d/compare-eax-and 0/imm32
    22266       75/jump-if-!= break/disp8
    22267       e9/jump $check-mu-copy-to-stmt:error-src-not-literal-or-in-register/disp32
    22268     }
    22269     # var dest-type/ebx: (addr type-tree) = dest->value->type
    22270     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    22271     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    22272     89/<- %ebx 0/r32/eax
    22273     # if (dest->is-deref?) dest-type = dest-type->payload
    22274 $check-mu-copy-to-stmt:check-dest-deref:
    22275     8b/-> *(edi+0x10) 0/r32/eax  # Stmt-var-is-deref
    22276     3d/compare-eax-and 0/imm32/false
    22277     {
    22278       74/jump-if-= break/disp8
    22279       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
    22280 $check-mu-copy-to-stmt:dest-is-deref:
    22281       # if dest-type->right is null, dest-type = dest-type->left
    22282       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
    22283       {
    22284         75/jump-if-!= break/disp8
    22285 $check-mu-copy-to-stmt:dest-is-deref2:
    22286         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    22287       }
    22288       89/<- %ebx 0/r32/eax
    22289     }
    22290     # if dest is a byte and src is not a literal, abort
    22291     {
    22292 $check-mu-copy-to-stmt:final-check-byte:
    22293       (simple-mu-type? %ebx 8)  # byte => eax
    22294       3d/compare-eax-and 0/imm32/false
    22295       74/jump-if-= break/disp8
    22296       (simple-mu-type? %ecx 0)  # literal => eax
    22297       3d/compare-eax-and 0/imm32/false
    22298       0f 84/jump-if-= $check-mu-copy-to-stmt:error-non-literal-to-byte/disp32
    22299     }
    22300     # if (src-type == dest-type) return
    22301     (type-match? %ebx %ecx %edx)  # => eax
    22302     3d/compare-eax-and 0/imm32
    22303     0f 85/jump-if-!= $check-mu-copy-to-stmt:end/disp32
    22304     # if dest is an addr and src is 0, return
    22305     {
    22306 $check-mu-copy-to-stmt:final-check-addr:
    22307       (mu-addr-type? %ebx)  # => eax
    22308       3d/compare-eax-and 0/imm32/false
    22309       74/jump-if-= break/disp8
    22310       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    22311       (lookup *eax *(eax+4))  # Var-name Var-name => eax
    22312       (string-equal? %eax "0")  # => eax
    22313       3d/compare-eax-and 0/imm32/false
    22314       74/jump-if-= break/disp8
    22315       e9/jump $check-mu-copy-to-stmt:end/disp32
    22316     }
    22317     # if dest is an offset and src is 0, return
    22318     {
    22319 $check-mu-copy-to-stmt:final-check-offset:
    22320       81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
    22321       75/jump-if-!= break/disp8
    22322       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
    22323       (simple-mu-type? %eax 7)  # offset => eax
    22324       3d/compare-eax-and 0/imm32/false
    22325       74/jump-if-= break/disp8
    22326       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    22327       (lookup *eax *(eax+4))  # Var-name Var-name => eax
    22328       (string-equal? %eax "0")  # => eax
    22329       3d/compare-eax-and 0/imm32/false
    22330       74/jump-if-= break/disp8
    22331       e9/jump $check-mu-copy-to-stmt:end/disp32
    22332     }
    22333     # if dest is not number-like, abort
    22334     (check-mu-numberlike-arg %edi *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    22335 $check-mu-copy-to-stmt:end:
    22336     # . reclaim locals
    22337     81 0/subop/add %esp 0x6c/imm32
    22338     # . restore registers
    22339     5f/pop-to-edi
    22340     5e/pop-to-esi
    22341     5b/pop-to-ebx
    22342     5a/pop-to-edx
    22343     59/pop-to-ecx
    22344     58/pop-to-eax
    22345     # . epilogue
    22346     89/<- %esp 5/r32/ebp
    22347     5d/pop-to-ebp
    22348     c3/return
    22349
    22350 $check-mu-copy-to-stmt:error-incorrect-inouts:
    22351     (write-buffered *(ebp+0x10) "fn ")
    22352     8b/-> *(ebp+0xc) 0/r32/eax
    22353     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22354     (write-buffered *(ebp+0x10) %eax)
    22355     (write-buffered *(ebp+0x10) ": stmt 'copy-to' must have two inouts\n")
    22356     (flush *(ebp+0x10))
    22357     (stop *(ebp+0x14) 1)
    22358     # never gets here
    22359
    22360 $check-mu-copy-to-stmt:error-too-many-outputs:
    22361     (write-buffered *(ebp+0x10) "fn ")
    22362     8b/-> *(ebp+0xc) 0/r32/eax
    22363     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22364     (write-buffered *(ebp+0x10) %eax)
    22365     (write-buffered *(ebp+0x10) ": stmt 'copy-to' must not have any outputs\n")
    22366     (flush *(ebp+0x10))
    22367     (stop *(ebp+0x14) 1)
    22368     # never gets here
    22369
    22370 $check-mu-copy-to-stmt:error-src-not-literal-or-in-register:
    22371     (write-buffered *(ebp+0x10) "fn ")
    22372     8b/-> *(ebp+0xc) 0/r32/eax
    22373     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22374     (write-buffered *(ebp+0x10) %eax)
    22375     (write-buffered *(ebp+0x10) ": stmt copy-to: source (second inout) is in memory\n")
    22376     (flush *(ebp+0x10))
    22377     (stop *(ebp+0x14) 1)
    22378     # never gets here
    22379
    22380 $check-mu-copy-to-stmt:error-src-too-large:
    22381     (write-buffered *(ebp+0x10) "fn ")
    22382     8b/-> *(ebp+0xc) 0/r32/eax
    22383     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22384     (write-buffered *(ebp+0x10) %eax)
    22385     (write-buffered *(ebp+0x10) ": stmt copy-to: '")
    22386     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    22387     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    22388     (write-buffered *(ebp+0x10) %eax)
    22389     (write-buffered *(ebp+0x10) "' is too large to copy\n")
    22390     (flush *(ebp+0x10))
    22391     (stop *(ebp+0x14) 1)
    22392     # never gets here
    22393
    22394 $check-mu-copy-to-stmt:error-non-literal-to-byte:
    22395     (write-buffered *(ebp+0x10) "fn ")
    22396     8b/-> *(ebp+0xc) 0/r32/eax
    22397     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22398     (write-buffered *(ebp+0x10) %eax)
    22399     (write-buffered *(ebp+0x10) ": stmt copy-to: cannot copy non-literal to type byte; use copy-byte-to\n")
    22400     (flush *(ebp+0x10))
    22401     (stop *(ebp+0x14) 1)
    22402     # never gets here
    22403
    22404 check-mu-copy-byte-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    22405     # . prologue
    22406     55/push-ebp
    22407     89/<- %ebp 4/r32/esp
    22408     # . save registers
    22409     50/push-eax
    22410     51/push-ecx
    22411     52/push-edx
    22412     56/push-esi
    22413     57/push-edi
    22414     # var type-parameters/edx: (addr table (handle array byte) (addr type-tree) 8)
    22415     81 5/subop/subtract %esp 0x60/imm32
    22416     68/push 0x60/imm32/size
    22417     68/push 0/imm32/read
    22418     68/push 0/imm32/write
    22419     89/<- %edx 4/r32/esp
    22420 $check-mu-copy-byte-stmt:get-output:
    22421     # esi = stmt
    22422     8b/-> *(ebp+8) 6/r32/esi
    22423     # var output/edi: (addr stmt-var) = stmt->outputs
    22424     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    22425     89/<- %edi 0/r32/eax
    22426     # zero outputs
    22427     3d/compare-eax-and 0/imm32
    22428     0f 84/jump-if-= $check-mu-copy-byte-stmt:error-no-output/disp32
    22429     # > 1 output
    22430     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
    22431     3d/compare-eax-and 0/imm32
    22432     0f 85/jump-if-!= $check-mu-copy-byte-stmt:error-too-many-outputs/disp32
    22433 $check-mu-copy-byte-stmt:get-inout:
    22434     # var inout/esi: (addr stmt-var) = stmt->inouts
    22435     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    22436     89/<- %esi 0/r32/eax
    22437     # zero inouts
    22438     3d/compare-eax-and 0/imm32
    22439     0f 84/jump-if-= $check-mu-copy-byte-stmt:error-no-inout/disp32
    22440     # > 1 inout
    22441     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
    22442     3d/compare-eax-and 0/imm32
    22443     0f 85/jump-if-!= $check-mu-copy-byte-stmt:error-too-many-inouts/disp32
    22444 $check-mu-copy-byte-stmt:types:
    22445     # if inout is not a scalar, abort
    22446     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    22447     (size-of %eax)  # => eax
    22448     3d/compare-eax-and 4/imm32
    22449     0f 8f/jump-if-> $check-mu-copy-byte-stmt:error-inout-too-large/disp32
    22450     # var inout-type/ecx: (addr type-tree) = inout->value->type
    22451     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    22452     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    22453     89/<- %ecx 0/r32/eax
    22454 $check-mu-copy-byte-stmt:check-inout-deref:
    22455     # if (inout->is-deref?) inout-type = inout-type->payload
    22456     8b/-> *(esi+0x10) 0/r32/eax  # Stmt-var-is-deref
    22457     3d/compare-eax-and 0/imm32/false
    22458     {
    22459       74/jump-if-= break/disp8
    22460 $check-mu-copy-byte-stmt:inout-is-deref:
    22461       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
    22462       # if inout-type->right is null, t = inout-type->left
    22463       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
    22464       {
    22465         75/jump-if-!= break/disp8
    22466 $check-mu-copy-byte-stmt:inout-is-deref2:
    22467         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    22468       }
    22469       89/<- %ecx 0/r32/eax
    22470     }
    22471     # if output not in register, abort
    22472     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    22473     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    22474     3d/compare-eax-and 0/imm32
    22475     0f 84/jump-if-= $check-mu-copy-byte-stmt:error-output-not-in-register/disp32
    22476     # var output-type/eax: (addr type-tree) = output->value->type
    22477     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    22478     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    22479     # if output is not of type byte, abort
    22480     (simple-mu-type? %eax 8)  # byte => eax
    22481     3d/compare-eax-and 0/imm32
    22482     0f 84/jump-if-= $check-mu-copy-byte-stmt:error-invalid-output-type/disp32
    22483 $check-mu-copy-byte-stmt:end:
    22484     # . reclaim locals
    22485     81 0/subop/add %esp 0x6c/imm32
    22486     # . restore registers
    22487     5f/pop-to-edi
    22488     5e/pop-to-esi
    22489     5a/pop-to-edx
    22490     59/pop-to-ecx
    22491     58/pop-to-eax
    22492     # . epilogue
    22493     89/<- %esp 5/r32/ebp
    22494     5d/pop-to-ebp
    22495     c3/return
    22496
    22497 $check-mu-copy-byte-stmt:error-no-inout:
    22498     (write-buffered *(ebp+0x10) "fn ")
    22499     8b/-> *(ebp+0xc) 0/r32/eax
    22500     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22501     (write-buffered *(ebp+0x10) %eax)
    22502     (write-buffered *(ebp+0x10) ": stmt 'copy-byte' expects an inout\n")
    22503     (flush *(ebp+0x10))
    22504     (stop *(ebp+0x14) 1)
    22505     # never gets here
    22506
    22507 $check-mu-copy-byte-stmt:error-too-many-inouts:
    22508     (write-buffered *(ebp+0x10) "fn ")
    22509     8b/-> *(ebp+0xc) 0/r32/eax
    22510     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22511     (write-buffered *(ebp+0x10) %eax)
    22512     (write-buffered *(ebp+0x10) ": stmt 'copy-byte' must have just one inout\n")
    22513     (flush *(ebp+0x10))
    22514     (stop *(ebp+0x14) 1)
    22515     # never gets here
    22516
    22517 $check-mu-copy-byte-stmt:error-no-output:
    22518     (write-buffered *(ebp+0x10) "fn ")
    22519     8b/-> *(ebp+0xc) 0/r32/eax
    22520     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22521     (write-buffered *(ebp+0x10) %eax)
    22522     (write-buffered *(ebp+0x10) ": stmt 'copy-byte' expects an output\n")
    22523     (flush *(ebp+0x10))
    22524     (stop *(ebp+0x14) 1)
    22525     # never gets here
    22526
    22527 $check-mu-copy-byte-stmt:error-output-not-in-register:
    22528     (write-buffered *(ebp+0x10) "fn ")
    22529     8b/-> *(ebp+0xc) 0/r32/eax
    22530     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22531     (write-buffered *(ebp+0x10) %eax)
    22532     (write-buffered *(ebp+0x10) ": stmt copy-byte: output '")
    22533     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    22534     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    22535     (write-buffered *(ebp+0x10) %eax)
    22536     (write-buffered *(ebp+0x10) "' not in a register\n")
    22537     (flush *(ebp+0x10))
    22538     (stop *(ebp+0x14) 1)
    22539     # never gets here
    22540
    22541 $check-mu-copy-byte-stmt:error-too-many-outputs:
    22542     (write-buffered *(ebp+0x10) "fn ")
    22543     8b/-> *(ebp+0xc) 0/r32/eax
    22544     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22545     (write-buffered *(ebp+0x10) %eax)
    22546     (write-buffered *(ebp+0x10) ": stmt 'copy-byte' must have just one output\n")
    22547     (flush *(ebp+0x10))
    22548     (stop *(ebp+0x14) 1)
    22549     # never gets here
    22550
    22551 $check-mu-copy-byte-stmt:error-invalid-output-type:
    22552     (write-buffered *(ebp+0x10) "fn ")
    22553     8b/-> *(ebp+0xc) 0/r32/eax
    22554     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22555     (write-buffered *(ebp+0x10) %eax)
    22556     (write-buffered *(ebp+0x10) ": stmt 'copy-byte' must write to output of type byte\n")
    22557     (flush *(ebp+0x10))
    22558     (stop *(ebp+0x14) 1)
    22559     # never gets here
    22560
    22561 $check-mu-copy-byte-stmt:error-inout-too-large:
    22562     (write-buffered *(ebp+0x10) "fn ")
    22563     8b/-> *(ebp+0xc) 0/r32/eax
    22564     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22565     (write-buffered *(ebp+0x10) %eax)
    22566     (write-buffered *(ebp+0x10) ": stmt copy-byte: '")
    22567     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    22568     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    22569     (write-buffered *(ebp+0x10) %eax)
    22570     (write-buffered *(ebp+0x10) "' is too large to fit in a register\n")
    22571     (flush *(ebp+0x10))
    22572     (stop *(ebp+0x14) 1)
    22573     # never gets here
    22574
    22575 check-mu-copy-byte-to-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    22576     # . prologue
    22577     55/push-ebp
    22578     89/<- %ebp 4/r32/esp
    22579     # . save registers
    22580     50/push-eax
    22581     52/push-edx
    22582     53/push-ebx
    22583     56/push-esi
    22584     57/push-edi
    22585     # var type-parameters/edx: (addr table (handle array byte) (addr type-tree) 8)
    22586     81 5/subop/subtract %esp 0x60/imm32
    22587     68/push 0x60/imm32/size
    22588     68/push 0/imm32/read
    22589     68/push 0/imm32/write
    22590     89/<- %edx 4/r32/esp
    22591     # esi = stmt
    22592     8b/-> *(ebp+8) 6/r32/esi
    22593 $check-mu-copy-byte-to-stmt:check-for-output:
    22594     # if stmt->outputs abort
    22595     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    22596     3d/compare-eax-and 0/imm32
    22597     0f 85/jump-if-!= $check-mu-copy-byte-to-stmt:error-too-many-outputs/disp32
    22598 $check-mu-copy-byte-to-stmt:get-dest:
    22599     # var dest/edi: (addr stmt-var) = stmt->inouts
    22600     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    22601     89/<- %edi 0/r32/eax
    22602     # zero inouts
    22603     3d/compare-eax-and 0/imm32
    22604     0f 84/jump-if-= $check-mu-copy-byte-to-stmt:error-incorrect-inouts/disp32
    22605 $check-mu-copy-byte-to-stmt:get-src:
    22606     # var src/esi: (addr stmt-var) = dest->next
    22607     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
    22608     89/<- %esi 0/r32/eax
    22609     # 1 inout
    22610     3d/compare-eax-and 0/imm32
    22611     0f 84/jump-if-= $check-mu-copy-byte-to-stmt:error-incorrect-inouts/disp32
    22612     # > 2 inouts
    22613     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
    22614     3d/compare-eax-and 0/imm32
    22615     0f 85/jump-if-!= $check-mu-copy-byte-to-stmt:error-incorrect-inouts/disp32
    22616 $check-mu-copy-byte-to-stmt:types:
    22617     # if src is not a scalar, abort
    22618     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    22619     (size-of %eax)  # => eax
    22620     3d/compare-eax-and 4/imm32
    22621     0f 8f/jump-if-> $check-mu-copy-byte-to-stmt:error-src-too-large/disp32
    22622     # if src not in register, abort
    22623     {
    22624       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    22625       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    22626       3d/compare-eax-and 0/imm32
    22627       75/jump-if-!= break/disp8
    22628       e9/jump $check-mu-copy-byte-to-stmt:error-src-not-in-register/disp32
    22629     }
    22630     # var dest-type/ebx: (addr type-tree) = dest->value->type
    22631     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    22632     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    22633     89/<- %ebx 0/r32/eax
    22634     # if (dest->is-deref?) dest-type = dest-type->payload
    22635 $check-mu-copy-byte-to-stmt:check-dest-deref:
    22636     8b/-> *(edi+0x10) 0/r32/eax  # Stmt-var-is-deref
    22637     3d/compare-eax-and 0/imm32/false
    22638     {
    22639       74/jump-if-= break/disp8
    22640       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
    22641 $check-mu-copy-byte-to-stmt:dest-is-deref:
    22642       # if dest-type->right is null, dest-type = dest-type->left
    22643       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
    22644       {
    22645         75/jump-if-!= break/disp8
    22646 $check-mu-copy-byte-to-stmt:dest-is-deref2:
    22647         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    22648       }
    22649       89/<- %ebx 0/r32/eax
    22650     }
    22651     # if dest is not a byte, abort
    22652     (simple-mu-type? %ebx 8)  # byte => eax
    22653     3d/compare-eax-and 0/imm32/false
    22654     0f 84/jump-if-= $check-mu-copy-byte-to-stmt:error-invalid-dest-type/disp32
    22655 $check-mu-copy-byte-to-stmt:end:
    22656     # . reclaim locals
    22657     81 0/subop/add %esp 0x6c/imm32
    22658     # . restore registers
    22659     5f/pop-to-edi
    22660     5e/pop-to-esi
    22661     5b/pop-to-ebx
    22662     5a/pop-to-edx
    22663     58/pop-to-eax
    22664     # . epilogue
    22665     89/<- %esp 5/r32/ebp
    22666     5d/pop-to-ebp
    22667     c3/return
    22668
    22669 $check-mu-copy-byte-to-stmt:error-incorrect-inouts:
    22670     (write-buffered *(ebp+0x10) "fn ")
    22671     8b/-> *(ebp+0xc) 0/r32/eax
    22672     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22673     (write-buffered *(ebp+0x10) %eax)
    22674     (write-buffered *(ebp+0x10) ": stmt 'copy-byte-to' must have two inouts\n")
    22675     (flush *(ebp+0x10))
    22676     (stop *(ebp+0x14) 1)
    22677     # never gets here
    22678
    22679 $check-mu-copy-byte-to-stmt:error-too-many-outputs:
    22680     (write-buffered *(ebp+0x10) "fn ")
    22681     8b/-> *(ebp+0xc) 0/r32/eax
    22682     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22683     (write-buffered *(ebp+0x10) %eax)
    22684     (write-buffered *(ebp+0x10) ": stmt 'copy-byte-to' must not have any outputs\n")
    22685     (flush *(ebp+0x10))
    22686     (stop *(ebp+0x14) 1)
    22687     # never gets here
    22688
    22689 $check-mu-copy-byte-to-stmt:error-src-not-in-register:
    22690     (write-buffered *(ebp+0x10) "fn ")
    22691     8b/-> *(ebp+0xc) 0/r32/eax
    22692     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22693     (write-buffered *(ebp+0x10) %eax)
    22694     (write-buffered *(ebp+0x10) ": stmt copy-byte-to: source (second inout) must be in a register\n")
    22695     (flush *(ebp+0x10))
    22696     (stop *(ebp+0x14) 1)
    22697     # never gets here
    22698
    22699 $check-mu-copy-byte-to-stmt:error-invalid-dest-type:
    22700     (write-buffered *(ebp+0x10) "fn ")
    22701     8b/-> *(ebp+0xc) 0/r32/eax
    22702     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22703     (write-buffered *(ebp+0x10) %eax)
    22704     (write-buffered *(ebp+0x10) ": stmt copy-byte-to: '")
    22705     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    22706     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    22707     (write-buffered *(ebp+0x10) %eax)
    22708     (write-buffered *(ebp+0x10) "' must be a byte\n")
    22709     (flush *(ebp+0x10))
    22710     (stop *(ebp+0x14) 1)
    22711     # never gets here
    22712
    22713 $check-mu-copy-byte-to-stmt:error-src-too-large:
    22714     (write-buffered *(ebp+0x10) "fn ")
    22715     8b/-> *(ebp+0xc) 0/r32/eax
    22716     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22717     (write-buffered *(ebp+0x10) %eax)
    22718     (write-buffered *(ebp+0x10) ": stmt copy-byte-to: '")
    22719     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    22720     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    22721     (write-buffered *(ebp+0x10) %eax)
    22722     (write-buffered *(ebp+0x10) "' is too large to copy\n")
    22723     (flush *(ebp+0x10))
    22724     (stop *(ebp+0x14) 1)
    22725     # never gets here
    22726
    22727 check-mu-compare-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    22728     # . prologue
    22729     55/push-ebp
    22730     89/<- %ebp 4/r32/esp
    22731     # . save registers
    22732     50/push-eax
    22733     51/push-ecx
    22734     52/push-edx
    22735     53/push-ebx
    22736     56/push-esi
    22737     57/push-edi
    22738     # var type-parameters/edx: (addr table (handle array byte) (addr type-tree) 8)
    22739     81 5/subop/subtract %esp 0x60/imm32
    22740     68/push 0x60/imm32/size
    22741     68/push 0/imm32/read
    22742     68/push 0/imm32/write
    22743     89/<- %edx 4/r32/esp
    22744     # esi = stmt
    22745     8b/-> *(ebp+8) 6/r32/esi
    22746 $check-mu-compare-stmt:check-for-output:
    22747     # if stmt->outputs abort
    22748     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    22749     3d/compare-eax-and 0/imm32
    22750     0f 85/jump-if-!= $check-mu-compare-stmt:error-too-many-outputs/disp32
    22751 $check-mu-compare-stmt:get-left:
    22752     # var left/edi: (addr stmt-var) = stmt->inouts
    22753     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    22754     89/<- %edi 0/r32/eax
    22755     # zero inouts
    22756     3d/compare-eax-and 0/imm32
    22757     0f 84/jump-if-= $check-mu-compare-stmt:error-incorrect-inouts/disp32
    22758 $check-mu-compare-stmt:get-right:
    22759     # var right/esi: (addr stmt-var) = left->next
    22760     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
    22761     89/<- %esi 0/r32/eax
    22762     # 1 inout
    22763     3d/compare-eax-and 0/imm32
    22764     0f 84/jump-if-= $check-mu-compare-stmt:error-incorrect-inouts/disp32
    22765     # > 2 inouts
    22766     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
    22767     3d/compare-eax-and 0/imm32
    22768     0f 85/jump-if-!= $check-mu-compare-stmt:error-incorrect-inouts/disp32
    22769     # if both inouts are in memory, abort
    22770     {
    22771 $check-mu-compare-stmt:both-in-mem:
    22772       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    22773       (lookup *(eax+0x8) *(eax+0xc))  # Var-type Var-type => eax
    22774       (simple-mu-type? %eax 0)  # => eax
    22775       3d/compare-eax-and 0/imm32
    22776       0f 85/jump-if-!= break/disp32
    22777       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    22778       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    22779       3d/compare-eax-and 0/imm32
    22780       75/jump-if-!= break/disp8
    22781       (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    22782       (lookup *(eax+0x8) *(eax+0xc))  # Var-type Var-type => eax
    22783       (simple-mu-type? %eax 0)  # => eax
    22784       3d/compare-eax-and 0/imm32
    22785       75/jump-if-!= break/disp8
    22786       (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    22787       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    22788       3d/compare-eax-and 0/imm32
    22789       75/jump-if-!= break/disp8
    22790       e9/jump $check-mu-compare-stmt:error-both-in-memory/disp32
    22791     }
    22792 $check-mu-compare-stmt:types:
    22793     # var right-type/ecx: (addr type-tree) = right->value->type
    22794     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    22795     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    22796     89/<- %ecx 0/r32/eax
    22797     # if (right->is-deref?) right-type = right-type->payload
    22798     8b/-> *(esi+0x10) 0/r32/eax  # Stmt-var-is-deref
    22799     3d/compare-eax-and 0/imm32/false
    22800     {
    22801       74/jump-if-= break/disp8
    22802       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
    22803       # if right-type->right is null, right-type = right-type->left
    22804       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
    22805       {
    22806         75/jump-if-!= break/disp8
    22807         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    22808       }
    22809       89/<- %ecx 0/r32/eax
    22810     }
    22811     # if right-type is a literal string, abort
    22812     (simple-mu-type? %ecx 0x10)  # string-literal => eax
    22813     3d/compare-eax-and 0/imm32/false
    22814     0f 85/jump-if-!= $check-mu-compare-stmt:error-right-string-literal/disp32
    22815     # if right is not a scalar, abort
    22816     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    22817     (size-of %eax)  # => eax
    22818     3d/compare-eax-and 4/imm32
    22819     0f 8f/jump-if-> $check-mu-compare-stmt:error-right-too-large/disp32
    22820     # if left is not a scalar, abort
    22821     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    22822     (size-of %eax)  # => eax
    22823     3d/compare-eax-and 4/imm32
    22824     0f 8f/jump-if-> $check-mu-compare-stmt:error-left-too-large/disp32
    22825     # var left-type/ebx: (addr type-tree) = left->value->type
    22826     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    22827     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    22828     89/<- %ebx 0/r32/eax
    22829     # if (left->is-deref?) left-type = left-type->payload
    22830     8b/-> *(edi+0x10) 0/r32/eax  # Stmt-var-is-deref
    22831     3d/compare-eax-and 0/imm32/false
    22832     {
    22833       74/jump-if-= break/disp8
    22834       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
    22835       # if left-type->right is null, left-type = left-type->left
    22836       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
    22837       {
    22838         75/jump-if-!= break/disp8
    22839         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    22840       }
    22841       89/<- %ebx 0/r32/eax
    22842     }
    22843     # if (left-type == right-type) return
    22844     (type-match? %ebx %ecx %edx)  # => eax
    22845     3d/compare-eax-and 0/imm32
    22846     0f 85/jump-if-!= $check-mu-compare-stmt:end/disp32
    22847     # if left is an addr and right is 0, return
    22848     {
    22849       (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    22850       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    22851       (mu-addr-type? %eax)  # => eax
    22852       3d/compare-eax-and 0/imm32/false
    22853       74/jump-if-= break/disp8
    22854       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    22855       (lookup *eax *(eax+4))  # Var-name Var-name => eax
    22856       (string-equal? %eax "0")  # => eax
    22857       3d/compare-eax-and 0/imm32/false
    22858       74/jump-if-= break/disp8
    22859       eb/jump $check-mu-compare-stmt:end/disp8
    22860     }
    22861     # if left is not number-like, abort
    22862     (check-mu-numberlike-arg %edi *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    22863 $check-mu-compare-stmt:end:
    22864     # . reclaim locals
    22865     81 0/subop/add %esp 0x6c/imm32
    22866     # . restore registers
    22867     5f/pop-to-edi
    22868     5e/pop-to-esi
    22869     5b/pop-to-ebx
    22870     5a/pop-to-edx
    22871     59/pop-to-ecx
    22872     58/pop-to-eax
    22873     # . epilogue
    22874     89/<- %esp 5/r32/ebp
    22875     5d/pop-to-ebp
    22876     c3/return
    22877
    22878 $check-mu-compare-stmt:error-incorrect-inouts:
    22879     (write-buffered *(ebp+0x10) "fn ")
    22880     8b/-> *(ebp+0xc) 0/r32/eax
    22881     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22882     (write-buffered *(ebp+0x10) %eax)
    22883     (write-buffered *(ebp+0x10) ": stmt 'compare' must have two inouts\n")
    22884     (flush *(ebp+0x10))
    22885     (stop *(ebp+0x14) 1)
    22886     # never gets here
    22887
    22888 $check-mu-compare-stmt:error-too-many-outputs:
    22889     (write-buffered *(ebp+0x10) "fn ")
    22890     8b/-> *(ebp+0xc) 0/r32/eax
    22891     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22892     (write-buffered *(ebp+0x10) %eax)
    22893     (write-buffered *(ebp+0x10) ": stmt 'compare' must not have any outputs\n")
    22894     (flush *(ebp+0x10))
    22895     (stop *(ebp+0x14) 1)
    22896     # never gets here
    22897
    22898 $check-mu-compare-stmt:error-both-in-memory:
    22899     (write-buffered *(ebp+0x10) "fn ")
    22900     8b/-> *(ebp+0xc) 0/r32/eax
    22901     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22902     (write-buffered *(ebp+0x10) %eax)
    22903     (write-buffered *(ebp+0x10) ": stmt compare: both inouts are in memory\n")
    22904     (flush *(ebp+0x10))
    22905     (stop *(ebp+0x14) 1)
    22906     # never gets here
    22907
    22908 $check-mu-compare-stmt:error-left-too-large:
    22909     (write-buffered *(ebp+0x10) "fn ")
    22910     8b/-> *(ebp+0xc) 0/r32/eax
    22911     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22912     (write-buffered *(ebp+0x10) %eax)
    22913     (write-buffered *(ebp+0x10) ": stmt compare: '")
    22914     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    22915     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    22916     (write-buffered *(ebp+0x10) %eax)
    22917     (write-buffered *(ebp+0x10) "' is too large to compare\n")
    22918     (flush *(ebp+0x10))
    22919     (stop *(ebp+0x14) 1)
    22920     # never gets here
    22921
    22922 $check-mu-compare-stmt:error-right-too-large:
    22923     (write-buffered *(ebp+0x10) "fn ")
    22924     8b/-> *(ebp+0xc) 0/r32/eax
    22925     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22926     (write-buffered *(ebp+0x10) %eax)
    22927     (write-buffered *(ebp+0x10) ": stmt compare: '")
    22928     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    22929     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    22930     (write-buffered *(ebp+0x10) %eax)
    22931     (write-buffered *(ebp+0x10) "' is too large to compare\n")
    22932     (flush *(ebp+0x10))
    22933     (stop *(ebp+0x14) 1)
    22934     # never gets here
    22935
    22936 $check-mu-compare-stmt:error-right-string-literal:
    22937     (write-buffered *(ebp+0x10) "fn ")
    22938     8b/-> *(ebp+0xc) 0/r32/eax
    22939     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22940     (write-buffered *(ebp+0x10) %eax)
    22941     (write-buffered *(ebp+0x10) ": stmt compare: string literal ")
    22942     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    22943     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    22944     (write-buffered *(ebp+0x10) %eax)
    22945     (write-buffered *(ebp+0x10) " is not supported; use the string-equal? function\n")
    22946     (flush *(ebp+0x10))
    22947     (stop *(ebp+0x14) 1)
    22948     # never gets here
    22949
    22950 check-mu-address-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    22951     # . prologue
    22952     55/push-ebp
    22953     89/<- %ebp 4/r32/esp
    22954     # . save registers
    22955     50/push-eax
    22956     51/push-ecx
    22957     52/push-edx
    22958     56/push-esi
    22959     57/push-edi
    22960 $check-mu-address-stmt:get-output:
    22961     # esi = stmt
    22962     8b/-> *(ebp+8) 6/r32/esi
    22963     # var output/edi: (addr stmt-var) = stmt->outputs
    22964     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    22965     89/<- %edi 0/r32/eax
    22966     # zero outputs
    22967     3d/compare-eax-and 0/imm32
    22968     0f 84/jump-if-= $check-mu-address-stmt:error-no-output/disp32
    22969     # > 1 output
    22970     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
    22971     3d/compare-eax-and 0/imm32
    22972     0f 85/jump-if-!= $check-mu-address-stmt:error-too-many-outputs/disp32
    22973 $check-mu-address-stmt:get-inout:
    22974     # var inout/esi: (addr stmt-var) = stmt->inouts
    22975     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    22976     89/<- %esi 0/r32/eax
    22977     # zero inouts
    22978     3d/compare-eax-and 0/imm32
    22979     0f 84/jump-if-= $check-mu-address-stmt:error-no-inout/disp32
    22980     # > 1 inout
    22981     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
    22982     3d/compare-eax-and 0/imm32
    22983     0f 85/jump-if-!= $check-mu-address-stmt:error-too-many-inouts/disp32
    22984 $check-mu-address-stmt:types:
    22985     # if output not in register, abort
    22986     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    22987     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    22988     3d/compare-eax-and 0/imm32
    22989     0f 84/jump-if-= $check-mu-address-stmt:error-output-not-in-register/disp32
    22990     # var output-type/edx: (addr type-tree) = output->value->type
    22991     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    22992     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    22993     89/<- %edx 0/r32/eax
    22994     # if output-type not an addr, abort
    22995     (mu-addr-type? %edx)  # => eax
    22996     3d/compare-eax-and 0/imm32/false
    22997     0f 84/jump-if-= $check-mu-address-stmt:error-output-not-address/disp32
    22998     # output-type = output-type->right
    22999     (lookup *(edx+0xc) *(edx+0x10))  # Type-tree-right Type-tree-right => eax
    23000     # if output-type->right is null, output-type = output-type->left
    23001     81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
    23002     {
    23003       75/jump-if-!= break/disp8
    23004       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    23005     }
    23006     89/<- %edx 0/r32/eax
    23007     # var inout-type/ecx: (addr type-tree) = inout->value->type
    23008     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    23009     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    23010     89/<- %ecx 0/r32/eax
    23011     # if (inout->is-deref?) inout-type = inout-type->payload
    23012     8b/-> *(esi+0x10) 0/r32/eax  # Stmt-var-is-deref
    23013     3d/compare-eax-and 0/imm32/false
    23014     {
    23015       74/jump-if-= break/disp8
    23016       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
    23017       # if inout-type->right is null, t = inout-type->left
    23018       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
    23019       {
    23020         75/jump-if-!= break/disp8
    23021         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    23022       }
    23023       89/<- %ecx 0/r32/eax
    23024     }
    23025     # if (inout-type != output-type) abort
    23026     (type-equal-ignoring-capacity? %edx %ecx)  # => eax
    23027     3d/compare-eax-and 0/imm32
    23028     0f 84/jump-if-= $check-mu-address-stmt:error-type-mismatch/disp32
    23029 $check-mu-address-stmt:end:
    23030     # . restore registers
    23031     5f/pop-to-edi
    23032     5e/pop-to-esi
    23033     5a/pop-to-edx
    23034     59/pop-to-ecx
    23035     58/pop-to-eax
    23036     # . epilogue
    23037     89/<- %esp 5/r32/ebp
    23038     5d/pop-to-ebp
    23039     c3/return
    23040
    23041 $check-mu-address-stmt:error-no-inout:
    23042     (write-buffered *(ebp+0x10) "fn ")
    23043     8b/-> *(ebp+0xc) 0/r32/eax
    23044     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    23045     (write-buffered *(ebp+0x10) %eax)
    23046     (write-buffered *(ebp+0x10) ": stmt 'address' expects an inout\n")
    23047     (flush *(ebp+0x10))
    23048     (stop *(ebp+0x14) 1)
    23049     # never gets here
    23050
    23051 $check-mu-address-stmt:error-too-many-inouts:
    23052     (write-buffered *(ebp+0x10) "fn ")
    23053     8b/-> *(ebp+0xc) 0/r32/eax
    23054     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    23055     (write-buffered *(ebp+0x10) %eax)
    23056     (write-buffered *(ebp+0x10) ": stmt 'address' must have just one inout\n")
    23057     (flush *(ebp+0x10))
    23058     (stop *(ebp+0x14) 1)
    23059     # never gets here
    23060
    23061 $check-mu-address-stmt:error-no-output:
    23062     (write-buffered *(ebp+0x10) "fn ")
    23063     8b/-> *(ebp+0xc) 0/r32/eax
    23064     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    23065     (write-buffered *(ebp+0x10) %eax)
    23066     (write-buffered *(ebp+0x10) ": stmt 'address' expects an output\n")
    23067     (flush *(ebp+0x10))
    23068     (stop *(ebp+0x14) 1)
    23069     # never gets here
    23070
    23071 $check-mu-address-stmt:error-output-not-in-register:
    23072     (write-buffered *(ebp+0x10) "fn ")
    23073     8b/-> *(ebp+0xc) 0/r32/eax
    23074     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    23075     (write-buffered *(ebp+0x10) %eax)
    23076     (write-buffered *(ebp+0x10) ": stmt address: output '")
    23077     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    23078     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    23079     (write-buffered *(ebp+0x10) %eax)
    23080     (write-buffered *(ebp+0x10) "' not in a register\n")
    23081     (flush *(ebp+0x10))
    23082     (stop *(ebp+0x14) 1)
    23083     # never gets here
    23084
    23085 $check-mu-address-stmt:error-too-many-outputs:
    23086     (write-buffered *(ebp+0x10) "fn ")
    23087     8b/-> *(ebp+0xc) 0/r32/eax
    23088     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    23089     (write-buffered *(ebp+0x10) %eax)
    23090     (write-buffered *(ebp+0x10) ": stmt 'address' must have just one output\n")
    23091     (flush *(ebp+0x10))
    23092     (stop *(ebp+0x14) 1)
    23093     # never gets here
    23094
    23095 $check-mu-address-stmt:error-output-not-address:
    23096     (write-buffered *(ebp+0x10) "fn ")
    23097     8b/-> *(ebp+0xc) 0/r32/eax
    23098     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    23099     (write-buffered *(ebp+0x10) %eax)
    23100     (write-buffered *(ebp+0x10) ": stmt address: output '")
    23101     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    23102     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    23103     (write-buffered *(ebp+0x10) %eax)
    23104     (write-buffered *(ebp+0x10) "' is not an addr\n")
    23105     (flush *(ebp+0x10))
    23106     (stop *(ebp+0x14) 1)
    23107     # never gets here
    23108
    23109 $check-mu-address-stmt:error-type-mismatch:
    23110     (write-buffered *(ebp+0x10) "fn ")
    23111     8b/-> *(ebp+0xc) 0/r32/eax
    23112     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    23113     (write-buffered *(ebp+0x10) %eax)
    23114     (write-buffered *(ebp+0x10) ": stmt address: output '")
    23115     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    23116     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    23117     (write-buffered *(ebp+0x10) %eax)
    23118     (write-buffered *(ebp+0x10) "' cannot hold address of '")
    23119     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    23120     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    23121     (write-buffered *(ebp+0x10) %eax)
    23122     (write-buffered *(ebp+0x10) "'\n")
    23123     (flush *(ebp+0x10))
    23124     (stop *(ebp+0x14) 1)
    23125     # never gets here
    23126
    23127 type-equal-ignoring-capacity?:  # a: (addr type-tree), b: (addr type-tree) -> result/eax: boolean
    23128     # . prologue
    23129     55/push-ebp
    23130     89/<- %ebp 4/r32/esp
    23131     # . save registers
    23132     51/push-ecx
    23133     52/push-edx
    23134     53/push-ebx
    23135     # var curr-a/ecx: (addr type-tree) = a
    23136     8b/-> *(ebp+8) 1/r32/ecx
    23137     # var curr-b/ebx: (addr type-tree) = b
    23138     8b/-> *(ebp+0xc) 3/r32/ebx
    23139     # if (curr-a->is-atom?) fall back to regular equality
    23140     81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
    23141     0f 85/jump-if-!= $type-equal-ignoring-capacity?:base-case/disp32
    23142     # if (curr-a->left != curr-b->left) return false
    23143     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
    23144     89/<- %edx 0/r32/eax
    23145     (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
    23146     (type-equal? %edx %eax)  # => eax
    23147     3d/compare-eax-and 0/imm32/false
    23148     0f 84/jump-if-= $type-equal-ignoring-capacity?:end/disp32  # eax switches meaning
    23149     # if (curr-a->left == "array") curr-a = curr-a->element-type
    23150     {
    23151       (mu-array? %edx)  # => eax
    23152       3d/compare-eax-and 0/imm32/false
    23153       75/jump-if-!= break/disp8
    23154 $type-equal-ignoring-capacity?:array:
    23155       # curr-a = curr-a->right->left
    23156       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
    23157       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    23158       89/<- %ecx 0/r32/eax
    23159       # curr-b = curr-b->right->left
    23160       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
    23161       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    23162       89/<- %ebx 0/r32/eax
    23163       eb/jump $type-equal-ignoring-capacity?:base-case/disp8
    23164     }
    23165     # if (curr-a->left == "stream") curr-a = curr-a->element-type
    23166     {
    23167       (mu-stream? %edx)  # => eax
    23168       3d/compare-eax-and 0/imm32/false
    23169       75/jump-if-!= break/disp8
    23170 $type-equal-ignoring-capacity?:stream:
    23171       # curr-a = curr-a->right->left
    23172       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
    23173       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    23174       89/<- %ecx 0/r32/eax
    23175       # curr-b = curr-b->right->left
    23176       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
    23177       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    23178       89/<- %ebx 0/r32/eax
    23179       eb/jump $type-equal-ignoring-capacity?:base-case/disp8
    23180     }
    23181 $type-equal-ignoring-capacity?:base-case:
    23182     # return type-equal?(curr-a, curr-b)
    23183     (type-equal? %ecx %ebx)  # => eax
    23184 $type-equal-ignoring-capacity?:end:
    23185     # . restore registers
    23186     5b/pop-to-ebx
    23187     5a/pop-to-edx
    23188     59/pop-to-ecx
    23189     # . epilogue
    23190     89/<- %esp 5/r32/ebp
    23191     5d/pop-to-ebp
    23192     c3/return
    23193
    23194 check-mu-return-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    23195     # . prologue
    23196     55/push-ebp
    23197     89/<- %ebp 4/r32/esp
    23198     # . save registers
    23199     50/push-eax
    23200     51/push-ecx
    23201     52/push-edx
    23202     53/push-ebx
    23203     56/push-esi
    23204     57/push-edi
    23205     # var type-parameters/edx: (addr table (handle array byte) (addr type-tree) 8)
    23206     81 5/subop/subtract %esp 0x60/imm32
    23207     68/push 0x60/imm32/size
    23208     68/push 0/imm32/read
    23209     68/push 0/imm32/write
    23210     89/<- %edx 4/r32/esp
    23211     # var template/esi: (addr list var) = fn->outputs
    23212     8b/-> *(ebp+0xc) 0/r32/eax
    23213     (lookup *(eax+0x10) *(eax+0x14))  # Function-outputs Function-outputs => eax
    23214     89/<- %esi 0/r32/eax
    23215     # var curr-template/ebx: (addr list var) = fn->outputs
    23216     89/<- %ebx 0/r32/eax
    23217     # var curr/edi: (addr stmt-var) = stmt->inouts
    23218     8b/-> *(ebp+8) 0/r32/eax
    23219     (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    23220     89/<- %edi 0/r32/eax
    23221     {
    23222       # if template is null, break
    23223       81 7/subop/compare %ebx 0/imm32
    23224       0f 84/jump-if-= break/disp32
    23225       # if curr is null, abort
    23226       81 7/subop/compare %edi 0/imm32
    23227       0f 84/jump-if-= $check-mu-return-stmt:error-too-few-inouts/disp32
    23228       # var template-type/ecx: (addr type-tree) = template->value->type
    23229       (lookup *ebx *(ebx+4))  # List-value List-value => eax
    23230       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    23231       89/<- %ecx 0/r32/eax
    23232       # var curr-type/eax: (addr type-tree) = curr->value->type
    23233       (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    23234       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    23235       # if (curr->is-deref?) curr-type = payload of curr-type
    23236       81 7/subop/compare *(edi+0x10) 0/imm32/false  # Stmt-var-is-deref
    23237       {
    23238         74/jump-if-= break/disp8
    23239         (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
    23240         # if t->right is null, t = t->left
    23241         81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
    23242         75/jump-if-!= break/disp8
    23243         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    23244       }
    23245       # if curr-type is literal and template-type is float, abort
    23246       50/push-eax
    23247       {
    23248         (simple-mu-type? %eax 0)  # literal => eax
    23249         3d/compare-eax-and 0/imm32/false
    23250         74/jump-if-= break/disp8
    23251         (simple-mu-type? %ecx 0xf)  # float => eax
    23252         3d/compare-eax-and 0/imm32/false
    23253         0f 85/jump-if-!= $check-mu-return-stmt:error-literal-to-float/disp32
    23254       }
    23255       58/pop-to-eax
    23256       # if (curr-type != template-type) abort
    23257       (type-match? %ecx %eax %edx)  # => eax
    23258       3d/compare-eax-and 0/imm32/false
    23259       0f 84/jump-if-= $check-mu-return-stmt:error1/disp32
    23260       # if register-within-list-with-conflict?(curr, original template, curr-template, stmt) abort
    23261       (register-within-list-with-conflict? %edi %esi %ebx *(ebp+8))  # => eax
    23262       3d/compare-eax-and 0/imm32/false
    23263       0f 85/jump-if-!= $check-mu-return-stmt:error2/disp32
    23264       # template = template->next
    23265       (lookup *(ebx+8) *(ebx+0xc))  # List-next List-next => eax
    23266       89/<- %ebx 0/r32/eax
    23267       # curr = curr->next
    23268       (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
    23269       89/<- %edi 0/r32/eax
    23270       #
    23271       e9/jump loop/disp32
    23272     }
    23273     # if curr is not null, abort
    23274     81 7/subop/compare %edi 0/imm32
    23275     0f 85/jump-if-!= $check-mu-return-stmt:error-too-many-inouts/disp32
    23276 $check-mu-return-stmt:end:
    23277     # . reclaim locals
    23278     81 0/subop/add %esp 0x6c/imm32
    23279     # . restore registers
    23280     5f/pop-to-edi
    23281     5e/pop-to-esi
    23282     5b/pop-to-ebx
    23283     5a/pop-to-edx
    23284     59/pop-to-ecx
    23285     58/pop-to-eax
    23286     # . epilogue
    23287     89/<- %esp 5/r32/ebp
    23288     5d/pop-to-ebp
    23289     c3/return
    23290
    23291 $check-mu-return-stmt:error1:
    23292     (write-buffered *(ebp+0x10) "fn ")
    23293     8b/-> *(ebp+0xc) 0/r32/eax
    23294     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    23295     (write-buffered *(ebp+0x10) %eax)
    23296     (write-buffered *(ebp+0x10) ": return: '")
    23297     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    23298     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    23299     (write-buffered *(ebp+0x10) %eax)
    23300     (write-buffered *(ebp+0x10) "' has the wrong type\n")
    23301     (flush *(ebp+0x10))
    23302     (stop *(ebp+0x14) 1)
    23303     # never gets here
    23304
    23305 $check-mu-return-stmt:error2:
    23306     (write-buffered *(ebp+0x10) "fn ")
    23307     8b/-> *(ebp+0xc) 0/r32/eax
    23308     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    23309     (write-buffered *(ebp+0x10) %eax)
    23310     (write-buffered *(ebp+0x10) ": return: '")
    23311     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    23312     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    23313     (write-buffered *(ebp+0x10) %eax)
    23314     (write-buffered *(ebp+0x10) "' is no longer available\n")
    23315     (flush *(ebp+0x10))
    23316     (stop *(ebp+0x14) 1)
    23317     # never gets here
    23318
    23319 $check-mu-return-stmt:error-literal-to-float:
    23320     (write-buffered *(ebp+0x10) "fn ")
    23321     8b/-> *(ebp+0xc) 0/r32/eax
    23322     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    23323     (write-buffered *(ebp+0x10) %eax)
    23324     (write-buffered *(ebp+0x10) ": return: cannot copy literal '")
    23325     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    23326     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    23327     (write-buffered *(ebp+0x10) %eax)
    23328     (write-buffered *(ebp+0x10) "' to float\n")
    23329     (flush *(ebp+0x10))
    23330     (stop *(ebp+0x14) 1)
    23331     # never gets here
    23332
    23333 $check-mu-return-stmt:error-too-few-inouts:
    23334     (write-buffered *(ebp+0x10) "fn ")
    23335     8b/-> *(ebp+0xc) 0/r32/eax
    23336     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    23337     (write-buffered *(ebp+0x10) %eax)
    23338     (write-buffered *(ebp+0x10) ": return: too few inouts\n")
    23339     (flush *(ebp+0x10))
    23340     (stop *(ebp+0x14) 1)
    23341     # never gets here
    23342
    23343 $check-mu-return-stmt:error-too-many-inouts:
    23344     (write-buffered *(ebp+0x10) "fn ")
    23345     8b/-> *(ebp+0xc) 0/r32/eax
    23346     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    23347     (write-buffered *(ebp+0x10) %eax)
    23348     (write-buffered *(ebp+0x10) ": return: too many inouts\n")
    23349     (flush *(ebp+0x10))
    23350     (stop *(ebp+0x14) 1)
    23351     # never gets here
    23352
    23353 check-all-unique-registers:  # outputs: (addr list var), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    23354     # . prologue
    23355     55/push-ebp
    23356     89/<- %ebp 4/r32/esp
    23357     # . save registers
    23358     50/push-eax
    23359     51/push-ecx
    23360     56/push-esi
    23361     # var table/esi: (addr table (handle array byte) int 8)
    23362     81 5/subop/subtract %esp 0x60/imm32
    23363     68/push 0x60/imm32/size
    23364     68/push 0/imm32/read
    23365     68/push 0/imm32/write
    23366     89/<- %esi 4/r32/esp
    23367     # var curr/ecx: (addr list var) = outputs
    23368     8b/-> *(ebp+8) 1/r32/ecx
    23369     {
    23370       # if (curr == 0) break
    23371       81 7/subop/compare %ecx 0/imm32
    23372       0f 84/jump-if-= break/disp32
    23373       # var reg/eax: (addr array byte) = curr->value->register  # guaranteed to exist
    23374       (lookup *ecx *(ecx+4))  # List-value List-value => eax
    23375       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    23376       # if reg exists in table, abort
    23377       (maybe-get %esi %eax 0xc)  # => eax
    23378       3d/compare-eax-and 0/imm32
    23379       0f 85/jump-if-!= $check-all-unique-registers:abort/disp32
    23380       # insert reg in table
    23381       (lookup *ecx *(ecx+4))  # List-value List-value => eax
    23382       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    23383       (get-or-insert %esi %eax 0xc Heap)
    23384       # curr = curr->next
    23385       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
    23386       89/<- %ecx 0/r32/eax
    23387       e9/jump loop/disp32
    23388     }
    23389 $check-all-unique-registers:end:
    23390     # . reclaim locals
    23391     81 0/subop/add %esp 0x6c/imm32
    23392     # . restore registers
    23393     5e/pop-to-esi
    23394     59/pop-to-ecx
    23395     58/pop-to-eax
    23396     # . epilogue
    23397     89/<- %esp 5/r32/ebp
    23398     5d/pop-to-ebp
    23399     c3/return
    23400
    23401 $check-all-unique-registers:abort:
    23402     (write-buffered *(ebp+0x10) "fn ")
    23403     8b/-> *(ebp+0xc) 0/r32/eax
    23404     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    23405     (write-buffered *(ebp+0x10) %eax)
    23406     (write-buffered *(ebp+0x10) ": outputs must be in unique registers\n")
    23407     (flush *(ebp+0x10))
    23408     (stop *(ebp+0x14) 1)
    23409     # never gets here
    23410
    23411 # return false if s's register is not between start (inclusive) and end (exclusive)
    23412 # return false if the positionally corresponding register in stmt->inouts (where s comes from) is also s's register
    23413 # otherwise return true
    23414 register-within-list-with-conflict?:  # s: (addr stmt-var), start: (addr list var), end: (addr list var), stmt: (addr stmt) -> result/eax: boolean
    23415     # . prologue
    23416     55/push-ebp
    23417     89/<- %ebp 4/r32/esp
    23418     # . save registers
    23419     51/push-ecx
    23420     52/push-edx
    23421     53/push-ebx
    23422     56/push-esi
    23423     57/push-edi
    23424     # var target/ebx: (addr array byte) = s->value->register
    23425     8b/-> *(ebp+8) 0/r32/eax
    23426     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    23427     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    23428 #?     (write-buffered Stderr "AA: ")
    23429 #?     (write-buffered Stderr %eax)
    23430 #?     (write-buffered Stderr Newline)
    23431 #?     (flush Stderr)
    23432     # if (var->register == 0) return false
    23433     3d/compare-eax-and 0/imm32
    23434     0f 84/jump-if-= $register-within-list-with-conflict?:end/disp32  # eax turns into result
    23435     89/<- %ebx 0/r32/eax
    23436     # var curr/ecx: (addr list var) = start
    23437     8b/-> *(ebp+0xc) 1/r32/ecx
    23438     # edx = end
    23439     8b/-> *(ebp+0x10) 2/r32/edx
    23440     {
    23441       # if (curr == 0) break
    23442       81 7/subop/compare %edi 0/imm32
    23443       0f 84/jump-if-= break/disp32
    23444       # if (curr == end) break
    23445       39/compare %ecx 2/r32/edx
    23446       0f 84/jump-if-= break/disp32
    23447       # var curr-reg/eax: (addr array byte) = curr->value->register
    23448       (lookup *ecx *(ecx+4))  # List-value List-value => eax
    23449       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    23450       # if (curr-reg == 0) continue
    23451       3d/compare-eax-and 0/imm32
    23452       74/jump-if-= $register-within-list-with-conflict?:continue/disp8
    23453       # if (curr-reg == target) check for conflict
    23454       (string-equal? %eax %ebx)  # => eax
    23455       3d/compare-eax-and 0/imm32/false
    23456       {
    23457         74/jump-if-= break/disp8
    23458 #?         (write-buffered Stderr "conflict?\n")
    23459 #?         (flush Stderr)
    23460         # var return-inouts/eax: (addr stmt-var) = stmt->inouts
    23461         8b/-> *(ebp+0x14) 0/r32/eax
    23462         (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    23463         (register-conflict? %ebx %eax *(ebp+0xc))  # => eax
    23464         eb/jump $register-within-list-with-conflict?:end/disp8
    23465       }
    23466 $register-within-list-with-conflict?:continue:
    23467       # curr = curr->next
    23468       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
    23469       89/<- %ecx 0/r32/eax
    23470       e9/jump loop/disp32
    23471     }
    23472     # return false
    23473     b8/copy-to-eax 0/imm32/false
    23474 $register-within-list-with-conflict?:end:
    23475     # . restore registers
    23476     5f/pop-to-edi
    23477     5e/pop-to-esi
    23478     5b/pop-to-ebx
    23479     5a/pop-to-edx
    23480     59/pop-to-ecx
    23481     # . epilogue
    23482     89/<- %esp 5/r32/ebp
    23483     5d/pop-to-ebp
    23484     c3/return
    23485
    23486 # At the first occurrence of register 'reg' in fn-outputs,
    23487 # check if the corresponding element of return-inouts has a different register.
    23488 # This hacky helper is intended to be called in one specific place. Don't
    23489 # reuse it as is.
    23490 register-conflict?:  # reg: (addr array byte), return-inouts: (addr stmt-var), fn-outputs: (addr list var) => result/eax: boolean
    23491     # . prologue
    23492     55/push-ebp
    23493     89/<- %ebp 4/r32/esp
    23494     # . save registers
    23495     51/push-ecx
    23496     52/push-edx
    23497     53/push-ebx
    23498     56/push-esi
    23499     57/push-edi
    23500 #?     (write-buffered Stderr "BB: ")
    23501 #?     (write-buffered Stderr *(ebp+8))
    23502 #?     (write-buffered Stderr Newline)
    23503 #?     (flush Stderr)
    23504     # var curr-output/edi: (addr list var) = fn-outputs
    23505     8b/-> *(ebp+0x10) 7/r32/edi
    23506     # var curr-inout/esi: (addr stmt-var) = return-inouts
    23507     8b/-> *(ebp+0xc) 6/r32/esi
    23508     {
    23509       # if (curr-output == 0) abort
    23510       81 7/subop/compare %edi 0/imm32
    23511       0f 84/jump-if-= break/disp32
    23512       # if (curr-output->value->register != reg) continue
    23513       (lookup *edi *(edi+4))  # List-value List-value => eax
    23514       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    23515       (string-equal? %eax *(ebp+8))  # => eax
    23516       3d/compare-eax-and 0/imm32/false
    23517       0f 84/jump-if= $register-conflict?:continue/disp32
    23518 #?       (write-buffered Stderr "rescan\n")
    23519 #?       (flush Stderr)
    23520       # var curr-reg/eax: (addr array byte) = curr-inout->value->register
    23521       (lookup *esi *(esi+4))  # List-value List-value => eax
    23522       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    23523       # if (curr-reg == 0) return true
    23524       3d/compare-eax-and 0/imm32
    23525       {
    23526         75/jump-if-!= break/disp8
    23527 #?         (write-buffered Stderr "no register\n")
    23528 #?         (flush Stderr)
    23529         b8/copy-to-eax 1/imm32/true
    23530         e9/jump $register-conflict?:end/disp32
    23531       }
    23532       # return (curr-reg != reg)
    23533       (string-equal? %eax *(ebp+8))  # => eax
    23534       3d/compare-eax-and 0/imm32/false
    23535       0f 94/set-if-= %al
    23536 #?       (write-buffered Stderr "final: ")
    23537 #?       (write-int32-hex-buffered Stderr %eax)
    23538 #?       (write-buffered Stderr Newline)
    23539 #?       (flush Stderr)
    23540       eb/jump $register-conflict?:end/disp8
    23541 $register-conflict?:continue:
    23542       # curr-output = curr-output->next
    23543       (lookup *(edi+8) *(edi+0xc))  # List-next List-next => eax
    23544       89/<- %edi 0/r32/eax
    23545       # curr-inout = curr-inout->next
    23546       (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
    23547       89/<- %esi 0/r32/eax
    23548       e9/jump loop/disp32
    23549     }
    23550     # should never get here
    23551     (write-buffered Stderr "register-conflict? misused\n")
    23552     (flush Stderr)
    23553     e8/call syscall_exit/disp32
    23554 $register-conflict?:end:
    23555     # . restore registers
    23556     5f/pop-to-edi
    23557     5e/pop-to-esi
    23558     5b/pop-to-ebx
    23559     5a/pop-to-edx
    23560     59/pop-to-ecx
    23561     # . epilogue
    23562     89/<- %esp 5/r32/ebp
    23563     5d/pop-to-ebp
    23564     c3/return
    23565
    23566 check-final-stmt-is-return:  # block: (addr block), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    23567     # . prologue
    23568     55/push-ebp
    23569     89/<- %ebp 4/r32/esp
    23570     # . save registers
    23571     50/push-eax
    23572     51/push-ecx
    23573     # var curr/ecx: (addr list stmt) = block->stmts
    23574     8b/-> *(ebp+8) 0/r32/eax
    23575     (lookup *(eax+4) *(eax+8))  # Block-stmts Block-stmts => eax
    23576     3d/compare-eax-and 0/imm32
    23577     74/jump-if-= $check-final-stmt-is-return:error/disp8
    23578     89/<- %ecx 0/r32/eax
    23579     {
    23580       # if curr->next == 0, break
    23581       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
    23582       3d/compare-eax-and 0/imm32
    23583       74/jump-if-= break/disp8
    23584       # curr = curr->next
    23585       89/<- %ecx 0/r32/eax
    23586       e9/jump loop/disp32
    23587     }
    23588 $check-final-stmt-is-return:check-tag:
    23589     # if curr->value->tag != Stmt1, abort
    23590     (lookup *ecx *(ecx+4))  # List-value List-value => eax
    23591     81 7/subop/compare *eax 1/imm32/stmt1  # Stmt-tag
    23592     75/jump-if-!= $check-final-stmt-is-return:error/disp8
    23593 $check-final-stmt-is-return:check-operation:
    23594     # if curr->operation != "return", abort
    23595     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
    23596     (string-equal? %eax "return")
    23597     3d/compare-eax-and 0/imm32/false
    23598     74/jump-if-= $check-final-stmt-is-return:error/disp8
    23599 $check-final-stmt-is-return:end:
    23600     # . restore registers
    23601     59/pop-to-ecx
    23602     58/pop-to-eax
    23603     # . epilogue
    23604     89/<- %esp 5/r32/ebp
    23605     5d/pop-to-ebp
    23606     c3/return
    23607
    23608 $check-final-stmt-is-return:error:
    23609     (write-buffered *(ebp+0x10) "fn ")
    23610     8b/-> *(ebp+0xc) 0/r32/eax
    23611     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    23612     (write-buffered *(ebp+0x10) %eax)
    23613     (write-buffered *(ebp+0x10) ": final statement should be a 'return'\n")
    23614     (flush *(ebp+0x10))
    23615     (stop *(ebp+0x14) 1)
    23616     # never gets here
    23617
    23618 check-no-breaks:  # block: (addr block), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    23619     # . prologue
    23620     55/push-ebp
    23621     89/<- %ebp 4/r32/esp
    23622     # . save registers
    23623     50/push-eax
    23624     51/push-ecx
    23625     # var curr/ecx: (addr list stmt) = block->stmts
    23626     8b/-> *(ebp+8) 0/r32/eax
    23627     (lookup *(eax+4) *(eax+8))  # Block-stmts Block-stmts => eax
    23628     3d/compare-eax-and 0/imm32
    23629     0f 84/jump-if-= $check-no-breaks:end/disp32
    23630     89/<- %ecx 0/r32/eax
    23631     {
    23632       # if curr->next == 0, break
    23633       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
    23634       3d/compare-eax-and 0/imm32
    23635       74/jump-if-= break/disp8
    23636       # if curr->value->tag != Stmt1, continue
    23637       (lookup *ecx *(ecx+4))  # List-value List-value => eax
    23638       81 7/subop/compare *eax 1/imm32/stmt1  # Stmt-tag
    23639       75/jump-if-!= $check-no-breaks:continue/disp8
    23640       # if curr->value->operation starts with "break", abort
    23641       (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
    23642       (string-starts-with? %eax "break")  # => eax
    23643       3d/compare-eax-and 0/imm32/false
    23644       75/jump-if-!= $check-no-breaks:error/disp8
    23645 $check-no-breaks:continue:
    23646       # curr = curr->next
    23647       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
    23648       89/<- %ecx 0/r32/eax
    23649       e9/jump loop/disp32
    23650     }
    23651 $check-no-breaks:end:
    23652     # . restore registers
    23653     59/pop-to-ecx
    23654     58/pop-to-eax
    23655     # . epilogue
    23656     89/<- %esp 5/r32/ebp
    23657     5d/pop-to-ebp
    23658     c3/return
    23659
    23660 $check-no-breaks:error:
    23661     (write-buffered *(ebp+0x10) "fn ")
    23662     8b/-> *(ebp+0xc) 0/r32/eax
    23663     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    23664     (write-buffered *(ebp+0x10) %eax)
    23665     (write-buffered *(ebp+0x10) " has outputs, so you cannot 'break' out of the outermost block. Use 'return'.\n")
    23666     (flush *(ebp+0x10))
    23667     (stop *(ebp+0x14) 1)
    23668     # never gets here
    23669
    23670 check-mu-get-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    23671     # . prologue
    23672     55/push-ebp
    23673     89/<- %ebp 4/r32/esp
    23674     # . save registers
    23675     50/push-eax
    23676     51/push-ecx
    23677     52/push-edx
    23678     53/push-ebx
    23679     56/push-esi
    23680     57/push-edi
    23681     # esi = stmt
    23682     8b/-> *(ebp+8) 6/r32/esi
    23683     # - check for 0 inouts
    23684     # var base/ecx: (addr var) = stmt->inouts->value
    23685     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    23686     3d/compare-eax-and 0/imm32/false
    23687     0f 84/jump-if-= $check-mu-get-stmt:error-too-few-inouts/disp32
    23688     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    23689     89/<- %ecx 0/r32/eax
    23690 $check-mu-get-stmt:check-base:
    23691     # - check base type
    23692     # if it's an 'addr', check that it's in a register
    23693     # var base-type/ebx: (addr type-tree) = lookup(base->type)
    23694     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
    23695     89/<- %ebx 0/r32/eax
    23696     {
    23697       81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
    23698       0f 85/jump-if-!= break/disp32
    23699 $check-mu-get-stmt:base-is-compound:
    23700       # if (type->left != addr) break
    23701       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
    23702       (simple-mu-type? %eax 2)  # addr => eax
    23703       3d/compare-eax-and 0/imm32/false
    23704       74/jump-if-= break/disp8
    23705 $check-mu-get-stmt:base-is-addr:
    23706       # now check for register
    23707       81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
    23708       0f 84/jump-if-= $check-mu-get-stmt:error-base-type-addr-but-not-register/disp32
    23709 $check-mu-get-stmt:base-is-addr-in-register:
    23710       # type->left is now an addr; skip it
    23711       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
    23712       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
    23713       0f 85/jump-if-!= $check-mu-get-stmt:error-bad-base/disp32
    23714 $check-mu-get-stmt:base-is-addr-to-atom-in-register:
    23715       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    23716       89/<- %ebx 0/r32/eax
    23717     }
    23718 $check-mu-get-stmt:check-base-typeinfo:
    23719     # ensure type is a container
    23720     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
    23721     {
    23722       75/jump-if-!= break/disp8
    23723       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
    23724       89/<- %ebx 0/r32/eax
    23725     }
    23726     # var base-type-id/ebx: type-id = base-type->value
    23727     8b/-> *(ebx+4) 3/r32/ebx  # Type-tree-value
    23728     (container? %ebx)  # => eax
    23729     3d/compare-eax-and 0/imm32/false
    23730     0f 84/jump-if-= $check-mu-get-stmt:error-bad-base/disp32
    23731     # var base-typeinfo/edx: (addr typeinfo) = find-typeinfo(base-type-id)
    23732     # . var container/ecx: (handle typeinfo)
    23733     68/push 0/imm32
    23734     68/push 0/imm32
    23735     89/<- %ecx 4/r32/esp
    23736     # .
    23737     (find-typeinfo %ebx %ecx)
    23738     (lookup *ecx *(ecx+4))  # => eax
    23739     # . reclaim container
    23740     81 0/subop/add %esp 8/imm32
    23741     # .
    23742     89/<- %edx 0/r32/eax
    23743     # var offset/ecx: (addr stmt-var) = stmt->inouts->next
    23744     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    23745     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    23746     89/<- %ecx 0/r32/eax
    23747     # - check for 1 inout
    23748     3d/compare-eax-and 0/imm32/false
    23749     0f 84/jump-if-= $check-mu-get-stmt:error-too-few-inouts/disp32
    23750     # var offset/ecx: (addr var) = lookup(offset->value)
    23751     (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
    23752     89/<- %ecx 0/r32/eax
    23753     # - check for valid field
    23754     81 7/subop/compare *(ecx+0x14) -1/imm32/uninitialized  # Var-offset
    23755     0f 84/jump-if-= $check-mu-get-stmt:error-bad-field/disp32
    23756     # - check for too many inouts
    23757     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    23758     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    23759     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    23760     3d/compare-eax-and 0/imm32/false
    23761     0f 85/jump-if-!= $check-mu-get-stmt:error-too-many-inouts/disp32
    23762     # var output/edi: (addr var) = stmt->outputs->value
    23763     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    23764     # - check for 0 outputs
    23765     3d/compare-eax-and 0/imm32/false
    23766     0f 84/jump-if-= $check-mu-get-stmt:error-too-few-outputs/disp32
    23767     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    23768     89/<- %edi 0/r32/eax
    23769 $check-mu-get-stmt:check-output-type:
    23770     # - check output type
    23771     # must be in register
    23772     (lookup *(edi+0x18) *(edi+0x1c))  # Var-register Var-register => eax
    23773     3d/compare-eax-and 0/imm32
    23774     0f 84/jump-if-= $check-mu-get-stmt:error-output-not-in-register/disp32
    23775     # must have a non-atomic type
    23776     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
    23777     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
    23778     0f 85/jump-if-!= $check-mu-get-stmt:error-output-type-not-address/disp32
    23779     # type must start with (addr ...)
    23780     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    23781     (simple-mu-type? %eax 2)  # => eax
    23782     3d/compare-eax-and 0/imm32/false
    23783     0f 84/jump-if-= $check-mu-get-stmt:error-output-type-not-address/disp32
    23784 $check-mu-get-stmt:check-output-type-match:
    23785     # payload of addr type must match 'type' definition
    23786     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
    23787     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
    23788     # if (payload->right == null) payload = payload->left
    23789     81 7/subop/compare *(eax+0xc) 0/imm32/null  # Type-tree-right
    23790     {
    23791       75/jump-if-!= break/disp8
    23792       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    23793     }
    23794     89/<- %edi 0/r32/eax
    23795     # . var output-name/ecx: (addr array byte)
    23796     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    23797     89/<- %ecx 0/r32/eax
    23798     # . var base-typeinfo-entry/eax: (addr handle typeinfo-entry)
    23799     (lookup *(edx+4) *(edx+8))  # Typeinfo-fields Typeinfo-fields => eax
    23800     (get %eax %ecx 0x10)  # => eax
    23801     # .
    23802     (lookup *eax *(eax+4))  # => eax
    23803     (lookup *eax *(eax+4))  # Typeinfo-entry-input-var Typeinfo-entry-input-var => eax
    23804     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    23805     # .
    23806     (type-equal? %edi %eax)  # => eax
    23807     3d/compare-eax-and 0/imm32/false
    23808     0f 84/jump-if-= $check-mu-get-stmt:error-bad-output-type/disp32
    23809     # - check for too many outputs
    23810     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    23811     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    23812     3d/compare-eax-and 0/imm32/false
    23813     0f 85/jump-if-!= $check-mu-get-stmt:error-too-many-outputs/disp32
    23814 $check-mu-get-stmt:end:
    23815     # . restore registers
    23816     5f/pop-to-edi
    23817     5e/pop-to-esi
    23818     5b/pop-to-ebx
    23819     5a/pop-to-edx
    23820     59/pop-to-ecx
    23821     58/pop-to-eax
    23822     # . epilogue
    23823     89/<- %esp 5/r32/ebp
    23824     5d/pop-to-ebp
    23825     c3/return
    23826
    23827 $check-mu-get-stmt:error-too-few-inouts:
    23828     (write-buffered *(ebp+0x10) "fn ")
    23829     8b/-> *(ebp+0xc) 0/r32/eax
    23830     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    23831     (write-buffered *(ebp+0x10) %eax)
    23832     (write-buffered *(ebp+0x10) ": stmt get: too few inouts (2 required)\n")
    23833     (flush *(ebp+0x10))
    23834     (stop *(ebp+0x14) 1)
    23835     # never gets here
    23836
    23837 $check-mu-get-stmt:error-too-many-inouts:
    23838     (write-buffered *(ebp+0x10) "fn ")
    23839     8b/-> *(ebp+0xc) 0/r32/eax
    23840     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    23841     (write-buffered *(ebp+0x10) %eax)
    23842     (write-buffered *(ebp+0x10) ": stmt get: too many inouts (2 required)\n")
    23843     (flush *(ebp+0x10))
    23844     (stop *(ebp+0x14) 1)
    23845     # never gets here
    23846
    23847 $check-mu-get-stmt:error-too-few-outputs:
    23848     (write-buffered *(ebp+0x10) "fn ")
    23849     8b/-> *(ebp+0xc) 0/r32/eax
    23850     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    23851     (write-buffered *(ebp+0x10) %eax)
    23852     (write-buffered *(ebp+0x10) ": stmt get: must have an output\n")
    23853     (flush *(ebp+0x10))
    23854     (stop *(ebp+0x14) 1)
    23855     # never gets here
    23856
    23857 $check-mu-get-stmt:error-too-many-outputs:
    23858     (write-buffered *(ebp+0x10) "fn ")
    23859     8b/-> *(ebp+0xc) 0/r32/eax
    23860     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    23861     (write-buffered *(ebp+0x10) %eax)
    23862     (write-buffered *(ebp+0x10) ": stmt get: too many outputs (1 required)\n")
    23863     (flush *(ebp+0x10))
    23864     (stop *(ebp+0x14) 1)
    23865     # never gets here
    23866
    23867 $check-mu-get-stmt:error-bad-base:
    23868     # error("fn " fn ": stmt get: var '" base->name "' must have a 'type' definition\n")
    23869     (write-buffered *(ebp+0x10) "fn ")
    23870     8b/-> *(ebp+0xc) 0/r32/eax
    23871     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    23872     (write-buffered *(ebp+0x10) %eax)
    23873     (write-buffered *(ebp+0x10) ": stmt get: var '")
    23874     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    23875     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    23876     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    23877     (write-buffered *(ebp+0x10) %eax)
    23878     (write-buffered *(ebp+0x10) "' must have a 'type' definition\n")
    23879     (flush *(ebp+0x10))
    23880     (stop *(ebp+0x14) 1)
    23881     # never gets here
    23882
    23883 $check-mu-get-stmt:error-base-type-addr-but-not-register:
    23884     (write-buffered *(ebp+0x10) "fn ")
    23885     8b/-> *(ebp+0xc) 0/r32/eax
    23886     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    23887     (write-buffered *(ebp+0x10) %eax)
    23888     (write-buffered *(ebp+0x10) ": stmt get: var '")
    23889     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    23890     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    23891     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    23892     (write-buffered *(ebp+0x10) %eax)
    23893     (write-buffered *(ebp+0x10) "' is an 'addr' type, and so must live in a register\n")
    23894     (flush *(ebp+0x10))
    23895     (stop *(ebp+0x14) 1)
    23896     # never gets here
    23897
    23898 $check-mu-get-stmt:error-bad-field:
    23899     # error("fn " fn ": stmt get: type " type " has no member called '" curr->name "'\n")
    23900     (write-buffered *(ebp+0x10) "fn ")
    23901     8b/-> *(ebp+0xc) 0/r32/eax
    23902     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    23903     (write-buffered *(ebp+0x10) %eax)
    23904     (write-buffered *(ebp+0x10) ": stmt get: type '")
    23905     # . write(Type-id->data[tmp])
    23906     bf/copy-to-edi Type-id/imm32
    23907     8b/-> *(edi+ebx<<2+0xc) 6/r32/esi
    23908     {
    23909       81 7/subop/compare %esi 0/imm32
    23910       74/jump-if-= break/disp8
    23911       (write-buffered *(ebp+0x10) %esi)
    23912     }
    23913     # .
    23914     (write-buffered *(ebp+0x10) "' has no member called '")
    23915     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    23916     (write-buffered *(ebp+0x10) %eax)
    23917     (write-buffered *(ebp+0x10) "'\n")
    23918     (flush *(ebp+0x10))
    23919     (stop *(ebp+0x14) 1)
    23920     # never gets here
    23921
    23922 $check-mu-get-stmt:error-output-not-in-register:
    23923     (write-buffered *(ebp+0x10) "fn ")
    23924     8b/-> *(ebp+0xc) 0/r32/eax
    23925     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    23926     (write-buffered *(ebp+0x10) %eax)
    23927     (write-buffered *(ebp+0x10) ": stmt get: output '")
    23928     (lookup *edi *(edi+4))  # Var-name Var-name => eax
    23929     (write-buffered *(ebp+0x10) %eax)
    23930     (write-buffered *(ebp+0x10) "' is not in a register\n")
    23931     (flush *(ebp+0x10))
    23932     (stop *(ebp+0x14) 1)
    23933     # never gets here
    23934
    23935 $check-mu-get-stmt:error-output-type-not-address:
    23936     (write-buffered *(ebp+0x10) "fn ")
    23937     8b/-> *(ebp+0xc) 0/r32/eax
    23938     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    23939     (write-buffered *(ebp+0x10) %eax)
    23940     (write-buffered *(ebp+0x10) ": stmt get: output must be an addr\n")
    23941     (flush *(ebp+0x10))
    23942     (stop *(ebp+0x14) 1)
    23943     # never gets here
    23944
    23945 $check-mu-get-stmt:error-bad-output-type:
    23946     (write-buffered *(ebp+0x10) "fn ")
    23947     8b/-> *(ebp+0xc) 0/r32/eax
    23948     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    23949     (write-buffered *(ebp+0x10) %eax)
    23950     (write-buffered *(ebp+0x10) ": stmt get: wrong output type for member '")
    23951     (write-buffered *(ebp+0x10) %ecx)
    23952     (write-buffered *(ebp+0x10) "' of type '")
    23953     bf/copy-to-edi Type-id/imm32
    23954     8b/-> *(edi+ebx<<2+0xc) 6/r32/esi
    23955     {
    23956       81 7/subop/compare %esi 0/imm32
    23957       74/jump-if-= break/disp8
    23958       (write-buffered *(ebp+0x10) %esi)
    23959     }
    23960     (write-buffered *(ebp+0x10) "'\n")
    23961     (flush *(ebp+0x10))
    23962     (stop *(ebp+0x14) 1)
    23963     # never gets here
    23964
    23965 check-mu-index-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    23966     # . prologue
    23967     55/push-ebp
    23968     89/<- %ebp 4/r32/esp
    23969     # . save registers
    23970     50/push-eax
    23971     51/push-ecx
    23972     52/push-edx
    23973     53/push-ebx
    23974     56/push-esi
    23975     57/push-edi
    23976     # esi = stmt
    23977     8b/-> *(ebp+8) 6/r32/esi
    23978     # - check for 0 inouts
    23979     # var base/ecx: (addr var) = stmt->inouts->value
    23980     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    23981 $check-mu-index-stmt:check-no-inouts:
    23982     3d/compare-eax-and 0/imm32
    23983     0f 84/jump-if-= $check-mu-index-stmt:error-too-few-inouts/disp32
    23984     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    23985     89/<- %ecx 0/r32/eax
    23986     # - check base type is either (addr array ...) in register or (array ...) on stack
    23987     # var base-type/ebx: (addr type-tree) = lookup(base->type)
    23988     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
    23989     89/<- %ebx 0/r32/eax
    23990     # if base-type is an atom, abort with a precise error
    23991     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
    23992     {
    23993       74/jump-if-= break/disp8
    23994       (simple-mu-type? %ebx 3)  # array => eax
    23995       3d/compare-eax-and 0/imm32/false
    23996       0f 85/jump-if-!= $check-mu-index-stmt:error-base-array-atom-type/disp32
    23997       0f 84/jump-if-= $check-mu-index-stmt:error-base-non-array-type/disp32
    23998     }
    23999 $check-mu-index-stmt:base-is-compound:
    24000     # if type->left not addr or array, abort
    24001     {
    24002       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
    24003       (simple-mu-type? %eax 2)  # addr => eax
    24004       3d/compare-eax-and 0/imm32/false
    24005       75/jump-if-!= break/disp8
    24006       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
    24007       (simple-mu-type? %eax 3)  # array => eax
    24008       3d/compare-eax-and 0/imm32/false
    24009       75/jump-if-!= break/disp8
    24010       e9/jump $check-mu-index-stmt:error-base-non-array-type/disp32
    24011     }
    24012     # if (type->left == addr) ensure type->right->left == array and type->register exists
    24013     {
    24014       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
    24015       (simple-mu-type? %eax 2)  # addr => eax
    24016       3d/compare-eax-and 0/imm32/false
    24017       74/jump-if-= break/disp8
    24018 $check-mu-index-stmt:base-is-addr:
    24019       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
    24020       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    24021       (simple-mu-type? %eax 3)  # array => eax
    24022       3d/compare-eax-and 0/imm32/false
    24023       0f 84/jump-if-= $check-mu-index-stmt:error-base-non-array-type/disp32
    24024 $check-mu-index-stmt:check-base-addr-is-register:
    24025       81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
    24026       0f 84/jump-if-= $check-mu-index-stmt:error-base-address-array-type-on-stack/disp32
    24027     }
    24028     # if (type->left == array) ensure type->register doesn't exist
    24029     {
    24030       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
    24031       (simple-mu-type? %eax 3)  # array => eax
    24032       3d/compare-eax-and 0/imm32/false
    24033       74/jump-if-= break/disp8
    24034 $check-mu-index-stmt:base-is-array:
    24035       81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
    24036       0f 85/jump-if-!= $check-mu-index-stmt:error-base-array-type-in-register/disp32
    24037     }
    24038     # if (base-type->left == addr) base-type = base-type->right
    24039     {
    24040       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
    24041       (simple-mu-type? %eax 2)  # addr => eax
    24042       3d/compare-eax-and 0/imm32/false
    24043       74/jump-if-= break/disp8
    24044       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
    24045       89/<- %ebx 0/r32/eax
    24046     }
    24047     # - check for 1 inout
    24048     # var index/ecx: (addr stmt-var) = stmt->inouts->next->value
    24049     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    24050     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    24051 $check-mu-index-stmt:check-single-inout:
    24052     3d/compare-eax-and 0/imm32
    24053     0f 84/jump-if-= $check-mu-index-stmt:error-too-few-inouts/disp32
    24054     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    24055     89/<- %ecx 0/r32/eax
    24056     # - check index is either a literal or register
    24057     # var index-type/edx: (addr type-tree)
    24058     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
    24059     89/<- %edx 0/r32/eax
    24060     # if index type is an atom, it must be a literal or int
    24061     81 7/subop/compare *edx 0/imm32/false  # Type-tree-is-atom
    24062     {
    24063       74/jump-if-= break/disp8
    24064 $check-mu-index-stmt:index-type-is-atom:
    24065       (simple-mu-type? %edx 0)  # literal => eax
    24066       3d/compare-eax-and 0/imm32/false
    24067       75/jump-if-!= $check-mu-index-stmt:index-type-done/disp8
    24068       (simple-mu-type? %edx 1)  # int => eax
    24069       3d/compare-eax-and 0/imm32/false
    24070       75/jump-if-!= $check-mu-index-stmt:index-type-done/disp8
    24071       (simple-mu-type? %edx 7)  # offset => eax
    24072       3d/compare-eax-and 0/imm32/false
    24073       0f 85/jump-if-!= $check-mu-index-stmt:error-index-offset-atom-type/disp32
    24074       e9/jump $check-mu-index-stmt:error-invalid-index-type/disp32
    24075     }
    24076     # if index type is a non-atom: it must be an offset
    24077     {
    24078       75/jump-if-!= break/disp8
    24079 $check-mu-index-stmt:index-type-is-non-atom:
    24080       (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
    24081       (simple-mu-type? %eax 7)  # offset => eax
    24082       3d/compare-eax-and 0/imm32/false
    24083       0f 84/jump-if-= $check-mu-index-stmt:error-invalid-index-type/disp32
    24084     }
    24085 $check-mu-index-stmt:index-type-done:
    24086     # check index is either a literal or in a register
    24087     {
    24088       (simple-mu-type? %edx 0)  # literal => eax
    24089       3d/compare-eax-and 0/imm32/false
    24090       75/jump-if-!= break/disp8
    24091 $check-mu-index-stmt:check-index-in-register:
    24092       81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
    24093       0f 84/jump-if-= $check-mu-index-stmt:error-index-on-stack/disp32
    24094     }
    24095     # - if index is an 'int', check that element type of base has size 1, 2, 4 or 8 bytes.
    24096     {
    24097       (simple-mu-type? %edx 1)  # int => eax
    24098       3d/compare-eax-and 0/imm32/false
    24099       74/jump-if-= break/disp8
    24100 $check-mu-index-stmt:check-index-can-be-int:
    24101       (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    24102       (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    24103       (array-element-size %eax)  # => eax
    24104       3d/compare-eax-and 1/imm32
    24105       74/jump-if-= break/disp8
    24106       3d/compare-eax-and 2/imm32
    24107       74/jump-if-= break/disp8
    24108       3d/compare-eax-and 4/imm32
    24109       74/jump-if-= break/disp8
    24110       3d/compare-eax-and 8/imm32
    24111       74/jump-if-= break/disp8
    24112       e9/jump $check-mu-index-stmt:error-index-needs-offset/disp32
    24113     }
    24114     # - check for too many inouts
    24115     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    24116     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    24117     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    24118     3d/compare-eax-and 0/imm32/false
    24119     0f 85/jump-if-!= $check-mu-index-stmt:error-too-many-inouts/disp32
    24120     # - check for 0 outputs
    24121     # var output/edi: (addr var) = stmt->outputs->value
    24122     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    24123     3d/compare-eax-and 0/imm32/false
    24124     0f 84/jump-if-= $check-mu-index-stmt:error-too-few-outputs/disp32
    24125     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    24126     89/<- %edi 0/r32/eax
    24127     # - check output type
    24128     # must have a non-atomic type
    24129     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
    24130     89/<- %edx 0/r32/eax
    24131     81 7/subop/compare *edx 0/imm32/false  # Type-tree-is-atom
    24132     0f 85/jump-if-!= $check-mu-index-stmt:error-output-type-not-address/disp32
    24133     # type must start with (addr ...)
    24134     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
    24135     (simple-mu-type? %eax 2)  # addr => eax
    24136     3d/compare-eax-and 0/imm32/false
    24137     0f 84/jump-if-= $check-mu-index-stmt:error-output-type-not-address/disp32
    24138     # if tail(base-type) != tail(output-type) abort
    24139     (type-tail %ebx)  # => eax
    24140     89/<- %ebx 0/r32/eax
    24141     (type-tail %edx)  # => eax
    24142     (type-equal? %ebx %eax)  # => eax
    24143     3d/compare-eax-and 0/imm32/false
    24144     0f 84/jump-if-= $check-mu-index-stmt:error-bad-output-type/disp32
    24145     # - check for too many outputs
    24146     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    24147     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    24148     3d/compare-eax-and 0/imm32/false
    24149     0f 85/jump-if-!= $check-mu-index-stmt:error-too-many-outputs/disp32
    24150 $check-mu-index-stmt:end:
    24151     # . restore registers
    24152     5f/pop-to-edi
    24153     5e/pop-to-esi
    24154     5b/pop-to-ebx
    24155     5a/pop-to-edx
    24156     59/pop-to-ecx
    24157     58/pop-to-eax
    24158     # . epilogue
    24159     89/<- %esp 5/r32/ebp
    24160     5d/pop-to-ebp
    24161     c3/return
    24162
    24163 $check-mu-index-stmt:error-base-non-array-type:
    24164     (write-buffered *(ebp+0x10) "fn ")
    24165     8b/-> *(ebp+0xc) 0/r32/eax
    24166     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24167     (write-buffered *(ebp+0x10) %eax)
    24168     (write-buffered *(ebp+0x10) ": stmt index: var '")
    24169     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    24170     (write-buffered *(ebp+0x10) %eax)
    24171     (write-buffered *(ebp+0x10) "' is not an array\n")
    24172     (flush *(ebp+0x10))
    24173     (stop *(ebp+0x14) 1)
    24174     # never gets here
    24175
    24176 $check-mu-index-stmt:error-base-array-atom-type:
    24177     (write-buffered *(ebp+0x10) "fn ")
    24178     8b/-> *(ebp+0xc) 0/r32/eax
    24179     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24180     (write-buffered *(ebp+0x10) %eax)
    24181     (write-buffered *(ebp+0x10) ": stmt index: array '")
    24182     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    24183     (write-buffered *(ebp+0x10) %eax)
    24184     (write-buffered *(ebp+0x10) "' must specify the type of its elements\n")
    24185     (flush *(ebp+0x10))
    24186     (stop *(ebp+0x14) 1)
    24187     # never gets here
    24188
    24189 $check-mu-index-stmt:error-base-address-array-type-on-stack:
    24190     (write-buffered *(ebp+0x10) "fn ")
    24191     8b/-> *(ebp+0xc) 0/r32/eax
    24192     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24193     (write-buffered *(ebp+0x10) %eax)
    24194     (write-buffered *(ebp+0x10) ": stmt index: var '")
    24195     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    24196     (write-buffered *(ebp+0x10) %eax)
    24197     (write-buffered *(ebp+0x10) "' is an addr to an array, and so must live in a register\n")
    24198     (flush *(ebp+0x10))
    24199     (stop *(ebp+0x14) 1)
    24200     # never gets here
    24201
    24202 $check-mu-index-stmt:error-base-array-type-in-register:
    24203     (write-buffered *(ebp+0x10) "fn ")
    24204     8b/-> *(ebp+0xc) 0/r32/eax
    24205     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24206     (write-buffered *(ebp+0x10) %eax)
    24207     (write-buffered *(ebp+0x10) ": stmt index: var '")
    24208     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    24209     (write-buffered *(ebp+0x10) %eax)
    24210     (write-buffered *(ebp+0x10) "' is an array, and so must live on the stack\n")
    24211     (flush *(ebp+0x10))
    24212     (stop *(ebp+0x14) 1)
    24213     # never gets here
    24214
    24215 $check-mu-index-stmt:error-too-few-inouts:
    24216     (write-buffered *(ebp+0x10) "fn ")
    24217     8b/-> *(ebp+0xc) 0/r32/eax
    24218     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24219     (write-buffered *(ebp+0x10) %eax)
    24220     (write-buffered *(ebp+0x10) ": stmt index: too few inouts (2 required)\n")
    24221     (flush *(ebp+0x10))
    24222     (stop *(ebp+0x14) 1)
    24223     # never gets here
    24224
    24225 $check-mu-index-stmt:error-invalid-index-type:
    24226     (write-buffered *(ebp+0x10) "fn ")
    24227     8b/-> *(ebp+0xc) 0/r32/eax
    24228     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24229     (write-buffered *(ebp+0x10) %eax)
    24230     (write-buffered *(ebp+0x10) ": stmt index: second argument '")
    24231     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    24232     (write-buffered *(ebp+0x10) %eax)
    24233     (write-buffered *(ebp+0x10) "' must be an int or offset\n")
    24234     (flush *(ebp+0x10))
    24235     (stop *(ebp+0x14) 1)
    24236     # never gets here
    24237
    24238 $check-mu-index-stmt:error-index-offset-atom-type:
    24239     (write-buffered *(ebp+0x10) "fn ")
    24240     8b/-> *(ebp+0xc) 0/r32/eax
    24241     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24242     (write-buffered *(ebp+0x10) %eax)
    24243     (write-buffered *(ebp+0x10) ": stmt index: offset '")
    24244     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    24245     (write-buffered *(ebp+0x10) %eax)
    24246     (write-buffered *(ebp+0x10) "' must specify the type of array elements\n")
    24247     (flush *(ebp+0x10))
    24248     (stop *(ebp+0x14) 1)
    24249     # never gets here
    24250
    24251 $check-mu-index-stmt:error-index-on-stack:
    24252     (write-buffered *(ebp+0x10) "fn ")
    24253     8b/-> *(ebp+0xc) 0/r32/eax
    24254     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24255     (write-buffered *(ebp+0x10) %eax)
    24256     (write-buffered *(ebp+0x10) ": stmt index: second argument '")
    24257     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    24258     (write-buffered *(ebp+0x10) %eax)
    24259     (write-buffered *(ebp+0x10) "' must be in a register\n")
    24260     (flush *(ebp+0x10))
    24261     (stop *(ebp+0x14) 1)
    24262     # never gets here
    24263
    24264 $check-mu-index-stmt:error-index-needs-offset:
    24265     (write-buffered *(ebp+0x10) "fn ")
    24266     8b/-> *(ebp+0xc) 0/r32/eax
    24267     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24268     (write-buffered *(ebp+0x10) %eax)
    24269     (write-buffered *(ebp+0x10) ": stmt index: cannot take an int for array '")
    24270     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    24271     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    24272     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    24273     (write-buffered *(ebp+0x10) %eax)
    24274     (write-buffered *(ebp+0x10) "'; create an offset instead. See mu.md for details.\n")
    24275     (flush *(ebp+0x10))
    24276     (stop *(ebp+0x14) 1)
    24277     # never gets here
    24278
    24279 $check-mu-index-stmt:error-too-many-inouts:
    24280     (write-buffered *(ebp+0x10) "fn ")
    24281     8b/-> *(ebp+0xc) 0/r32/eax
    24282     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24283     (write-buffered *(ebp+0x10) %eax)
    24284     (write-buffered *(ebp+0x10) ": stmt index: too many inouts (2 required)\n")
    24285     (flush *(ebp+0x10))
    24286     (stop *(ebp+0x14) 1)
    24287     # never gets here
    24288
    24289 $check-mu-index-stmt:error-too-few-outputs:
    24290     (write-buffered *(ebp+0x10) "fn ")
    24291     8b/-> *(ebp+0xc) 0/r32/eax
    24292     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24293     (write-buffered *(ebp+0x10) %eax)
    24294     (write-buffered *(ebp+0x10) ": stmt index: must have an output\n")
    24295     (flush *(ebp+0x10))
    24296     (stop *(ebp+0x14) 1)
    24297     # never gets here
    24298
    24299 $check-mu-index-stmt:error-too-many-outputs:
    24300     (write-buffered *(ebp+0x10) "fn ")
    24301     8b/-> *(ebp+0xc) 0/r32/eax
    24302     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24303     (write-buffered *(ebp+0x10) %eax)
    24304     (write-buffered *(ebp+0x10) ": stmt index: too many outputs (1 required)\n")
    24305     (flush *(ebp+0x10))
    24306     (stop *(ebp+0x14) 1)
    24307     # never gets here
    24308
    24309 $check-mu-index-stmt:error-output-not-in-register:
    24310     (write-buffered *(ebp+0x10) "fn ")
    24311     8b/-> *(ebp+0xc) 0/r32/eax
    24312     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24313     (write-buffered *(ebp+0x10) %eax)
    24314     (write-buffered *(ebp+0x10) ": stmt index: output '")
    24315     (lookup *edi *(edi+4))  # Var-name Var-name => eax
    24316     (write-buffered *(ebp+0x10) %eax)
    24317     (write-buffered *(ebp+0x10) "' is not in a register\n")
    24318     (flush *(ebp+0x10))
    24319     (stop *(ebp+0x14) 1)
    24320     # never gets here
    24321
    24322 $check-mu-index-stmt:error-output-type-not-address:
    24323     (write-buffered *(ebp+0x10) "fn ")
    24324     8b/-> *(ebp+0xc) 0/r32/eax
    24325     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24326     (write-buffered *(ebp+0x10) %eax)
    24327     (write-buffered *(ebp+0x10) ": stmt index: output '")
    24328     (lookup *edi *(edi+4))  # Var-name Var-name => eax
    24329     (write-buffered *(ebp+0x10) %eax)
    24330     (write-buffered *(ebp+0x10) "' must be an addr\n")
    24331     (flush *(ebp+0x10))
    24332     (stop *(ebp+0x14) 1)
    24333     # never gets here
    24334
    24335 $check-mu-index-stmt:error-bad-output-type:
    24336     (write-buffered *(ebp+0x10) "fn ")
    24337     8b/-> *(ebp+0xc) 0/r32/eax
    24338     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24339     (write-buffered *(ebp+0x10) %eax)
    24340     (write-buffered *(ebp+0x10) ": stmt index: output '")
    24341     (lookup *edi *(edi+4))  # Var-name Var-name => eax
    24342     (write-buffered *(ebp+0x10) %eax)
    24343     (write-buffered *(ebp+0x10) "' does not have the right type\n")
    24344     (flush *(ebp+0x10))
    24345     (stop *(ebp+0x14) 1)
    24346     # never gets here
    24347
    24348 check-mu-length-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    24349     # . prologue
    24350     55/push-ebp
    24351     89/<- %ebp 4/r32/esp
    24352     # . save registers
    24353     50/push-eax
    24354     51/push-ecx
    24355     52/push-edx
    24356     53/push-ebx
    24357     56/push-esi
    24358     57/push-edi
    24359     # esi = stmt
    24360     8b/-> *(ebp+8) 6/r32/esi
    24361     # - check for 0 inouts
    24362     # var base/ecx: (addr var) = stmt->inouts->value
    24363     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    24364 $check-mu-length-stmt:check-no-inouts:
    24365     3d/compare-eax-and 0/imm32
    24366     0f 84/jump-if-= $check-mu-length-stmt:error-too-few-inouts/disp32
    24367     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    24368     89/<- %ecx 0/r32/eax
    24369     # - check base type is either (addr array ...) in register or (array ...) on stack
    24370     # var base-type/ebx: (addr type-tree) = lookup(base->type)
    24371     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
    24372     89/<- %ebx 0/r32/eax
    24373     # if base-type is an atom, abort with a precise error
    24374     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
    24375     {
    24376       74/jump-if-= break/disp8
    24377       (simple-mu-type? %ebx 3)  # array => eax
    24378       3d/compare-eax-and 0/imm32/false
    24379       0f 85/jump-if-!= $check-mu-length-stmt:error-base-array-atom-type/disp32
    24380       0f 84/jump-if-= $check-mu-length-stmt:error-base-non-array-type/disp32
    24381     }
    24382 $check-mu-length-stmt:base-is-compound:
    24383     # if type->left not addr or array, abort
    24384     {
    24385       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
    24386       (simple-mu-type? %eax 2)  # addr => eax
    24387       3d/compare-eax-and 0/imm32/false
    24388       75/jump-if-!= break/disp8
    24389       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
    24390       (simple-mu-type? %eax 3)  # array => eax
    24391       3d/compare-eax-and 0/imm32/false
    24392       75/jump-if-!= break/disp8
    24393       e9/jump $check-mu-length-stmt:error-base-non-array-type/disp32
    24394     }
    24395     # if (type->left == addr) ensure type->right->left == array and type->register exists
    24396     {
    24397       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
    24398       (simple-mu-type? %eax 2)  # addr => eax
    24399       3d/compare-eax-and 0/imm32/false
    24400       74/jump-if-= break/disp8
    24401 $check-mu-length-stmt:base-is-addr:
    24402       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
    24403       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    24404       (simple-mu-type? %eax 3)  # array => eax
    24405       3d/compare-eax-and 0/imm32/false
    24406       0f 84/jump-if-= $check-mu-length-stmt:error-base-non-array-type/disp32
    24407 $check-mu-length-stmt:check-base-addr-is-register:
    24408       81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
    24409       0f 84/jump-if-= $check-mu-length-stmt:error-base-address-array-type-on-stack/disp32
    24410     }
    24411     # if (type->left == array) ensure type->register doesn't exist
    24412     {
    24413       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
    24414       (simple-mu-type? %eax 3)  # array => eax
    24415       3d/compare-eax-and 0/imm32/false
    24416       74/jump-if-= break/disp8
    24417 $check-mu-length-stmt:base-is-array:
    24418       81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
    24419       0f 85/jump-if-!= $check-mu-length-stmt:error-base-array-type-in-register/disp32
    24420     }
    24421     # if (base-type->left == addr) base-type = base-type->right
    24422     {
    24423       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
    24424       (simple-mu-type? %eax 2)  # addr => eax
    24425       3d/compare-eax-and 0/imm32/false
    24426       74/jump-if-= break/disp8
    24427       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
    24428       89/<- %ebx 0/r32/eax
    24429     }
    24430     # - check for too many inouts
    24431     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    24432     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    24433     3d/compare-eax-and 0/imm32/false
    24434     0f 85/jump-if-!= $check-mu-length-stmt:error-too-many-inouts/disp32
    24435     # - check for 0 outputs
    24436     # var output/edi: (addr var) = stmt->outputs->value
    24437     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    24438     3d/compare-eax-and 0/imm32/false
    24439     0f 84/jump-if-= $check-mu-length-stmt:error-too-few-outputs/disp32
    24440     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    24441     89/<- %edi 0/r32/eax
    24442     # - check output type
    24443     # must have a non-atomic type
    24444     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
    24445     (simple-mu-type? %eax 1)  # int => eax
    24446     3d/compare-eax-and 0/imm32/false
    24447     0f 84/jump-if-= $check-mu-length-stmt:error-invalid-output-type/disp32
    24448     # - check for too many outputs
    24449     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    24450     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    24451     3d/compare-eax-and 0/imm32/false
    24452     0f 85/jump-if-!= $check-mu-length-stmt:error-too-many-outputs/disp32
    24453 $check-mu-length-stmt:end:
    24454     # . restore registers
    24455     5f/pop-to-edi
    24456     5e/pop-to-esi
    24457     5b/pop-to-ebx
    24458     5a/pop-to-edx
    24459     59/pop-to-ecx
    24460     58/pop-to-eax
    24461     # . epilogue
    24462     89/<- %esp 5/r32/ebp
    24463     5d/pop-to-ebp
    24464     c3/return
    24465
    24466 $check-mu-length-stmt:error-base-non-array-type:
    24467     (write-buffered *(ebp+0x10) "fn ")
    24468     8b/-> *(ebp+0xc) 0/r32/eax
    24469     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24470     (write-buffered *(ebp+0x10) %eax)
    24471     (write-buffered *(ebp+0x10) ": stmt length: var '")
    24472     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    24473     (write-buffered *(ebp+0x10) %eax)
    24474     (write-buffered *(ebp+0x10) "' is not an array\n")
    24475     (flush *(ebp+0x10))
    24476     (stop *(ebp+0x14) 1)
    24477     # never gets here
    24478
    24479 $check-mu-length-stmt:error-base-array-atom-type:
    24480     (write-buffered *(ebp+0x10) "fn ")
    24481     8b/-> *(ebp+0xc) 0/r32/eax
    24482     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24483     (write-buffered *(ebp+0x10) %eax)
    24484     (write-buffered *(ebp+0x10) ": stmt length: array '")
    24485     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    24486     (write-buffered *(ebp+0x10) %eax)
    24487     (write-buffered *(ebp+0x10) "' must specify the type of its elements\n")
    24488     (flush *(ebp+0x10))
    24489     (stop *(ebp+0x14) 1)
    24490     # never gets here
    24491
    24492 $check-mu-length-stmt:error-base-address-array-type-on-stack:
    24493     (write-buffered *(ebp+0x10) "fn ")
    24494     8b/-> *(ebp+0xc) 0/r32/eax
    24495     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24496     (write-buffered *(ebp+0x10) %eax)
    24497     (write-buffered *(ebp+0x10) ": stmt length: var '")
    24498     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    24499     (write-buffered *(ebp+0x10) %eax)
    24500     (write-buffered *(ebp+0x10) "' is an addr to an array, and so must live in a register\n")
    24501     (flush *(ebp+0x10))
    24502     (stop *(ebp+0x14) 1)
    24503     # never gets here
    24504
    24505 $check-mu-length-stmt:error-base-array-type-in-register:
    24506     (write-buffered *(ebp+0x10) "fn ")
    24507     8b/-> *(ebp+0xc) 0/r32/eax
    24508     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24509     (write-buffered *(ebp+0x10) %eax)
    24510     (write-buffered *(ebp+0x10) ": stmt length: var '")
    24511     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    24512     (write-buffered *(ebp+0x10) %eax)
    24513     (write-buffered *(ebp+0x10) "' is an array, and so must live on the stack\n")
    24514     (flush *(ebp+0x10))
    24515     (stop *(ebp+0x14) 1)
    24516     # never gets here
    24517
    24518 $check-mu-length-stmt:error-too-few-inouts:
    24519     (write-buffered *(ebp+0x10) "fn ")
    24520     8b/-> *(ebp+0xc) 0/r32/eax
    24521     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24522     (write-buffered *(ebp+0x10) %eax)
    24523     (write-buffered *(ebp+0x10) ": stmt length: too few inouts (1 required)\n")
    24524     (flush *(ebp+0x10))
    24525     (stop *(ebp+0x14) 1)
    24526     # never gets here
    24527
    24528 $check-mu-length-stmt:error-invalid-index-type:
    24529     (write-buffered *(ebp+0x10) "fn ")
    24530     8b/-> *(ebp+0xc) 0/r32/eax
    24531     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24532     (write-buffered *(ebp+0x10) %eax)
    24533     (write-buffered *(ebp+0x10) ": stmt length: second argument '")
    24534     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    24535     (write-buffered *(ebp+0x10) %eax)
    24536     (write-buffered *(ebp+0x10) "' must be an int or offset\n")
    24537     (flush *(ebp+0x10))
    24538     (stop *(ebp+0x14) 1)
    24539     # never gets here
    24540
    24541 $check-mu-length-stmt:error-index-offset-atom-type:
    24542     (write-buffered *(ebp+0x10) "fn ")
    24543     8b/-> *(ebp+0xc) 0/r32/eax
    24544     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24545     (write-buffered *(ebp+0x10) %eax)
    24546     (write-buffered *(ebp+0x10) ": stmt length: offset '")
    24547     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    24548     (write-buffered *(ebp+0x10) %eax)
    24549     (write-buffered *(ebp+0x10) "' must specify the type of array elements\n")
    24550     (flush *(ebp+0x10))
    24551     (stop *(ebp+0x14) 1)
    24552     # never gets here
    24553
    24554 $check-mu-length-stmt:error-index-on-stack:
    24555     (write-buffered *(ebp+0x10) "fn ")
    24556     8b/-> *(ebp+0xc) 0/r32/eax
    24557     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24558     (write-buffered *(ebp+0x10) %eax)
    24559     (write-buffered *(ebp+0x10) ": stmt length: second argument '")
    24560     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    24561     (write-buffered *(ebp+0x10) %eax)
    24562     (write-buffered *(ebp+0x10) "' must be in a register\n")
    24563     (flush *(ebp+0x10))
    24564     (stop *(ebp+0x14) 1)
    24565     # never gets here
    24566
    24567 $check-mu-length-stmt:error-index-needs-offset:
    24568     (write-buffered *(ebp+0x10) "fn ")
    24569     8b/-> *(ebp+0xc) 0/r32/eax
    24570     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24571     (write-buffered *(ebp+0x10) %eax)
    24572     (write-buffered *(ebp+0x10) ": stmt length: cannot take an int for array '")
    24573     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    24574     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    24575     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    24576     (write-buffered *(ebp+0x10) %eax)
    24577     (write-buffered *(ebp+0x10) "'; create an offset instead. See mu.md for details.\n")
    24578     (flush *(ebp+0x10))
    24579     (stop *(ebp+0x14) 1)
    24580     # never gets here
    24581
    24582 $check-mu-length-stmt:error-too-many-inouts:
    24583     (write-buffered *(ebp+0x10) "fn ")
    24584     8b/-> *(ebp+0xc) 0/r32/eax
    24585     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24586     (write-buffered *(ebp+0x10) %eax)
    24587     (write-buffered *(ebp+0x10) ": stmt length: too many inouts (1 required)\n")
    24588     (flush *(ebp+0x10))
    24589     (stop *(ebp+0x14) 1)
    24590     # never gets here
    24591
    24592 $check-mu-length-stmt:error-too-few-outputs:
    24593     (write-buffered *(ebp+0x10) "fn ")
    24594     8b/-> *(ebp+0xc) 0/r32/eax
    24595     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24596     (write-buffered *(ebp+0x10) %eax)
    24597     (write-buffered *(ebp+0x10) ": stmt length: must have an output\n")
    24598     (flush *(ebp+0x10))
    24599     (stop *(ebp+0x14) 1)
    24600     # never gets here
    24601
    24602 $check-mu-length-stmt:error-too-many-outputs:
    24603     (write-buffered *(ebp+0x10) "fn ")
    24604     8b/-> *(ebp+0xc) 0/r32/eax
    24605     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24606     (write-buffered *(ebp+0x10) %eax)
    24607     (write-buffered *(ebp+0x10) ": stmt length: too many outputs (1 required)\n")
    24608     (flush *(ebp+0x10))
    24609     (stop *(ebp+0x14) 1)
    24610     # never gets here
    24611
    24612 $check-mu-length-stmt:error-output-not-in-register:
    24613     (write-buffered *(ebp+0x10) "fn ")
    24614     8b/-> *(ebp+0xc) 0/r32/eax
    24615     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24616     (write-buffered *(ebp+0x10) %eax)
    24617     (write-buffered *(ebp+0x10) ": stmt length: output '")
    24618     (lookup *edi *(edi+4))  # Var-name Var-name => eax
    24619     (write-buffered *(ebp+0x10) %eax)
    24620     (write-buffered *(ebp+0x10) "' is not in a register\n")
    24621     (flush *(ebp+0x10))
    24622     (stop *(ebp+0x14) 1)
    24623     # never gets here
    24624
    24625 $check-mu-length-stmt:error-invalid-output-type:
    24626     (write-buffered *(ebp+0x10) "fn ")
    24627     8b/-> *(ebp+0xc) 0/r32/eax
    24628     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24629     (write-buffered *(ebp+0x10) %eax)
    24630     (write-buffered *(ebp+0x10) ": stmt length: output '")
    24631     (lookup *edi *(edi+4))  # Var-name Var-name => eax
    24632     (write-buffered *(ebp+0x10) %eax)
    24633     (write-buffered *(ebp+0x10) "' does not have the right type\n")
    24634     (flush *(ebp+0x10))
    24635     (stop *(ebp+0x14) 1)
    24636     # never gets here
    24637
    24638 check-mu-compute-offset-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    24639     # . prologue
    24640     55/push-ebp
    24641     89/<- %ebp 4/r32/esp
    24642     # . save registers
    24643     50/push-eax
    24644     51/push-ecx
    24645     52/push-edx
    24646     53/push-ebx
    24647     56/push-esi
    24648     57/push-edi
    24649     # esi = stmt
    24650     8b/-> *(ebp+8) 6/r32/esi
    24651     # - check for 0 inouts
    24652     # var base/ecx: (addr var) = stmt->inouts->value
    24653     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    24654 $check-mu-compute-offset-stmt:check-no-inouts:
    24655     3d/compare-eax-and 0/imm32
    24656     0f 84/jump-if-= $check-mu-compute-offset-stmt:error-too-few-inouts/disp32
    24657     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    24658     89/<- %ecx 0/r32/eax
    24659     # - check base type is either (addr array ...) in register or (array ...) on stack
    24660     # var base-type/ebx: (addr type-tree) = lookup(base->type)
    24661     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
    24662     89/<- %ebx 0/r32/eax
    24663     # if base-type is an atom, abort with a precise error
    24664     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
    24665     {
    24666       74/jump-if-= break/disp8
    24667       (simple-mu-type? %ebx 3)  # array => eax
    24668       3d/compare-eax-and 0/imm32/false
    24669       0f 85/jump-if-!= $check-mu-compute-offset-stmt:error-base-array-atom-type/disp32
    24670       0f 84/jump-if-= $check-mu-compute-offset-stmt:error-base-non-array-type/disp32
    24671     }
    24672 $check-mu-compute-offset-stmt:base-is-compound:
    24673     # if type->left not addr or array, abort
    24674     {
    24675       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
    24676       (simple-mu-type? %eax 2)  # addr => eax
    24677       3d/compare-eax-and 0/imm32/false
    24678       75/jump-if-!= break/disp8
    24679       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
    24680       (simple-mu-type? %eax 3)  # array => eax
    24681       3d/compare-eax-and 0/imm32/false
    24682       75/jump-if-!= break/disp8
    24683       e9/jump $check-mu-compute-offset-stmt:error-base-non-array-type/disp32
    24684     }
    24685     # if (type->left == addr) ensure type->right->left == array and type->register exists
    24686     {
    24687       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
    24688       (simple-mu-type? %eax 2)  # addr => eax
    24689       3d/compare-eax-and 0/imm32/false
    24690       74/jump-if-= break/disp8
    24691 $check-mu-compute-offset-stmt:base-is-addr:
    24692       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
    24693       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    24694       (simple-mu-type? %eax 3)  # array => eax
    24695       3d/compare-eax-and 0/imm32/false
    24696       0f 84/jump-if-= $check-mu-compute-offset-stmt:error-base-non-array-type/disp32
    24697     }
    24698     # if (base-type->left == addr) base-type = base-type->right
    24699     {
    24700       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
    24701       (simple-mu-type? %eax 2)  # addr => eax
    24702       3d/compare-eax-and 0/imm32/false
    24703       74/jump-if-= break/disp8
    24704       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
    24705       89/<- %ebx 0/r32/eax
    24706     }
    24707     # - check for 1 inout
    24708     # var index/ecx: (addr stmt-var) = stmt->inouts->next->value
    24709     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    24710     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    24711 $check-mu-compute-offset-stmt:check-single-inout:
    24712     3d/compare-eax-and 0/imm32
    24713     0f 84/jump-if-= $check-mu-compute-offset-stmt:error-too-few-inouts/disp32
    24714     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    24715     89/<- %ecx 0/r32/eax
    24716     # - check index is either a literal or register
    24717     # var index-type/edx: (addr type-tree)
    24718     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
    24719     89/<- %edx 0/r32/eax
    24720     # index type must be a literal or int
    24721     81 7/subop/compare *edx 0/imm32/false  # Type-tree-is-atom
    24722     0f 84/jump-if-= $check-mu-compute-offset-stmt:error-invalid-index-type/disp32
    24723     {
    24724 $check-mu-compute-offset-stmt:index-type-is-atom:
    24725       (simple-mu-type? %edx 0)  # literal => eax
    24726       3d/compare-eax-and 0/imm32/false
    24727       75/jump-if-!= break/disp8
    24728       (simple-mu-type? %edx 1)  # int => eax
    24729       3d/compare-eax-and 0/imm32/false
    24730       75/jump-if-!= break/disp8
    24731       e9/jump $check-mu-compute-offset-stmt:error-invalid-index-type/disp32
    24732     }
    24733     # - check for too many inouts
    24734     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    24735     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    24736     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    24737     3d/compare-eax-and 0/imm32/false
    24738     0f 85/jump-if-!= $check-mu-compute-offset-stmt:error-too-many-inouts/disp32
    24739     # - check for 0 outputs
    24740     # var output/edi: (addr var) = stmt->outputs->value
    24741     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    24742     3d/compare-eax-and 0/imm32/false
    24743     0f 84/jump-if-= $check-mu-compute-offset-stmt:error-too-few-outputs/disp32
    24744     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    24745     89/<- %edi 0/r32/eax
    24746     # - check output type
    24747     # must have a non-atomic type
    24748     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
    24749     89/<- %edx 0/r32/eax
    24750     81 7/subop/compare *edx 0/imm32/false  # Type-tree-is-atom
    24751     0f 85/jump-if-!= $check-mu-compute-offset-stmt:error-output-type-not-offset/disp32
    24752     # type must start with (offset ...)
    24753     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
    24754     (simple-mu-type? %eax 7)  # offset => eax
    24755     3d/compare-eax-and 0/imm32/false
    24756     0f 84/jump-if-= $check-mu-compute-offset-stmt:error-output-type-not-offset/disp32
    24757     # if tail(base-type) != tail(output-type) abort
    24758     (type-tail %ebx)  # => eax
    24759     89/<- %ebx 0/r32/eax
    24760     (type-tail %edx)  # => eax
    24761     (type-equal? %ebx %eax)  # => eax
    24762     3d/compare-eax-and 0/imm32/false
    24763     0f 84/jump-if-= $check-mu-compute-offset-stmt:error-bad-output-type/disp32
    24764     # - check for too many outputs
    24765     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    24766     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    24767     3d/compare-eax-and 0/imm32/false
    24768     0f 85/jump-if-!= $check-mu-compute-offset-stmt:error-too-many-outputs/disp32
    24769 $check-mu-compute-offset-stmt:end:
    24770     # . restore registers
    24771     5f/pop-to-edi
    24772     5e/pop-to-esi
    24773     5b/pop-to-ebx
    24774     5a/pop-to-edx
    24775     59/pop-to-ecx
    24776     58/pop-to-eax
    24777     # . epilogue
    24778     89/<- %esp 5/r32/ebp
    24779     5d/pop-to-ebp
    24780     c3/return
    24781
    24782 $check-mu-compute-offset-stmt:error-base-non-array-type:
    24783     (write-buffered *(ebp+0x10) "fn ")
    24784     8b/-> *(ebp+0xc) 0/r32/eax
    24785     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24786     (write-buffered *(ebp+0x10) %eax)
    24787     (write-buffered *(ebp+0x10) ": stmt compute-offset: var '")
    24788     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    24789     (write-buffered *(ebp+0x10) %eax)
    24790     (write-buffered *(ebp+0x10) "' is not an array\n")
    24791     (flush *(ebp+0x10))
    24792     (stop *(ebp+0x14) 1)
    24793     # never gets here
    24794
    24795 $check-mu-compute-offset-stmt:error-base-array-atom-type:
    24796     (write-buffered *(ebp+0x10) "fn ")
    24797     8b/-> *(ebp+0xc) 0/r32/eax
    24798     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24799     (write-buffered *(ebp+0x10) %eax)
    24800     (write-buffered *(ebp+0x10) ": stmt compute-offset: array '")
    24801     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    24802     (write-buffered *(ebp+0x10) %eax)
    24803     (write-buffered *(ebp+0x10) "' must specify the type of its elements\n")
    24804     (flush *(ebp+0x10))
    24805     (stop *(ebp+0x14) 1)
    24806     # never gets here
    24807
    24808 $check-mu-compute-offset-stmt:error-too-few-inouts:
    24809     (write-buffered *(ebp+0x10) "fn ")
    24810     8b/-> *(ebp+0xc) 0/r32/eax
    24811     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24812     (write-buffered *(ebp+0x10) %eax)
    24813     (write-buffered *(ebp+0x10) ": stmt compute-offset: too few inouts (2 required)\n")
    24814     (flush *(ebp+0x10))
    24815     (stop *(ebp+0x14) 1)
    24816     # never gets here
    24817
    24818 $check-mu-compute-offset-stmt:error-invalid-index-type:
    24819     (write-buffered *(ebp+0x10) "fn ")
    24820     8b/-> *(ebp+0xc) 0/r32/eax
    24821     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24822     (write-buffered *(ebp+0x10) %eax)
    24823     (write-buffered *(ebp+0x10) ": stmt compute-offset: second argument '")
    24824     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    24825     (write-buffered *(ebp+0x10) %eax)
    24826     (write-buffered *(ebp+0x10) "' must be an int\n")
    24827     (flush *(ebp+0x10))
    24828     (stop *(ebp+0x14) 1)
    24829     # never gets here
    24830
    24831 $check-mu-compute-offset-stmt:error-index-offset-atom-type:
    24832     (write-buffered *(ebp+0x10) "fn ")
    24833     8b/-> *(ebp+0xc) 0/r32/eax
    24834     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24835     (write-buffered *(ebp+0x10) %eax)
    24836     (write-buffered *(ebp+0x10) ": stmt compute-offset: offset '")
    24837     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    24838     (write-buffered *(ebp+0x10) %eax)
    24839     (write-buffered *(ebp+0x10) "' must specify the type of array elements\n")
    24840     (flush *(ebp+0x10))
    24841     (stop *(ebp+0x14) 1)
    24842     # never gets here
    24843
    24844 $check-mu-compute-offset-stmt:error-index-on-stack:
    24845     (write-buffered *(ebp+0x10) "fn ")
    24846     8b/-> *(ebp+0xc) 0/r32/eax
    24847     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24848     (write-buffered *(ebp+0x10) %eax)
    24849     (write-buffered *(ebp+0x10) ": stmt compute-offset: second argument '")
    24850     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    24851     (write-buffered *(ebp+0x10) %eax)
    24852     (write-buffered *(ebp+0x10) "' must be in a register\n")
    24853     (flush *(ebp+0x10))
    24854     (stop *(ebp+0x14) 1)
    24855     # never gets here
    24856
    24857 $check-mu-compute-offset-stmt:error-too-many-inouts:
    24858     (write-buffered *(ebp+0x10) "fn ")
    24859     8b/-> *(ebp+0xc) 0/r32/eax
    24860     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24861     (write-buffered *(ebp+0x10) %eax)
    24862     (write-buffered *(ebp+0x10) ": stmt compute-offset: too many inouts (2 required)\n")
    24863     (flush *(ebp+0x10))
    24864     (stop *(ebp+0x14) 1)
    24865     # never gets here
    24866
    24867 $check-mu-compute-offset-stmt:error-too-few-outputs:
    24868     (write-buffered *(ebp+0x10) "fn ")
    24869     8b/-> *(ebp+0xc) 0/r32/eax
    24870     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24871     (write-buffered *(ebp+0x10) %eax)
    24872     (write-buffered *(ebp+0x10) ": stmt compute-offset: must have an output\n")
    24873     (flush *(ebp+0x10))
    24874     (stop *(ebp+0x14) 1)
    24875     # never gets here
    24876
    24877 $check-mu-compute-offset-stmt:error-too-many-outputs:
    24878     (write-buffered *(ebp+0x10) "fn ")
    24879     8b/-> *(ebp+0xc) 0/r32/eax
    24880     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24881     (write-buffered *(ebp+0x10) %eax)
    24882     (write-buffered *(ebp+0x10) ": stmt compute-offset: too many outputs (1 required)\n")
    24883     (flush *(ebp+0x10))
    24884     (stop *(ebp+0x14) 1)
    24885     # never gets here
    24886
    24887 $check-mu-compute-offset-stmt:error-output-not-in-register:
    24888     (write-buffered *(ebp+0x10) "fn ")
    24889     8b/-> *(ebp+0xc) 0/r32/eax
    24890     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24891     (write-buffered *(ebp+0x10) %eax)
    24892     (write-buffered *(ebp+0x10) ": stmt compute-offset: output '")
    24893     (lookup *edi *(edi+4))  # Var-name Var-name => eax
    24894     (write-buffered *(ebp+0x10) %eax)
    24895     (write-buffered *(ebp+0x10) "' is not in a register\n")
    24896     (flush *(ebp+0x10))
    24897     (stop *(ebp+0x14) 1)
    24898     # never gets here
    24899
    24900 $check-mu-compute-offset-stmt:error-output-type-not-offset:
    24901     (write-buffered *(ebp+0x10) "fn ")
    24902     8b/-> *(ebp+0xc) 0/r32/eax
    24903     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24904     (write-buffered *(ebp+0x10) %eax)
    24905     (write-buffered *(ebp+0x10) ": stmt compute-offset: output '")
    24906     (lookup *edi *(edi+4))  # Var-name Var-name => eax
    24907     (write-buffered *(ebp+0x10) %eax)
    24908     (write-buffered *(ebp+0x10) "' must be an offset\n")
    24909     (flush *(ebp+0x10))
    24910     (stop *(ebp+0x14) 1)
    24911     # never gets here
    24912
    24913 $check-mu-compute-offset-stmt:error-bad-output-type:
    24914     (write-buffered *(ebp+0x10) "fn ")
    24915     8b/-> *(ebp+0xc) 0/r32/eax
    24916     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24917     (write-buffered *(ebp+0x10) %eax)
    24918     (write-buffered *(ebp+0x10) ": stmt compute-offset: output '")
    24919     (lookup *edi *(edi+4))  # Var-name Var-name => eax
    24920     (write-buffered *(ebp+0x10) %eax)
    24921     (write-buffered *(ebp+0x10) "' does not have the right type\n")
    24922     (flush *(ebp+0x10))
    24923     (stop *(ebp+0x14) 1)
    24924     # never gets here
    24925
    24926 check-mu-copy-object-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    24927     # . prologue
    24928     55/push-ebp
    24929     89/<- %ebp 4/r32/esp
    24930     # . save registers
    24931     50/push-eax
    24932     51/push-ecx
    24933     53/push-ebx
    24934     56/push-esi
    24935     57/push-edi
    24936     # esi = stmt
    24937     8b/-> *(ebp+8) 6/r32/esi
    24938 $check-mu-copy-object-stmt:check-for-output:
    24939     # if stmt->outputs abort
    24940     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    24941     3d/compare-eax-and 0/imm32
    24942     0f 85/jump-if-!= $check-mu-copy-object-stmt:error-too-many-outputs/disp32
    24943 $check-mu-copy-object-stmt:get-left:
    24944     # var dest/edi: (addr stmt-var) = stmt->inouts
    24945     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    24946     89/<- %edi 0/r32/eax
    24947     # zero inouts
    24948     3d/compare-eax-and 0/imm32
    24949     0f 84/jump-if-= $check-mu-copy-object-stmt:error-incorrect-inouts/disp32
    24950 $check-mu-copy-object-stmt:get-src:
    24951     # var src/esi: (addr stmt-var) = dest->next
    24952     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
    24953     89/<- %esi 0/r32/eax
    24954     # 1 inout
    24955     3d/compare-eax-and 0/imm32
    24956     0f 84/jump-if-= $check-mu-copy-object-stmt:error-incorrect-inouts/disp32
    24957     # > 2 inouts
    24958     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
    24959     3d/compare-eax-and 0/imm32
    24960     0f 85/jump-if-!= $check-mu-copy-object-stmt:error-incorrect-inouts/disp32
    24961 $check-mu-copy-object-stmt:types:
    24962     # var src-type/ecx: (addr type-tree) = src->value->type
    24963     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    24964     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    24965     89/<- %ecx 0/r32/eax
    24966     # if (src->is-deref?) src-type = src-type->payload
    24967     8b/-> *(esi+0x10) 0/r32/eax  # Stmt-var-is-deref
    24968     3d/compare-eax-and 0/imm32/false
    24969     {
    24970       74/jump-if-= break/disp8
    24971       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
    24972       # if src-type->right is null, src-type = src-type->left
    24973       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
    24974       {
    24975         75/jump-if-!= break/disp8
    24976         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    24977       }
    24978       89/<- %ecx 0/r32/eax
    24979     }
    24980     # if src-type is not addr, abort
    24981     (mu-addr-type? %ecx)  # => eax
    24982     3d/compare-eax-and 0/imm32/false
    24983     0f 84/jump-if-= $check-mu-copy-object-stmt:error-invalid-types/disp32
    24984     # var dest-type/ebx: (addr type-tree) = dest->value->type
    24985     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    24986     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    24987     89/<- %ebx 0/r32/eax
    24988     # if (dest->is-deref?) dest-type = dest-type->payload
    24989     8b/-> *(edi+0x10) 0/r32/eax  # Stmt-var-is-deref
    24990     3d/compare-eax-and 0/imm32/false
    24991     {
    24992       74/jump-if-= break/disp8
    24993       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
    24994       # if dest-type->right is null, dest-type = dest-type->left
    24995       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
    24996       {
    24997         75/jump-if-!= break/disp8
    24998         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    24999       }
    25000       89/<- %ebx 0/r32/eax
    25001     }
    25002     # if (dest-type != src-type) abort
    25003     (type-equal? %ecx %ebx)  # => eax
    25004     3d/compare-eax-and 0/imm32
    25005     0f 84/jump-if-= $check-mu-copy-object-stmt:error-invalid-types/disp32
    25006 $check-mu-copy-object-stmt:end:
    25007     # . restore registers
    25008     5f/pop-to-edi
    25009     5e/pop-to-esi
    25010     5b/pop-to-ebx
    25011     59/pop-to-ecx
    25012     58/pop-to-eax
    25013     # . epilogue
    25014     89/<- %esp 5/r32/ebp
    25015     5d/pop-to-ebp
    25016     c3/return
    25017
    25018 $check-mu-copy-object-stmt:error-incorrect-inouts:
    25019     (write-buffered *(ebp+0x10) "fn ")
    25020     8b/-> *(ebp+0xc) 0/r32/eax
    25021     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25022     (write-buffered *(ebp+0x10) %eax)
    25023     (write-buffered *(ebp+0x10) ": stmt 'copy-object' must have two inouts\n")
    25024     (flush *(ebp+0x10))
    25025     (stop *(ebp+0x14) 1)
    25026     # never gets here
    25027
    25028 $check-mu-copy-object-stmt:error-too-many-outputs:
    25029     (write-buffered *(ebp+0x10) "fn ")
    25030     8b/-> *(ebp+0xc) 0/r32/eax
    25031     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25032     (write-buffered *(ebp+0x10) %eax)
    25033     (write-buffered *(ebp+0x10) ": stmt 'copy-object' must not have any outputs\n")
    25034     (flush *(ebp+0x10))
    25035     (stop *(ebp+0x14) 1)
    25036     # never gets here
    25037
    25038 $check-mu-copy-object-stmt:error-invalid-types:
    25039     (write-buffered *(ebp+0x10) "fn ")
    25040     8b/-> *(ebp+0xc) 0/r32/eax
    25041     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25042     (write-buffered *(ebp+0x10) %eax)
    25043     (write-buffered *(ebp+0x10) ": stmt copy-object: two inouts with identical addr types expected\n")
    25044     (flush *(ebp+0x10))
    25045     (stop *(ebp+0x14) 1)
    25046     # never gets here
    25047
    25048 check-mu-clear-object-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    25049     # . prologue
    25050     55/push-ebp
    25051     89/<- %ebp 4/r32/esp
    25052     # . save registers
    25053     50/push-eax
    25054     51/push-ecx
    25055     53/push-ebx
    25056     56/push-esi
    25057     57/push-edi
    25058     # esi = stmt
    25059     8b/-> *(ebp+8) 6/r32/esi
    25060 $check-mu-clear-object-stmt:check-for-output:
    25061     # if stmt->outputs abort
    25062     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    25063     3d/compare-eax-and 0/imm32
    25064     0f 85/jump-if-!= $check-mu-clear-object-stmt:error-too-many-outputs/disp32
    25065 $check-mu-clear-object-stmt:get-left:
    25066     # var dest/edi: (addr stmt-var) = stmt->inouts
    25067     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    25068     89/<- %edi 0/r32/eax
    25069     # zero inouts
    25070     3d/compare-eax-and 0/imm32
    25071     0f 84/jump-if-= $check-mu-clear-object-stmt:error-incorrect-inouts/disp32
    25072 $check-mu-clear-object-stmt:get-src:
    25073     # > 1 inout
    25074     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
    25075     3d/compare-eax-and 0/imm32
    25076     0f 85/jump-if-!= $check-mu-clear-object-stmt:error-incorrect-inouts/disp32
    25077 $check-mu-clear-object-stmt:types:
    25078     # var src-type/ecx: (addr type-tree) = src->value->type
    25079     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    25080     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    25081     89/<- %ecx 0/r32/eax
    25082     # if (src->is-deref?) src-type = src-type->payload
    25083     8b/-> *(edi+0x10) 0/r32/eax  # Stmt-var-is-deref
    25084     3d/compare-eax-and 0/imm32/false
    25085     {
    25086       74/jump-if-= break/disp8
    25087       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
    25088       # if src-type->right is null, src-type = src-type->left
    25089       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
    25090       {
    25091         75/jump-if-!= break/disp8
    25092         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    25093       }
    25094       89/<- %ecx 0/r32/eax
    25095     }
    25096     # if src-type is not addr, abort
    25097     (mu-addr-type? %ecx)  # => eax
    25098     3d/compare-eax-and 0/imm32/false
    25099     0f 84/jump-if-= $check-mu-clear-object-stmt:error-invalid-type/disp32
    25100 $check-mu-clear-object-stmt:end:
    25101     # . restore registers
    25102     5f/pop-to-edi
    25103     5e/pop-to-esi
    25104     5b/pop-to-ebx
    25105     59/pop-to-ecx
    25106     58/pop-to-eax
    25107     # . epilogue
    25108     89/<- %esp 5/r32/ebp
    25109     5d/pop-to-ebp
    25110     c3/return
    25111
    25112 $check-mu-clear-object-stmt:error-incorrect-inouts:
    25113     (write-buffered *(ebp+0x10) "fn ")
    25114     8b/-> *(ebp+0xc) 0/r32/eax
    25115     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25116     (write-buffered *(ebp+0x10) %eax)
    25117     (write-buffered *(ebp+0x10) ": stmt 'clear-object' must have a single inout\n")
    25118     (flush *(ebp+0x10))
    25119     (stop *(ebp+0x14) 1)
    25120     # never gets here
    25121
    25122 $check-mu-clear-object-stmt:error-too-many-outputs:
    25123     (write-buffered *(ebp+0x10) "fn ")
    25124     8b/-> *(ebp+0xc) 0/r32/eax
    25125     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25126     (write-buffered *(ebp+0x10) %eax)
    25127     (write-buffered *(ebp+0x10) ": stmt 'clear-object' must not have any outputs\n")
    25128     (flush *(ebp+0x10))
    25129     (stop *(ebp+0x14) 1)
    25130     # never gets here
    25131
    25132 $check-mu-clear-object-stmt:error-invalid-type:
    25133     (write-buffered *(ebp+0x10) "fn ")
    25134     8b/-> *(ebp+0xc) 0/r32/eax
    25135     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25136     (write-buffered *(ebp+0x10) %eax)
    25137     (write-buffered *(ebp+0x10) ": stmt clear-object: inout must have an addr type\n")
    25138     (flush *(ebp+0x10))
    25139     (stop *(ebp+0x14) 1)
    25140     # never gets here
    25141
    25142 check-mu-allocate-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    25143     # . prologue
    25144     55/push-ebp
    25145     89/<- %ebp 4/r32/esp
    25146     # . save registers
    25147     50/push-eax
    25148     53/push-ebx
    25149     56/push-esi
    25150     57/push-edi
    25151     # esi = stmt
    25152     8b/-> *(ebp+8) 6/r32/esi
    25153 $check-mu-allocate-stmt:check-for-output:
    25154     # if stmt->outputs abort
    25155     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    25156     3d/compare-eax-and 0/imm32
    25157     0f 85/jump-if-!= $check-mu-allocate-stmt:error-too-many-outputs/disp32
    25158 $check-mu-allocate-stmt:get-target:
    25159     # var target/edi: (addr stmt-var) = stmt->inouts
    25160     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    25161     89/<- %edi 0/r32/eax
    25162     # zero inouts
    25163     3d/compare-eax-and 0/imm32
    25164     0f 84/jump-if-= $check-mu-allocate-stmt:error-incorrect-inouts/disp32
    25165     # > 1 inouts
    25166     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
    25167     3d/compare-eax-and 0/imm32
    25168     0f 85/jump-if-!= $check-mu-allocate-stmt:error-incorrect-inouts/disp32
    25169 $check-mu-allocate-stmt:check-type:
    25170     # var target-type/ebx: (addr type-tree) = target->value->type
    25171     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    25172     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    25173     89/<- %ebx 0/r32/eax
    25174     # if (target->is-deref?) target-type = target-type->payload
    25175     8b/-> *(edi+0x10) 0/r32/eax  # Stmt-var-is-deref
    25176     3d/compare-eax-and 0/imm32/false
    25177     {
    25178       74/jump-if-= break/disp8
    25179       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
    25180       # if target-type->right is null, target-type = target-type->left
    25181       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
    25182       {
    25183         75/jump-if-!= break/disp8
    25184         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    25185       }
    25186       89/<- %ebx 0/r32/eax
    25187     }
    25188     # if target-type is not addr, abort
    25189     (mu-addr-type? %ebx)  # => eax
    25190     3d/compare-eax-and 0/imm32/false
    25191     0f 84/jump-if-= $check-mu-allocate-stmt:error-invalid-type/disp32
    25192     # if target-type->right is an atom, abort
    25193     (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
    25194     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
    25195     0f 85/jump-if-!= $check-mu-allocate-stmt:error-invalid-type/disp32
    25196     # if target-type->right->left is not handle, abort
    25197     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    25198     (simple-mu-type? %eax 4)  # handle => eax
    25199     3d/compare-eax-and 0/imm32/false
    25200     0f 84/jump-if-= $check-mu-allocate-stmt:error-invalid-type/disp32
    25201 $check-mu-allocate-stmt:end:
    25202     # . restore registers
    25203     5f/pop-to-edi
    25204     5e/pop-to-esi
    25205     5b/pop-to-ebx
    25206     58/pop-to-eax
    25207     # . epilogue
    25208     89/<- %esp 5/r32/ebp
    25209     5d/pop-to-ebp
    25210     c3/return
    25211
    25212 $check-mu-allocate-stmt:error-incorrect-inouts:
    25213     (write-buffered *(ebp+0x10) "fn ")
    25214     8b/-> *(ebp+0xc) 0/r32/eax
    25215     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25216     (write-buffered *(ebp+0x10) %eax)
    25217     (write-buffered *(ebp+0x10) ": stmt 'allocate' must have a single inout\n")
    25218     (flush *(ebp+0x10))
    25219     (stop *(ebp+0x14) 1)
    25220     # never gets here
    25221
    25222 $check-mu-allocate-stmt:error-too-many-outputs:
    25223     (write-buffered *(ebp+0x10) "fn ")
    25224     8b/-> *(ebp+0xc) 0/r32/eax
    25225     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25226     (write-buffered *(ebp+0x10) %eax)
    25227     (write-buffered *(ebp+0x10) ": stmt 'allocate' must not have any outputs\n")
    25228     (flush *(ebp+0x10))
    25229     (stop *(ebp+0x14) 1)
    25230     # never gets here
    25231
    25232 $check-mu-allocate-stmt:error-invalid-type:
    25233     (write-buffered *(ebp+0x10) "fn ")
    25234     8b/-> *(ebp+0xc) 0/r32/eax
    25235     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25236     (write-buffered *(ebp+0x10) %eax)
    25237     (write-buffered *(ebp+0x10) ": stmt allocate: inout '")
    25238     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    25239     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    25240     (write-buffered *(ebp+0x10) %eax)
    25241     (write-buffered *(ebp+0x10) "' must have type (addr handle ...)\n")
    25242     (flush *(ebp+0x10))
    25243     (stop *(ebp+0x14) 1)
    25244     # never gets here
    25245
    25246 check-mu-populate-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    25247     # . prologue
    25248     55/push-ebp
    25249     89/<- %ebp 4/r32/esp
    25250     # . save registers
    25251     50/push-eax
    25252     53/push-ebx
    25253     56/push-esi
    25254     57/push-edi
    25255     # esi = stmt
    25256     8b/-> *(ebp+8) 6/r32/esi
    25257 $check-mu-populate-stmt:check-for-output:
    25258     # if stmt->outputs abort
    25259     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    25260     3d/compare-eax-and 0/imm32
    25261     0f 85/jump-if-!= $check-mu-populate-stmt:error-too-many-outputs/disp32
    25262 $check-mu-populate-stmt:get-target:
    25263     # var target/edi: (addr stmt-var) = stmt->inouts
    25264     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    25265     89/<- %edi 0/r32/eax
    25266     # zero inouts
    25267     3d/compare-eax-and 0/imm32
    25268     0f 84/jump-if-= $check-mu-populate-stmt:error-incorrect-inouts/disp32
    25269 $check-mu-populate-stmt:get-length:
    25270     # var length/esi: (addr stmt-var) = dest->next
    25271     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
    25272     89/<- %esi 0/r32/eax
    25273     # 1 inout
    25274     3d/compare-eax-and 0/imm32
    25275     0f 84/jump-if-= $check-mu-populate-stmt:error-incorrect-inouts/disp32
    25276     # > 2 inouts
    25277     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
    25278     3d/compare-eax-and 0/imm32
    25279     0f 85/jump-if-!= $check-mu-populate-stmt:error-incorrect-inouts/disp32
    25280 $check-mu-populate-stmt:check-target-type:
    25281     # var target-type/ebx: (addr type-tree) = target->value->type
    25282     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    25283     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    25284     89/<- %ebx 0/r32/eax
    25285 $check-mu-populate-stmt:check-target-type-deref:
    25286     # if (target->is-deref?) target-type = target-type->payload
    25287     8b/-> *(edi+0x10) 0/r32/eax  # Stmt-var-is-deref
    25288     3d/compare-eax-and 0/imm32/false
    25289     {
    25290       74/jump-if-= break/disp8
    25291       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
    25292       # if target-type->right is null, target-type = target-type->left
    25293       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
    25294       {
    25295         75/jump-if-!= break/disp8
    25296         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    25297       }
    25298       89/<- %ebx 0/r32/eax
    25299     }
    25300 $check-mu-populate-stmt:check-target-type-addr:
    25301     # if target-type is not addr, abort
    25302     (mu-addr-type? %ebx)  # => eax
    25303     3d/compare-eax-and 0/imm32/false
    25304     0f 84/jump-if-= $check-mu-populate-stmt:error-invalid-target-type/disp32
    25305     # if target-type->right is an atom, abort
    25306     (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
    25307     89/<- %ebx 0/r32/eax
    25308     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
    25309     0f 85/jump-if-!= $check-mu-populate-stmt:error-invalid-target-type/disp32
    25310 $check-mu-populate-stmt:check-target-type-handle:
    25311     # if target-type->right->left is not handle, abort
    25312     (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
    25313     (simple-mu-type? %eax 4)  # handle => eax
    25314     3d/compare-eax-and 0/imm32/false
    25315     0f 84/jump-if-= $check-mu-populate-stmt:error-invalid-target-type/disp32
    25316     # if target-type->right->right is an atom, abort
    25317     (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
    25318     89/<- %ebx 0/r32/eax
    25319     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
    25320     0f 85/jump-if-!= $check-mu-populate-stmt:error-invalid-target-type/disp32
    25321 $check-mu-populate-stmt:check-target-type-array:
    25322     # if target-type->right->right->left is not array, abort
    25323     (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
    25324     (simple-mu-type? %eax 3)  # array => eax
    25325     3d/compare-eax-and 0/imm32/false
    25326     0f 84/jump-if-= $check-mu-populate-stmt:error-invalid-target-type/disp32
    25327 $check-mu-populate-stmt:check-length-type:
    25328     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    25329     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    25330     89/<- %ebx 0/r32/eax
    25331     (simple-mu-type? %ebx 0)  # literal => eax
    25332     3d/compare-eax-and 0/imm32/false
    25333     75/jump-if-!= $check-mu-populate-stmt:end/disp8
    25334     (simple-mu-type? %ebx 1)  # int => eax
    25335     3d/compare-eax-and 0/imm32/false
    25336     0f 84/jump-if-= $check-mu-populate-stmt:error-invalid-length-type/disp32
    25337 $check-mu-populate-stmt:end:
    25338     # . restore registers
    25339     5f/pop-to-edi
    25340     5e/pop-to-esi
    25341     5b/pop-to-ebx
    25342     58/pop-to-eax
    25343     # . epilogue
    25344     89/<- %esp 5/r32/ebp
    25345     5d/pop-to-ebp
    25346     c3/return
    25347
    25348 $check-mu-populate-stmt:error-incorrect-inouts:
    25349     (write-buffered *(ebp+0x10) "fn ")
    25350     8b/-> *(ebp+0xc) 0/r32/eax
    25351     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25352     (write-buffered *(ebp+0x10) %eax)
    25353     (write-buffered *(ebp+0x10) ": stmt 'populate' must have two inouts\n")
    25354     (flush *(ebp+0x10))
    25355     (stop *(ebp+0x14) 1)
    25356     # never gets here
    25357
    25358 $check-mu-populate-stmt:error-too-many-outputs:
    25359     (write-buffered *(ebp+0x10) "fn ")
    25360     8b/-> *(ebp+0xc) 0/r32/eax
    25361     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25362     (write-buffered *(ebp+0x10) %eax)
    25363     (write-buffered *(ebp+0x10) ": stmt 'populate' must not have any outputs\n")
    25364     (flush *(ebp+0x10))
    25365     (stop *(ebp+0x14) 1)
    25366     # never gets here
    25367
    25368 $check-mu-populate-stmt:error-invalid-target-type:
    25369     (write-buffered *(ebp+0x10) "fn ")
    25370     8b/-> *(ebp+0xc) 0/r32/eax
    25371     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25372     (write-buffered *(ebp+0x10) %eax)
    25373     (write-buffered *(ebp+0x10) ": stmt populate: first inout '")
    25374     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    25375     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    25376     (write-buffered *(ebp+0x10) %eax)
    25377     (write-buffered *(ebp+0x10) "' must have type (addr handle array ...)\n")
    25378     (flush *(ebp+0x10))
    25379     (stop *(ebp+0x14) 1)
    25380     # never gets here
    25381
    25382 $check-mu-populate-stmt:error-invalid-length-type:
    25383     (write-buffered *(ebp+0x10) "fn ")
    25384     8b/-> *(ebp+0xc) 0/r32/eax
    25385     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25386     (write-buffered *(ebp+0x10) %eax)
    25387     (write-buffered *(ebp+0x10) ": stmt populate: second inout '")
    25388     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    25389     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    25390     (write-buffered *(ebp+0x10) %eax)
    25391     (write-buffered *(ebp+0x10) "' must be an int\n")
    25392     (flush *(ebp+0x10))
    25393     (stop *(ebp+0x14) 1)
    25394     # never gets here
    25395
    25396 check-mu-populate-stream-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    25397     # . prologue
    25398     55/push-ebp
    25399     89/<- %ebp 4/r32/esp
    25400     # . save registers
    25401     50/push-eax
    25402     53/push-ebx
    25403     56/push-esi
    25404     57/push-edi
    25405     # esi = stmt
    25406     8b/-> *(ebp+8) 6/r32/esi
    25407 $check-mu-populate-stream-stmt:check-for-output:
    25408     # if stmt->outputs abort
    25409     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    25410     3d/compare-eax-and 0/imm32
    25411     0f 85/jump-if-!= $check-mu-populate-stream-stmt:error-too-many-outputs/disp32
    25412 $check-mu-populate-stream-stmt:get-target:
    25413     # var target/edi: (addr stmt-var) = stmt->inouts
    25414     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    25415     89/<- %edi 0/r32/eax
    25416     # zero inouts
    25417     3d/compare-eax-and 0/imm32
    25418     0f 84/jump-if-= $check-mu-populate-stream-stmt:error-incorrect-inouts/disp32
    25419 $check-mu-populate-stream-stmt:get-length:
    25420     # var length/esi: (addr stmt-var) = dest->next
    25421     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
    25422     89/<- %esi 0/r32/eax
    25423     # 1 inout
    25424     3d/compare-eax-and 0/imm32
    25425     0f 84/jump-if-= $check-mu-populate-stream-stmt:error-incorrect-inouts/disp32
    25426     # > 2 inouts
    25427     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
    25428     3d/compare-eax-and 0/imm32
    25429     0f 85/jump-if-!= $check-mu-populate-stream-stmt:error-incorrect-inouts/disp32
    25430 $check-mu-populate-stream-stmt:check-target-type:
    25431     # var target-type/ebx: (addr type-tree) = target->value->type
    25432     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    25433     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    25434     89/<- %ebx 0/r32/eax
    25435 $check-mu-populate-stream-stmt:check-target-type-deref:
    25436     # if (target->is-deref?) target-type = target-type->payload
    25437     8b/-> *(edi+0x10) 0/r32/eax  # Stmt-var-is-deref
    25438     3d/compare-eax-and 0/imm32/false
    25439     {
    25440       74/jump-if-= break/disp8
    25441       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
    25442       # if target-type->right is null, target-type = target-type->left
    25443       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
    25444       {
    25445         75/jump-if-!= break/disp8
    25446         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    25447       }
    25448       89/<- %ebx 0/r32/eax
    25449     }
    25450 $check-mu-populate-stream-stmt:check-target-type-addr:
    25451     # if target-type is not addr, abort
    25452     (mu-addr-type? %ebx)  # => eax
    25453     3d/compare-eax-and 0/imm32/false
    25454     0f 84/jump-if-= $check-mu-populate-stream-stmt:error-invalid-target-type/disp32
    25455     # if target-type->right is an atom, abort
    25456     (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
    25457     89/<- %ebx 0/r32/eax
    25458     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
    25459     0f 85/jump-if-!= $check-mu-populate-stream-stmt:error-invalid-target-type/disp32
    25460 $check-mu-populate-stream-stmt:check-target-type-handle:
    25461     # if target-type->right->left is not handle, abort
    25462     (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
    25463     (simple-mu-type? %eax 4)  # handle => eax
    25464     3d/compare-eax-and 0/imm32/false
    25465     0f 84/jump-if-= $check-mu-populate-stream-stmt:error-invalid-target-type/disp32
    25466     # if target-type->right->right is an atom, abort
    25467     (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
    25468     89/<- %ebx 0/r32/eax
    25469     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
    25470     0f 85/jump-if-!= $check-mu-populate-stream-stmt:error-invalid-target-type/disp32
    25471 $check-mu-populate-stream-stmt:check-target-type-stream:
    25472     # if target-type->right->right->left is not stream, abort
    25473     (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
    25474     (simple-mu-type? %eax 0xb)  # stream => eax
    25475     3d/compare-eax-and 0/imm32/false
    25476     0f 84/jump-if-= $check-mu-populate-stream-stmt:error-invalid-target-type/disp32
    25477 $check-mu-populate-stream-stmt:check-length-type:
    25478     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    25479     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    25480     89/<- %ebx 0/r32/eax
    25481     (simple-mu-type? %ebx 0)  # literal => eax
    25482     3d/compare-eax-and 0/imm32/false
    25483     75/jump-if-!= $check-mu-populate-stream-stmt:end/disp8
    25484     (simple-mu-type? %ebx 1)  # int => eax
    25485     3d/compare-eax-and 0/imm32/false
    25486     0f 84/jump-if-= $check-mu-populate-stream-stmt:error-invalid-length-type/disp32
    25487 $check-mu-populate-stream-stmt:end:
    25488     # . restore registers
    25489     5f/pop-to-edi
    25490     5e/pop-to-esi
    25491     5b/pop-to-ebx
    25492     58/pop-to-eax
    25493     # . epilogue
    25494     89/<- %esp 5/r32/ebp
    25495     5d/pop-to-ebp
    25496     c3/return
    25497
    25498 $check-mu-populate-stream-stmt:error-incorrect-inouts:
    25499     (write-buffered *(ebp+0x10) "fn ")
    25500     8b/-> *(ebp+0xc) 0/r32/eax
    25501     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25502     (write-buffered *(ebp+0x10) %eax)
    25503     (write-buffered *(ebp+0x10) ": stmt 'populate-stream' must have two inouts\n")
    25504     (flush *(ebp+0x10))
    25505     (stop *(ebp+0x14) 1)
    25506     # never gets here
    25507
    25508 $check-mu-populate-stream-stmt:error-too-many-outputs:
    25509     (write-buffered *(ebp+0x10) "fn ")
    25510     8b/-> *(ebp+0xc) 0/r32/eax
    25511     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25512     (write-buffered *(ebp+0x10) %eax)
    25513     (write-buffered *(ebp+0x10) ": stmt 'populate-stream' must not have any outputs\n")
    25514     (flush *(ebp+0x10))
    25515     (stop *(ebp+0x14) 1)
    25516     # never gets here
    25517
    25518 $check-mu-populate-stream-stmt:error-invalid-target-type:
    25519     (write-buffered *(ebp+0x10) "fn ")
    25520     8b/-> *(ebp+0xc) 0/r32/eax
    25521     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25522     (write-buffered *(ebp+0x10) %eax)
    25523     (write-buffered *(ebp+0x10) ": stmt populate-stream: first inout '")
    25524     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    25525     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    25526     (write-buffered *(ebp+0x10) %eax)
    25527     (write-buffered *(ebp+0x10) "' must have type (addr handle stream ...)\n")
    25528     (flush *(ebp+0x10))
    25529     (stop *(ebp+0x14) 1)
    25530     # never gets here
    25531
    25532 $check-mu-populate-stream-stmt:error-invalid-length-type:
    25533     (write-buffered *(ebp+0x10) "fn ")
    25534     8b/-> *(ebp+0xc) 0/r32/eax
    25535     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25536     (write-buffered *(ebp+0x10) %eax)
    25537     (write-buffered *(ebp+0x10) ": stmt populate-stream: second inout '")
    25538     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    25539     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    25540     (write-buffered *(ebp+0x10) %eax)
    25541     (write-buffered *(ebp+0x10) "' must be an int\n")
    25542     (flush *(ebp+0x10))
    25543     (stop *(ebp+0x14) 1)
    25544     # never gets here
    25545
    25546 check-mu-read-from-stream-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    25547     # . prologue
    25548     55/push-ebp
    25549     89/<- %ebp 4/r32/esp
    25550     # . save registers
    25551     50/push-eax
    25552     51/push-ecx
    25553     52/push-edx
    25554     53/push-ebx
    25555     56/push-esi
    25556     57/push-edi
    25557     # esi = stmt
    25558     8b/-> *(ebp+8) 6/r32/esi
    25559     # - check for 0 inouts
    25560     # var base/ecx: (addr var) = stmt->inouts->value
    25561     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    25562 $check-mu-read-from-stream-stmt:check-no-inouts:
    25563     3d/compare-eax-and 0/imm32
    25564     0f 84/jump-if-= $check-mu-read-from-stream-stmt:error-too-few-inouts/disp32
    25565     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    25566     89/<- %ecx 0/r32/eax
    25567     # - check base type is (addr stream T)
    25568     # var base-type/ebx: (addr type-tree) = lookup(base->type)
    25569     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
    25570     89/<- %ebx 0/r32/eax
    25571 $check-mu-read-from-stream-stmt:check-base-is-compound:
    25572     # if base-type is an atom, abort
    25573     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
    25574     0f 85/jump-if-!= $check-mu-read-from-stream-stmt:error-invalid-base-type/disp32
    25575 $check-mu-read-from-stream-stmt:check-base-is-addr:
    25576     # if type->left not addr, abort
    25577     (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
    25578     (simple-mu-type? %eax 2)  # addr => eax
    25579     3d/compare-eax-and 0/imm32/false
    25580     0f 84/jump-if-= $check-mu-read-from-stream-stmt:error-invalid-base-type/disp32
    25581 $check-mu-read-from-stream-stmt:check-base-is-addr-to-stream:
    25582     # base-type = base-type->right
    25583     (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
    25584     89/<- %ebx 0/r32/eax
    25585     # ensure base-type->left == stream
    25586     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    25587     (simple-mu-type? %eax 0xb)  # stream => eax
    25588     3d/compare-eax-and 0/imm32/false
    25589     0f 84/jump-if-= $check-mu-read-from-stream-stmt:error-invalid-base-type/disp32
    25590     # - check target type is (addr T)
    25591     # var target/ecx: (addr stmt-var) = stmt->inouts->next->value
    25592     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    25593     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    25594 $check-mu-read-from-stream-stmt:check-single-inout:
    25595     3d/compare-eax-and 0/imm32
    25596     0f 84/jump-if-= $check-mu-read-from-stream-stmt:error-too-few-inouts/disp32
    25597     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    25598     89/<- %ecx 0/r32/eax
    25599     # var target-type/edx: (addr type-tree)
    25600     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
    25601     89/<- %edx 0/r32/eax
    25602     # if target-type is an atom, it must be a literal or int
    25603 $check-mu-read-from-stream-stmt:check-target-is-compound:
    25604     81 7/subop/compare *edx 0/imm32/false  # Type-tree-is-atom
    25605     0f 85/jump-if-!= $check-mu-read-from-stream-stmt:error-target-type-not-address/disp32
    25606 $check-mu-read-from-stream-stmt:check-target-type:
    25607     # target type must start with (addr ...)
    25608     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
    25609     (simple-mu-type? %eax 2)  # addr => eax
    25610     3d/compare-eax-and 0/imm32/false
    25611     0f 84/jump-if-= $check-mu-read-from-stream-stmt:error-target-type-not-address/disp32
    25612     # if tail(base-type) != tail(target-type) abort
    25613     (type-tail %ebx)  # => eax
    25614     89/<- %ebx 0/r32/eax
    25615     (type-tail %edx)  # => eax
    25616     (type-equal? %ebx %eax)  # => eax
    25617     3d/compare-eax-and 0/imm32/false
    25618     0f 84/jump-if-= $check-mu-read-from-stream-stmt:error-invalid-target-type/disp32
    25619 $check-mu-read-from-stream-stmt:check-too-many-inouts:
    25620     # - check for too many inouts
    25621     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    25622     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    25623     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    25624     3d/compare-eax-and 0/imm32/false
    25625     0f 85/jump-if-!= $check-mu-read-from-stream-stmt:error-too-many-inouts/disp32
    25626 $check-mu-read-from-stream-stmt:check-unexpected-output:
    25627     # - check for any output
    25628     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    25629     3d/compare-eax-and 0/imm32/false
    25630     0f 85/jump-if-!= $check-mu-read-from-stream-stmt:error-unexpected-output/disp32
    25631 $check-mu-read-from-stream-stmt:end:
    25632     # . restore registers
    25633     5f/pop-to-edi
    25634     5e/pop-to-esi
    25635     5b/pop-to-ebx
    25636     5a/pop-to-edx
    25637     59/pop-to-ecx
    25638     58/pop-to-eax
    25639     # . epilogue
    25640     89/<- %esp 5/r32/ebp
    25641     5d/pop-to-ebp
    25642     c3/return
    25643
    25644 $check-mu-read-from-stream-stmt:error-invalid-base-type:
    25645     (write-buffered *(ebp+0x10) "fn ")
    25646     8b/-> *(ebp+0xc) 0/r32/eax
    25647     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25648     (write-buffered *(ebp+0x10) %eax)
    25649     (write-buffered *(ebp+0x10) ": stmt read-from-stream: var '")
    25650     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    25651     (write-buffered *(ebp+0x10) %eax)
    25652     (write-buffered *(ebp+0x10) "' must be an addr to a stream\n")
    25653     (flush *(ebp+0x10))
    25654     (stop *(ebp+0x14) 1)
    25655     # never gets here
    25656
    25657 $check-mu-read-from-stream-stmt:error-too-few-inouts:
    25658     (write-buffered *(ebp+0x10) "fn ")
    25659     8b/-> *(ebp+0xc) 0/r32/eax
    25660     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25661     (write-buffered *(ebp+0x10) %eax)
    25662     (write-buffered *(ebp+0x10) ": stmt read-from-stream: too few inouts (2 required)\n")
    25663     (flush *(ebp+0x10))
    25664     (stop *(ebp+0x14) 1)
    25665     # never gets here
    25666
    25667 $check-mu-read-from-stream-stmt:error-target-type-not-address:
    25668     (write-buffered *(ebp+0x10) "fn ")
    25669     8b/-> *(ebp+0xc) 0/r32/eax
    25670     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25671     (write-buffered *(ebp+0x10) %eax)
    25672     (write-buffered *(ebp+0x10) ": stmt read-from-stream: target '")
    25673     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    25674     (write-buffered *(ebp+0x10) %eax)
    25675     (write-buffered *(ebp+0x10) "' must be an addr\n")
    25676     (flush *(ebp+0x10))
    25677     (stop *(ebp+0x14) 1)
    25678     # never gets here
    25679
    25680 $check-mu-read-from-stream-stmt:error-invalid-target-type:
    25681     (write-buffered *(ebp+0x10) "fn ")
    25682     8b/-> *(ebp+0xc) 0/r32/eax
    25683     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25684     (write-buffered *(ebp+0x10) %eax)
    25685     (write-buffered *(ebp+0x10) ": stmt read-from-stream: second inout '")
    25686     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    25687     (write-buffered *(ebp+0x10) %eax)
    25688     (write-buffered *(ebp+0x10) "' does not have the right type\n")
    25689     (flush *(ebp+0x10))
    25690     (stop *(ebp+0x14) 1)
    25691     # never gets here
    25692
    25693 $check-mu-read-from-stream-stmt:error-too-many-inouts:
    25694     (write-buffered *(ebp+0x10) "fn ")
    25695     8b/-> *(ebp+0xc) 0/r32/eax
    25696     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25697     (write-buffered *(ebp+0x10) %eax)
    25698     (write-buffered *(ebp+0x10) ": stmt read-from-stream: too many inouts (2 required)\n")
    25699     (flush *(ebp+0x10))
    25700     (stop *(ebp+0x14) 1)
    25701     # never gets here
    25702
    25703 $check-mu-read-from-stream-stmt:error-unexpected-output:
    25704     (write-buffered *(ebp+0x10) "fn ")
    25705     8b/-> *(ebp+0xc) 0/r32/eax
    25706     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25707     (write-buffered *(ebp+0x10) %eax)
    25708     (write-buffered *(ebp+0x10) ": stmt read-from-stream: unexpected output\n")
    25709     (flush *(ebp+0x10))
    25710     (stop *(ebp+0x14) 1)
    25711     # never gets here
    25712
    25713 check-mu-write-to-stream-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    25714     # . prologue
    25715     55/push-ebp
    25716     89/<- %ebp 4/r32/esp
    25717     # . save registers
    25718     50/push-eax
    25719     51/push-ecx
    25720     52/push-edx
    25721     53/push-ebx
    25722     56/push-esi
    25723     57/push-edi
    25724     # esi = stmt
    25725     8b/-> *(ebp+8) 6/r32/esi
    25726     # - check for 0 inouts
    25727     # var base/ecx: (addr var) = stmt->inouts->value
    25728     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    25729 $check-mu-write-to-stream-stmt:check-no-inouts:
    25730     3d/compare-eax-and 0/imm32
    25731     0f 84/jump-if-= $check-mu-write-to-stream-stmt:error-too-few-inouts/disp32
    25732     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    25733     89/<- %ecx 0/r32/eax
    25734     # - check base type is (addr stream T)
    25735     # var base-type/ebx: (addr type-tree) = lookup(base->type)
    25736     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
    25737     89/<- %ebx 0/r32/eax
    25738 $check-mu-write-to-stream-stmt:check-base-is-compound:
    25739     # if base-type is an atom, abort
    25740     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
    25741     0f 85/jump-if-!= $check-mu-write-to-stream-stmt:error-invalid-base-type/disp32
    25742 $check-mu-write-to-stream-stmt:check-base-is-addr:
    25743     # if type->left not addr, abort
    25744     (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
    25745     (simple-mu-type? %eax 2)  # addr => eax
    25746     3d/compare-eax-and 0/imm32/false
    25747     0f 84/jump-if-= $check-mu-write-to-stream-stmt:error-invalid-base-type/disp32
    25748 $check-mu-write-to-stream-stmt:check-base-is-addr-to-stream:
    25749     # base-type = base-type->right
    25750     (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
    25751     89/<- %ebx 0/r32/eax
    25752     # ensure base-type->left == stream
    25753     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    25754     (simple-mu-type? %eax 0xb)  # stream => eax
    25755     3d/compare-eax-and 0/imm32/false
    25756     0f 84/jump-if-= $check-mu-write-to-stream-stmt:error-invalid-base-type/disp32
    25757     # - check target type is (addr T)
    25758     # var target/ecx: (addr stmt-var) = stmt->inouts->next->value
    25759     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    25760     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    25761 $check-mu-write-to-stream-stmt:check-single-inout:
    25762     3d/compare-eax-and 0/imm32
    25763     0f 84/jump-if-= $check-mu-write-to-stream-stmt:error-too-few-inouts/disp32
    25764     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    25765     89/<- %ecx 0/r32/eax
    25766     # var target-type/edx: (addr type-tree)
    25767     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
    25768     89/<- %edx 0/r32/eax
    25769     # if target-type is an atom, it must be a literal or int
    25770 $check-mu-write-to-stream-stmt:check-target-is-compound:
    25771     81 7/subop/compare *edx 0/imm32/false  # Type-tree-is-atom
    25772     0f 85/jump-if-!= $check-mu-write-to-stream-stmt:error-target-type-not-address/disp32
    25773 $check-mu-write-to-stream-stmt:check-target-type:
    25774     # target type must start with (addr ...)
    25775     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
    25776     (simple-mu-type? %eax 2)  # addr => eax
    25777     3d/compare-eax-and 0/imm32/false
    25778     0f 84/jump-if-= $check-mu-write-to-stream-stmt:error-target-type-not-address/disp32
    25779     # if tail(base-type) != tail(target-type) abort
    25780     (type-tail %ebx)  # => eax
    25781     89/<- %ebx 0/r32/eax
    25782     (type-tail %edx)  # => eax
    25783     (type-equal? %ebx %eax)  # => eax
    25784     3d/compare-eax-and 0/imm32/false
    25785     0f 84/jump-if-= $check-mu-write-to-stream-stmt:error-invalid-target-type/disp32
    25786 $check-mu-write-to-stream-stmt:check-too-many-inouts:
    25787     # - check for too many inouts
    25788     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    25789     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    25790     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    25791     3d/compare-eax-and 0/imm32/false
    25792     0f 85/jump-if-!= $check-mu-write-to-stream-stmt:error-too-many-inouts/disp32
    25793 $check-mu-write-to-stream-stmt:check-unexpected-output:
    25794     # - check for any output
    25795     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    25796     3d/compare-eax-and 0/imm32/false
    25797     0f 85/jump-if-!= $check-mu-write-to-stream-stmt:error-unexpected-output/disp32
    25798 $check-mu-write-to-stream-stmt:end:
    25799     # . restore registers
    25800     5f/pop-to-edi
    25801     5e/pop-to-esi
    25802     5b/pop-to-ebx
    25803     5a/pop-to-edx
    25804     59/pop-to-ecx
    25805     58/pop-to-eax
    25806     # . epilogue
    25807     89/<- %esp 5/r32/ebp
    25808     5d/pop-to-ebp
    25809     c3/return
    25810
    25811 $check-mu-write-to-stream-stmt:error-invalid-base-type:
    25812     (write-buffered *(ebp+0x10) "fn ")
    25813     8b/-> *(ebp+0xc) 0/r32/eax
    25814     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25815     (write-buffered *(ebp+0x10) %eax)
    25816     (write-buffered *(ebp+0x10) ": stmt write-to-stream: var '")
    25817     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    25818     (write-buffered *(ebp+0x10) %eax)
    25819     (write-buffered *(ebp+0x10) "' must be an addr to a stream\n")
    25820     (flush *(ebp+0x10))
    25821     (stop *(ebp+0x14) 1)
    25822     # never gets here
    25823
    25824 $check-mu-write-to-stream-stmt:error-too-few-inouts:
    25825     (write-buffered *(ebp+0x10) "fn ")
    25826     8b/-> *(ebp+0xc) 0/r32/eax
    25827     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25828     (write-buffered *(ebp+0x10) %eax)
    25829     (write-buffered *(ebp+0x10) ": stmt write-to-stream: too few inouts (2 required)\n")
    25830     (flush *(ebp+0x10))
    25831     (stop *(ebp+0x14) 1)
    25832     # never gets here
    25833
    25834 $check-mu-write-to-stream-stmt:error-target-type-not-address:
    25835     (write-buffered *(ebp+0x10) "fn ")
    25836     8b/-> *(ebp+0xc) 0/r32/eax
    25837     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25838     (write-buffered *(ebp+0x10) %eax)
    25839     (write-buffered *(ebp+0x10) ": stmt write-to-stream: target '")
    25840     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    25841     (write-buffered *(ebp+0x10) %eax)
    25842     (write-buffered *(ebp+0x10) "' must be an addr\n")
    25843     (flush *(ebp+0x10))
    25844     (stop *(ebp+0x14) 1)
    25845     # never gets here
    25846
    25847 $check-mu-write-to-stream-stmt:error-invalid-target-type:
    25848     (write-buffered *(ebp+0x10) "fn ")
    25849     8b/-> *(ebp+0xc) 0/r32/eax
    25850     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25851     (write-buffered *(ebp+0x10) %eax)
    25852     (write-buffered *(ebp+0x10) ": stmt write-to-stream: second inout '")
    25853     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    25854     (write-buffered *(ebp+0x10) %eax)
    25855     (write-buffered *(ebp+0x10) "' does not have the right type\n")
    25856     (flush *(ebp+0x10))
    25857     (stop *(ebp+0x14) 1)
    25858     # never gets here
    25859
    25860 $check-mu-write-to-stream-stmt:error-too-many-inouts:
    25861     (write-buffered *(ebp+0x10) "fn ")
    25862     8b/-> *(ebp+0xc) 0/r32/eax
    25863     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25864     (write-buffered *(ebp+0x10) %eax)
    25865     (write-buffered *(ebp+0x10) ": stmt write-to-stream: too many inouts (2 required)\n")
    25866     (flush *(ebp+0x10))
    25867     (stop *(ebp+0x14) 1)
    25868     # never gets here
    25869
    25870 $check-mu-write-to-stream-stmt:error-unexpected-output:
    25871     (write-buffered *(ebp+0x10) "fn ")
    25872     8b/-> *(ebp+0xc) 0/r32/eax
    25873     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25874     (write-buffered *(ebp+0x10) %eax)
    25875     (write-buffered *(ebp+0x10) ": stmt write-to-stream: unexpected output\n")
    25876     (flush *(ebp+0x10))
    25877     (stop *(ebp+0x14) 1)
    25878     # never gets here
    25879
    25880 check-mu-convert-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    25881     # . prologue
    25882     55/push-ebp
    25883     89/<- %ebp 4/r32/esp
    25884     # . save registers
    25885     50/push-eax
    25886     51/push-ecx
    25887     52/push-edx
    25888     56/push-esi
    25889     57/push-edi
    25890 $check-mu-convert-stmt:get-output:
    25891     # esi = stmt
    25892     8b/-> *(ebp+8) 6/r32/esi
    25893     # var output/edi: (addr stmt-var) = stmt->outputs
    25894     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    25895     89/<- %edi 0/r32/eax
    25896     # zero outputs
    25897     3d/compare-eax-and 0/imm32
    25898     0f 84/jump-if-= $check-mu-convert-stmt:error-no-output/disp32
    25899     # > 1 output
    25900     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
    25901     3d/compare-eax-and 0/imm32
    25902     0f 85/jump-if-!= $check-mu-convert-stmt:error-too-many-outputs/disp32
    25903 $check-mu-convert-stmt:get-inout:
    25904     # var inout/esi: (addr stmt-var) = stmt->inouts
    25905     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    25906     89/<- %esi 0/r32/eax
    25907     # zero inouts
    25908     3d/compare-eax-and 0/imm32
    25909     0f 84/jump-if-= $check-mu-convert-stmt:error-no-inout/disp32
    25910     # > 1 inout
    25911     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
    25912     3d/compare-eax-and 0/imm32
    25913     0f 85/jump-if-!= $check-mu-convert-stmt:error-too-many-inouts/disp32
    25914 $check-mu-convert-stmt:types:
    25915     # var inout-type/ecx: (addr type-tree) = inout->value->type
    25916     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    25917     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    25918     89/<- %ecx 0/r32/eax
    25919     # if (inout->is-deref?) inout-type = inout-type->payload
    25920     8b/-> *(esi+0x10) 0/r32/eax  # Stmt-var-is-deref
    25921     3d/compare-eax-and 0/imm32/false
    25922     {
    25923       74/jump-if-= break/disp8
    25924       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
    25925       # if inout-type->right is null, t = inout-type->left
    25926       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
    25927       {
    25928         75/jump-if-!= break/disp8
    25929         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    25930       }
    25931       89/<- %ecx 0/r32/eax
    25932     }
    25933     # if input is not int or float, abort
    25934     {
    25935       (simple-mu-type? %ecx 1)  # int => eax
    25936       3d/compare-eax-and 0/imm32/false
    25937       75/jump-if-!= break/disp8
    25938       (simple-mu-type? %ecx 0xf)  # float => eax
    25939       3d/compare-eax-and 0/imm32/false
    25940       75/jump-if-!= break/disp8
    25941       e9/jump $check-mu-convert-stmt:error-invalid-inout-type/disp32
    25942     }
    25943     # if output not in register, abort
    25944     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    25945     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    25946     3d/compare-eax-and 0/imm32
    25947     0f 84/jump-if-= $check-mu-convert-stmt:error-output-not-in-register/disp32
    25948     # var output-type/edx: (addr type-tree) = output->value->type
    25949     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    25950     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    25951     89/<- %edx 0/r32/eax
    25952     # if output is not int or float, abort
    25953     {
    25954       (simple-mu-type? %edx 1)  # int => eax
    25955       3d/compare-eax-and 0/imm32/false
    25956       75/jump-if-!= break/disp8
    25957       (simple-mu-type? %edx 0xf)  # float => eax
    25958       3d/compare-eax-and 0/imm32/false
    25959       75/jump-if-!= break/disp8
    25960       e9/jump $check-mu-convert-stmt:error-invalid-output-type/disp32
    25961     }
    25962     # if both are ints, abort
    25963     {
    25964       (simple-mu-type? %edx 1)  # int => eax
    25965       3d/compare-eax-and 0/imm32/false
    25966       74/jump-if-= break/disp8
    25967       (simple-mu-type? %ecx 1)  # int => eax
    25968       3d/compare-eax-and 0/imm32/false
    25969       74/jump-if-= break/disp8
    25970       e9/jump $check-mu-convert-stmt:error-int-to-int/disp32
    25971     }
    25972     # if both are floats, abort
    25973     {
    25974       (simple-mu-type? %edx 0xf)  # float => eax
    25975       3d/compare-eax-and 0/imm32/false
    25976       74/jump-if-= break/disp8
    25977       (simple-mu-type? %ecx 0xf)  # float => eax
    25978       3d/compare-eax-and 0/imm32/false
    25979       74/jump-if-= break/disp8
    25980       e9/jump $check-mu-convert-stmt:error-float-to-float/disp32
    25981     }
    25982 $check-mu-convert-stmt:end:
    25983     # . restore registers
    25984     5f/pop-to-edi
    25985     5e/pop-to-esi
    25986     5a/pop-to-edx
    25987     59/pop-to-ecx
    25988     58/pop-to-eax
    25989     # . epilogue
    25990     89/<- %esp 5/r32/ebp
    25991     5d/pop-to-ebp
    25992     c3/return
    25993
    25994 $check-mu-convert-stmt:error-no-inout:
    25995     (write-buffered *(ebp+0x10) "fn ")
    25996     8b/-> *(ebp+0xc) 0/r32/eax
    25997     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25998     (write-buffered *(ebp+0x10) %eax)
    25999     (write-buffered *(ebp+0x10) ": stmt 'convert' expects an inout\n")
    26000     (flush *(ebp+0x10))
    26001     (stop *(ebp+0x14) 1)
    26002     # never gets here
    26003
    26004 $check-mu-convert-stmt:error-too-many-inouts:
    26005     (write-buffered *(ebp+0x10) "fn ")
    26006     8b/-> *(ebp+0xc) 0/r32/eax
    26007     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    26008     (write-buffered *(ebp+0x10) %eax)
    26009     (write-buffered *(ebp+0x10) ": stmt 'convert' must have just one inout\n")
    26010     (flush *(ebp+0x10))
    26011     (stop *(ebp+0x14) 1)
    26012     # never gets here
    26013
    26014 $check-mu-convert-stmt:error-no-output:
    26015     (write-buffered *(ebp+0x10) "fn ")
    26016     8b/-> *(ebp+0xc) 0/r32/eax
    26017     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    26018     (write-buffered *(ebp+0x10) %eax)
    26019     (write-buffered *(ebp+0x10) ": stmt 'convert' expects an output\n")
    26020     (flush *(ebp+0x10))
    26021     (stop *(ebp+0x14) 1)
    26022     # never gets here
    26023
    26024 $check-mu-convert-stmt:error-output-not-in-register:
    26025     (write-buffered *(ebp+0x10) "fn ")
    26026     8b/-> *(ebp+0xc) 0/r32/eax
    26027     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    26028     (write-buffered *(ebp+0x10) %eax)
    26029     (write-buffered *(ebp+0x10) ": stmt convert: output '")
    26030     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    26031     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    26032     (write-buffered *(ebp+0x10) %eax)
    26033     (write-buffered *(ebp+0x10) "' not in a register\n")
    26034     (flush *(ebp+0x10))
    26035     (stop *(ebp+0x14) 1)
    26036     # never gets here
    26037
    26038 $check-mu-convert-stmt:error-too-many-outputs:
    26039     (write-buffered *(ebp+0x10) "fn ")
    26040     8b/-> *(ebp+0xc) 0/r32/eax
    26041     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    26042     (write-buffered *(ebp+0x10) %eax)
    26043     (write-buffered *(ebp+0x10) ": stmt 'convert' must have just one output\n")
    26044     (flush *(ebp+0x10))
    26045     (stop *(ebp+0x14) 1)
    26046     # never gets here
    26047
    26048 $check-mu-convert-stmt:error-invalid-inout-type:
    26049     (write-buffered *(ebp+0x10) "fn ")
    26050     8b/-> *(ebp+0xc) 0/r32/eax
    26051     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    26052     (write-buffered *(ebp+0x10) %eax)
    26053     (write-buffered *(ebp+0x10) ": stmt convert: inout '")
    26054     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    26055     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    26056     (write-buffered *(ebp+0x10) %eax)
    26057     (write-buffered *(ebp+0x10) "' must be an int or float\n")
    26058     (flush *(ebp+0x10))
    26059     (stop *(ebp+0x14) 1)
    26060     # never gets here
    26061
    26062 $check-mu-convert-stmt:error-invalid-output-type:
    26063     (write-buffered *(ebp+0x10) "fn ")
    26064     8b/-> *(ebp+0xc) 0/r32/eax
    26065     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    26066     (write-buffered *(ebp+0x10) %eax)
    26067     (write-buffered *(ebp+0x10) ": stmt convert: output '")
    26068     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    26069     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    26070     (write-buffered *(ebp+0x10) %eax)
    26071     (write-buffered *(ebp+0x10) "' must be an int or float\n")
    26072     (flush *(ebp+0x10))
    26073     (stop *(ebp+0x14) 1)
    26074     # never gets here
    26075
    26076 $check-mu-convert-stmt:error-int-to-int:
    26077     (write-buffered *(ebp+0x10) "fn ")
    26078     8b/-> *(ebp+0xc) 0/r32/eax
    26079     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    26080     (write-buffered *(ebp+0x10) %eax)
    26081     (write-buffered *(ebp+0x10) ": stmt convert: no need to convert int to int\n")
    26082     (flush *(ebp+0x10))
    26083     (stop *(ebp+0x14) 1)
    26084     # never gets here
    26085
    26086 $check-mu-convert-stmt:error-float-to-float:
    26087     (write-buffered *(ebp+0x10) "fn ")
    26088     8b/-> *(ebp+0xc) 0/r32/eax
    26089     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    26090     (write-buffered *(ebp+0x10) %eax)
    26091     (write-buffered *(ebp+0x10) ": stmt convert: no need to convert float to float\n")
    26092     (flush *(ebp+0x10))
    26093     (stop *(ebp+0x14) 1)
    26094     # never gets here
    26095
    26096 check-mu-call:  # stmt: (addr stmt), callee: (addr function), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    26097     # . prologue
    26098     55/push-ebp
    26099     89/<- %ebp 4/r32/esp
    26100     # var type-parameters: (addr table (handle array byte) (addr type-tree) 8)
    26101     68/push 0/imm32
    26102     # var type-parameters-storage: (table (handle array byte) (addr type-tree) 8)
    26103     81 5/subop/subtract %esp 0x60/imm32
    26104     68/push 0x60/imm32/size
    26105     68/push 0/imm32/read
    26106     68/push 0/imm32/write
    26107     # save a pointer to type-parameters-storage at type-parameters
    26108     89/<- *(ebp-4) 4/r32/esp
    26109     (clear-stream *(ebp-4))
    26110     # . save registers
    26111     50/push-eax
    26112     51/push-ecx
    26113     52/push-edx
    26114     53/push-ebx
    26115     56/push-esi
    26116     57/push-edi
    26117     # esi = stmt
    26118     8b/-> *(ebp+8) 6/r32/esi
    26119     # edi = callee
    26120     8b/-> *(ebp+0xc) 7/r32/edi
    26121     # var inouts/ecx: (addr stmt-var) = lookup(stmt->inouts)
    26122     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    26123     89/<- %ecx 0/r32/eax
    26124     # var expected/edx: (addr list var) = lookup(f->inouts)
    26125     (lookup *(edi+8) *(edi+0xc))  # Function-inouts Function-inouts => eax
    26126     89/<- %edx 0/r32/eax
    26127     {
    26128 $check-mu-call:check-for-inouts:
    26129       # if (inouts == 0) break
    26130       81 7/subop/compare %ecx 0/imm32
    26131       0f 84/jump-if-= break/disp32
    26132       # if (expected == 0) error
    26133       81 7/subop/compare %edx 0/imm32
    26134       0f 84/jump-if-= break/disp32
    26135 $check-mu-call:check-null-addr:
    26136       # if (inouts->value->name == "0") continue
    26137       (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
    26138       (lookup *eax *(eax+4))  # Var-name Var-name => eax
    26139       (string-equal? %eax "0")  # => eax
    26140       3d/compare-eax-and 0/imm32/false
    26141       0f 85/jump-if-!= $check-mu-call:continue-to-next-inout/disp32
    26142 $check-mu-call:check-inout-type:
    26143       # var t/ebx: (addr type-tree) = inouts->value->type
    26144       (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
    26145       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    26146       89/<- %ebx 0/r32/eax
    26147       # if (inouts->is-deref?) t = t->right
    26148       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
    26149       {
    26150         74/jump-if-= break/disp8
    26151         (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
    26152         89/<- %ebx 0/r32/eax
    26153         # if t->right is null, t = t->left
    26154         81 7/subop/compare *(ebx+0xc) 0/imm32  # Type-tree-right
    26155         75/jump-if-!= break/disp8
    26156         (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
    26157         89/<- %ebx 0/r32/eax
    26158       }
    26159       # var v2/eax: (addr v) = lookup(expected->value)
    26160       (lookup *edx *(edx+4))  # List-value List-value => eax
    26161       # var t2/eax: (addr type-tree) = lookup(v2->type)
    26162       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    26163       # if (t != t2) error
    26164       (type-match? %eax %ebx *(ebp-4))  # => eax
    26165       3d/compare-eax-and 0/imm32/false
    26166       {
    26167         0f 85/jump-if-!= break/disp32
    26168         (write-buffered *(ebp+0x14) "fn ")
    26169         8b/-> *(ebp+0x10) 0/r32/eax
    26170         (lookup *eax *(eax+4))  # Function-name Function-name => eax
    26171         (write-buffered *(ebp+0x14) %eax)
    26172         (write-buffered *(ebp+0x14) ": call ")
    26173         (lookup *edi *(edi+4))  # Function-name Function-name => eax
    26174         (write-buffered *(ebp+0x14) %eax)
    26175         (write-buffered *(ebp+0x14) ": type for inout '")
    26176         (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
    26177         (lookup *eax *(eax+4))  # Var-name Var-name => eax
    26178         (write-buffered *(ebp+0x14) %eax)
    26179         (write-buffered *(ebp+0x14) "' is not right\n")
    26180         (flush *(ebp+0x14))
    26181         (stop *(ebp+0x18) 1)
    26182       }
    26183 $check-mu-call:continue-to-next-inout:
    26184       # inouts = lookup(inouts->next)
    26185       (lookup *(ecx+8) *(ecx+0xc))  # Stmt-var-next Stmt-var-next => eax
    26186       89/<- %ecx 0/r32/eax
    26187       # expected = lookup(expected->next)
    26188       (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
    26189       89/<- %edx 0/r32/eax
    26190       #
    26191       e9/jump loop/disp32
    26192     }
    26193 $check-mu-call:check-inout-count:
    26194     # if (inouts == expected) proceed
    26195     39/compare %ecx 2/r32/edx
    26196     {
    26197       0f 84/jump-if-= break/disp32
    26198       # exactly one of the two is null
    26199       # if (inouts == 0) error("too many inouts")
    26200       {
    26201         81 7/subop/compare %ecx 0/imm32
    26202         0f 84/jump-if-= break/disp32
    26203         (write-buffered *(ebp+0x14) "fn ")
    26204         8b/-> *(ebp+0x10) 0/r32/eax
    26205         (lookup *eax *(eax+4))  # Function-name Function-name => eax
    26206         (write-buffered *(ebp+0x14) %eax)
    26207         (write-buffered *(ebp+0x14) ": call ")
    26208         (lookup *edi *(edi+4))  # Function-name Function-name => eax
    26209         (write-buffered *(ebp+0x14) %eax)
    26210         (write-buffered *(ebp+0x14) ": too many inouts\n")
    26211         (flush *(ebp+0x14))
    26212         (stop *(ebp+0x18) 1)
    26213       }
    26214       # if (expected == 0) error("too few inouts")
    26215       {
    26216         81 7/subop/compare %edx 0/imm32
    26217         0f 84/jump-if-= break/disp32
    26218         (write-buffered *(ebp+0x14) "fn ")
    26219         8b/-> *(ebp+0x10) 0/r32/eax
    26220         (lookup *eax *(eax+4))  # Function-name Function-name => eax
    26221         (write-buffered *(ebp+0x14) %eax)
    26222         (write-buffered *(ebp+0x14) ": call ")
    26223         (lookup *edi *(edi+4))  # Function-name Function-name => eax
    26224         (write-buffered *(ebp+0x14) %eax)
    26225         (write-buffered *(ebp+0x14) ": too few inouts\n")
    26226         (flush *(ebp+0x14))
    26227         (stop *(ebp+0x18) 1)
    26228       }
    26229     }
    26230 $check-mu-call:check-outputs:
    26231     # var outputs/ecx: (addr stmt-var) = lookup(stmt->outputs)
    26232     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    26233     89/<- %ecx 0/r32/eax
    26234     # var expected/edx: (addr list var) = lookup(f->outputs)
    26235     (lookup *(edi+0x10) *(edi+0x14))  # Function-outputs Function-outputs => eax
    26236     89/<- %edx 0/r32/eax
    26237     {
    26238 $check-mu-call:check-for-outputs:
    26239       # if (outputs == 0) break
    26240       81 7/subop/compare %ecx 0/imm32
    26241       0f 84/jump-if-= break/disp32
    26242       # if (expected == 0) error
    26243       81 7/subop/compare %edx 0/imm32
    26244       0f 84/jump-if-= break/disp32
    26245 $check-mu-call:check-output-type:
    26246       # var v/eax: (addr v) = lookup(outputs->value)
    26247       (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
    26248       # var t/ebx: (addr type-tree) = lookup(v->type)
    26249       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    26250       89/<- %ebx 0/r32/eax
    26251       # if (outputs->is-deref?) t = t->right  # TODO: check that t->left is an addr
    26252       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
    26253       {
    26254         74/jump-if-= break/disp8
    26255         (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
    26256         89/<- %ebx 0/r32/eax
    26257       }
    26258       # var v2/eax: (addr v) = lookup(expected->value)
    26259       (lookup *edx *(edx+4))  # List-value List-value => eax
    26260       # var t2/eax: (addr type-tree) = lookup(v2->type)
    26261       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    26262       # if (t != t2) error
    26263       (type-match? %eax %ebx *(ebp-4))  # => eax
    26264       3d/compare-eax-and 0/imm32/false
    26265       {
    26266         0f 85/jump-if-!= break/disp32
    26267         (write-buffered *(ebp+0x14) "fn ")
    26268         8b/-> *(ebp+0x10) 0/r32/eax
    26269         (lookup *eax *(eax+4))  # Function-name Function-name => eax
    26270         (write-buffered *(ebp+0x14) %eax)
    26271         (write-buffered *(ebp+0x14) ": call ")
    26272         (lookup *edi *(edi+4))  # Function-name Function-name => eax
    26273         (write-buffered *(ebp+0x14) %eax)
    26274         (write-buffered *(ebp+0x14) ": type for output '")
    26275         (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
    26276         (lookup *eax *(eax+4))  # Var-name Var-name => eax
    26277         (write-buffered *(ebp+0x14) %eax)
    26278         (write-buffered *(ebp+0x14) "' is not right\n")
    26279         (flush *(ebp+0x14))
    26280         (stop *(ebp+0x18) 1)
    26281       }
    26282 $check-mu-call:check-output-register:
    26283       # var v/eax: (addr v) = lookup(outputs->value)
    26284       (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
    26285       # var r/ebx: (addr array byte) = lookup(v->register)
    26286       (lookup *(eax+18) *(eax+0x1c))  # Var-register Var-register => eax
    26287       89/<- %ebx 0/r32/eax
    26288       # if (r == 0) error
    26289       3d/compare-eax-and 0/imm32
    26290       {
    26291         0f 85/jump-if-!= break/disp32
    26292         (write-buffered *(ebp+0x14) "fn ")
    26293         8b/-> *(ebp+0x10) 0/r32/eax
    26294         (lookup *eax *(eax+4))  # Function-name Function-name => eax
    26295         (write-buffered *(ebp+0x14) %eax)
    26296         (write-buffered *(ebp+0x14) ": call ")
    26297         (lookup *edi *(edi+4))  # Function-name Function-name => eax
    26298         (write-buffered *(ebp+0x14) %eax)
    26299         (write-buffered *(ebp+0x14) ": output '")
    26300         (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
    26301         (lookup *eax *(eax+4))  # Var-name Var-name => eax
    26302         (write-buffered *(ebp+0x14) %eax)
    26303         (write-buffered *(ebp+0x14) "' is not in a register\n")
    26304         (flush *(ebp+0x14))
    26305         (stop *(ebp+0x18) 1)
    26306       }
    26307       # var v2/eax: (addr v) = lookup(expected->value)
    26308       (lookup *edx *(edx+4))  # Stmt-var-value Stmt-var-value => eax
    26309       # var r2/eax: (addr array byte) = lookup(v2->register)
    26310       (lookup *(eax+18) *(eax+0x1c))  # Var-register Var-register => eax
    26311       # if (r != r2) error
    26312       (string-equal? %eax %ebx)  # => eax
    26313       3d/compare-eax-and 0/imm32/false
    26314       {
    26315         0f 85/jump-if-!= break/disp32
    26316         (write-buffered *(ebp+0x14) "fn ")
    26317         8b/-> *(ebp+0x10) 0/r32/eax
    26318         (lookup *eax *(eax+4))  # Function-name Function-name => eax
    26319         (write-buffered *(ebp+0x14) %eax)
    26320         (write-buffered *(ebp+0x14) ": call ")
    26321         (lookup *edi *(edi+4))  # Function-name Function-name => eax
    26322         (write-buffered *(ebp+0x14) %eax)
    26323         (write-buffered *(ebp+0x14) ": register for output '")
    26324         (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
    26325         (lookup *eax *(eax+4))  # Var-name Var-name => eax
    26326         (write-buffered *(ebp+0x14) %eax)
    26327         (write-buffered *(ebp+0x14) "' is not right\n")
    26328         (flush *(ebp+0x14))
    26329         (stop *(ebp+0x18) 1)
    26330       }
    26331 $check-mu-call:continue-to-next-output:
    26332       # outputs = lookup(outputs->next)
    26333       (lookup *(ecx+8) *(ecx+0xc))  # Stmt-var-next Stmt-var-next => eax
    26334       89/<- %ecx 0/r32/eax
    26335       # expected = lookup(expected->next)
    26336       (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
    26337       89/<- %edx 0/r32/eax
    26338       #
    26339       e9/jump loop/disp32
    26340     }
    26341 $check-mu-call:check-output-count:
    26342     # if (outputs == expected) proceed
    26343     39/compare %ecx 2/r32/edx
    26344     {
    26345       0f 84/jump-if-= break/disp32
    26346       # exactly one of the two is null
    26347       # if (outputs == 0) error("too many outputs")
    26348       {
    26349         81 7/subop/compare %ecx 0/imm32
    26350         0f 84/jump-if-= break/disp32
    26351         (write-buffered *(ebp+0x14) "fn ")
    26352         8b/-> *(ebp+0x10) 0/r32/eax
    26353         (lookup *eax *(eax+4))  # Function-name Function-name => eax
    26354         (write-buffered *(ebp+0x14) %eax)
    26355         (write-buffered *(ebp+0x14) ": call ")
    26356         (lookup *edi *(edi+4))  # Function-name Function-name => eax
    26357         (write-buffered *(ebp+0x14) %eax)
    26358         (write-buffered *(ebp+0x14) ": too many outputs\n")
    26359         (flush *(ebp+0x14))
    26360         (stop *(ebp+0x18) 1)
    26361       }
    26362       # if (expected == 0) error("too few outputs")
    26363       {
    26364         81 7/subop/compare %edx 0/imm32
    26365         0f 84/jump-if-= break/disp32
    26366         (write-buffered *(ebp+0x14) "fn ")
    26367         8b/-> *(ebp+0x10) 0/r32/eax
    26368         (lookup *eax *(eax+4))  # Function-name Function-name => eax
    26369         (write-buffered *(ebp+0x14) %eax)
    26370         (write-buffered *(ebp+0x14) ": call ")
    26371         (lookup *edi *(edi+4))  # Function-name Function-name => eax
    26372         (write-buffered *(ebp+0x14) %eax)
    26373         (write-buffered *(ebp+0x14) ": too few outputs\n")
    26374         (flush *(ebp+0x14))
    26375         (stop *(ebp+0x18) 1)
    26376       }
    26377     }
    26378 $check-mu-call:end:
    26379     # . restore registers
    26380     5f/pop-to-edi
    26381     5e/pop-to-esi
    26382     5b/pop-to-ebx
    26383     5a/pop-to-edx
    26384     59/pop-to-ecx
    26385     58/pop-to-eax
    26386     # . reclaim locals exclusively on the stack
    26387     81 0/subop/add %esp 0x70/imm32
    26388     # . epilogue
    26389     89/<- %esp 5/r32/ebp
    26390     5d/pop-to-ebp
    26391     c3/return
    26392
    26393 # like type-equal? but takes literals type parameters into account
    26394 type-match?:  # def: (addr type-tree), call: (addr type-tree), type-parameters: (addr table (handle array byte) (addr type-tree)) -> result/eax: boolean
    26395     # . prologue
    26396     55/push-ebp
    26397     89/<- %ebp 4/r32/esp
    26398     # if (call is literal and def is numberlike) return true
    26399     {
    26400 $type-match?:check-literal-int:
    26401       (simple-mu-type? *(ebp+0xc) 0)  # literal => eax
    26402       3d/compare-eax-and 0/imm32/false
    26403       74/jump-if-= break/disp8
    26404       (mu-numberlike-output? *(ebp+8))  # => eax
    26405       3d/compare-eax-and 0/imm32/false
    26406       74/jump-if-= break/disp8
    26407       b8/copy-to-eax 1/imm32/true
    26408       e9/jump $type-match?:end/disp32
    26409     }
    26410     # if (call is literal-string and def is string) return true
    26411     {
    26412 $type-match?:check-literal-string:
    26413       (simple-mu-type? *(ebp+0xc) 0x10)  # literal-string => eax
    26414       3d/compare-eax-and 0/imm32/false
    26415       74/jump-if-= break/disp8
    26416       (mu-string-type? *(ebp+8))  # => eax
    26417       3d/compare-eax-and 0/imm32/false
    26418       74/jump-if-= break/disp8
    26419       b8/copy-to-eax 1/imm32/true
    26420       e9/jump $type-match?:end/disp32
    26421     }
    26422 $type-match?:baseline:
    26423     # otherwise fall back
    26424     (type-component-match? *(ebp+8) *(ebp+0xc) *(ebp+0x10))  # => eax
    26425 $type-match?:end:
    26426     # . epilogue
    26427     89/<- %esp 5/r32/ebp
    26428     5d/pop-to-ebp
    26429     c3/return
    26430
    26431 type-component-match?:  # def: (addr type-tree), call: (addr type-tree), type-parameters: (addr table (handle array byte) (addr type-tree)) -> result/eax: boolean
    26432     # . prologue
    26433     55/push-ebp
    26434     89/<- %ebp 4/r32/esp
    26435     # . save registers
    26436     51/push-ecx
    26437     52/push-edx
    26438     53/push-ebx
    26439     # ecx = def
    26440     8b/-> *(ebp+8) 1/r32/ecx
    26441     # edx = call
    26442     8b/-> *(ebp+0xc) 2/r32/edx
    26443 $type-component-match?:compare-addr:
    26444     # if (def == call) return true
    26445     8b/-> %ecx 0/r32/eax  # Var-type
    26446     39/compare %edx 0/r32/eax  # Var-type
    26447     b8/copy-to-eax 1/imm32/true
    26448     0f 84/jump-if-= $type-component-match?:end/disp32
    26449     # if (def == 0) return false
    26450     b8/copy-to-eax 0/imm32/false
    26451     81 7/subop/compare %ecx 0/imm32  # Type-tree-is-atom
    26452     0f 84/jump-if-= $type-component-match?:end/disp32
    26453     # if (call == 0) return false
    26454     81 7/subop/compare %edx 0/imm32  # Type-tree-is-atom
    26455     0f 84/jump-if-= $type-component-match?:end/disp32
    26456     # if def is a type parameter, just check in type-parameters
    26457     {
    26458 $type-component-match?:check-type-parameter:
    26459       81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
    26460       74/jump-if-= break/disp8
    26461       81 7/subop/compare *(ecx+4) 0xa/imm32/type-parameter  # Type-tree-value
    26462       75/jump-if-!= break/disp8
    26463 $type-component-match?:type-parameter:
    26464       (type-parameter-match? *(ecx+8) *(ecx+0xc)  %edx  *(ebp+0x10))  # => eax
    26465       e9/jump $type-component-match?:end/disp32
    26466     }
    26467     # if def is a list containing just a type parameter, just check in type-parameters
    26468     {
    26469 $type-component-match?:check-list-type-parameter:
    26470       # if def is a list..
    26471       81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
    26472       75/jump-if-!= break/disp8
    26473       #   ..that's a singleton
    26474       81 7/subop/compare *(ecx+0xc) 0/imm32  # Type-tree-left
    26475       75/jump-if-!= break/disp8
    26476       #   ..and whose head is a type parameter
    26477       (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
    26478       81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
    26479       74/jump-if-= break/disp8
    26480       81 7/subop/compare *(eax+4) 0xa/imm32/type-parameter  # Type-tree-value
    26481       75/jump-if-!= break/disp8
    26482 $type-component-match?:list-type-parameter:
    26483       (type-parameter-match? *(eax+8) *(eax+0xc)  %edx  *(ebp+0x10))  # => eax
    26484       e9/jump $type-component-match?:end/disp32
    26485     }
    26486 $type-component-match?:compare-atom-state:
    26487     # if (def->is-atom? != call->is-atom?) return false
    26488     8b/-> *ecx 3/r32/ebx  # Type-tree-is-atom
    26489     39/compare *edx 3/r32/ebx  # Type-tree-is-atom
    26490     b8/copy-to-eax 0/imm32/false
    26491     0f 85/jump-if-!= $type-component-match?:end/disp32
    26492     # if def->is-atom? return (def->value == call->value)
    26493     {
    26494 $type-component-match?:check-atom:
    26495       81 7/subop/compare %ebx 0/imm32/false
    26496       74/jump-if-= break/disp8
    26497 $type-component-match?:is-atom:
    26498       8b/-> *(ecx+4) 0/r32/eax  # Type-tree-value
    26499       39/compare *(edx+4) 0/r32/eax  # Type-tree-value
    26500       0f 94/set-if-= %al
    26501       81 4/subop/and %eax 0xff/imm32
    26502       e9/jump $type-component-match?:end/disp32
    26503     }
    26504 $type-component-match?:check-left:
    26505     # if (!type-component-match?(def->left, call->left)) return false
    26506     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
    26507     89/<- %ebx 0/r32/eax
    26508     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
    26509     (type-component-match? %ebx %eax *(ebp+0x10))  # => eax
    26510     3d/compare-eax-and 0/imm32/false
    26511     74/jump-if-= $type-component-match?:end/disp8
    26512 $type-component-match?:check-right:
    26513     # return type-component-match?(def->right, call->right)
    26514     (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
    26515     89/<- %ebx 0/r32/eax
    26516     (lookup *(edx+0xc) *(edx+0x10))  # Type-tree-right Type-tree-right => eax
    26517     (type-component-match? %ebx %eax *(ebp+0x10))  # => eax
    26518 $type-component-match?:end:
    26519     # . restore registers
    26520     5b/pop-to-ebx
    26521     5a/pop-to-edx
    26522     59/pop-to-ecx
    26523     # . epilogue
    26524     89/<- %esp 5/r32/ebp
    26525     5d/pop-to-ebp
    26526     c3/return
    26527
    26528 type-parameter-match?:  # type-parameter-name: (handle array byte), type: (addr type-tree), type-parameters: (addr table (handle array byte) (addr type-tree)) -> result/eax: boolean
    26529     # . prologue
    26530     55/push-ebp
    26531     89/<- %ebp 4/r32/esp
    26532     # . save registers
    26533     51/push-ecx
    26534     #
    26535     (get-or-insert-handle *(ebp+0x14)  *(ebp+8) *(ebp+0xc)  0xc)  # => eax
    26536     # if parameter wasn't saved, save it
    26537     {
    26538       81 7/subop/compare *eax 0/imm32
    26539       75/jump-if-!= break/disp8
    26540       8b/-> *(ebp+0x10) 1/r32/ecx
    26541       89/<- *eax 1/r32/ecx
    26542     }
    26543     #
    26544     (type-equal? *(ebp+0x10) *eax)  # => eax
    26545 $type-parameter-match?:end:
    26546     # . restore registers
    26547     59/pop-to-ecx
    26548     # . epilogue
    26549     89/<- %esp 5/r32/ebp
    26550     5d/pop-to-ebp
    26551     c3/return
    26552
    26553 size-of:  # v: (addr var) -> result/eax: int
    26554     # . prologue
    26555     55/push-ebp
    26556     89/<- %ebp 4/r32/esp
    26557     # . save registers
    26558     51/push-ecx
    26559     # var t/ecx: (addr type-tree) = lookup(v->type)
    26560     8b/-> *(ebp+8) 1/r32/ecx
    26561 #?     (write-buffered Stderr "size-of ")
    26562 #?     (write-int32-hex-buffered Stderr %ecx)
    26563 #?     (write-buffered Stderr Newline)
    26564 #?     (write-buffered Stderr "type allocid: ")
    26565 #?     (write-int32-hex-buffered Stderr *(ecx+8))
    26566 #?     (write-buffered Stderr Newline)
    26567 #?     (flush Stderr)
    26568     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
    26569     89/<- %ecx 0/r32/eax
    26570     # if mu-array?(t) return size-of-array(t)
    26571     {
    26572       (mu-array? %ecx)  # => eax
    26573       3d/compare-eax-and 0/imm32/false
    26574       74/jump-if-= break/disp8
    26575       (size-of-array %ecx)  # => eax
    26576       eb/jump $size-of:end/disp8
    26577     }
    26578     # if mu-stream?(t) return size-of-stream(t)
    26579     {
    26580       (mu-stream? %ecx)  # => eax
    26581       3d/compare-eax-and 0/imm32/false
    26582       74/jump-if-= break/disp8
    26583       (size-of-stream %ecx)  # => eax
    26584       eb/jump $size-of:end/disp8
    26585     }
    26586     # if (!t->is-atom?) t = lookup(t->left)
    26587     {
    26588       81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
    26589       75/jump-if-!= break/disp8
    26590       (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
    26591       89/<- %ecx 0/r32/eax
    26592     }
    26593     # TODO: assert t->is-atom?
    26594     (size-of-type-id *(ecx+4))  # Type-tree-value => eax
    26595 $size-of:end:
    26596     # . restore registers
    26597     59/pop-to-ecx
    26598     # . epilogue
    26599     89/<- %esp 5/r32/ebp
    26600     5d/pop-to-ebp
    26601     c3/return
    26602
    26603 size-of-deref:  # v: (addr var) -> result/eax: int
    26604     # . prologue
    26605     55/push-ebp
    26606     89/<- %ebp 4/r32/esp
    26607     # . save registers
    26608     51/push-ecx
    26609     # var t/ecx: (addr type-tree) = lookup(v->type)
    26610     8b/-> *(ebp+8) 1/r32/ecx
    26611     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
    26612     89/<- %ecx 0/r32/eax
    26613     # TODO: assert(t is an addr)
    26614     # t = lookup(t->right)
    26615     (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
    26616     89/<- %ecx 0/r32/eax
    26617     # if mu-array?(t) return size-of-array(t)
    26618     {
    26619       (mu-array? %ecx)  # => eax
    26620       3d/compare-eax-and 0/imm32/false
    26621       74/jump-if-= break/disp8
    26622       (size-of-array %ecx)  # => eax
    26623       eb/jump $size-of-deref:end/disp8
    26624     }
    26625     # if mu-stream?(t) return size-of-stream(t)
    26626     {
    26627       (mu-stream? %ecx)  # => eax
    26628       3d/compare-eax-and 0/imm32/false
    26629       74/jump-if-= break/disp8
    26630       (size-of-stream %ecx)  # => eax
    26631       eb/jump $size-of-deref:end/disp8
    26632     }
    26633     # if (!t->is-atom?) t = lookup(t->left)
    26634     {
    26635       81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
    26636       75/jump-if-!= break/disp8
    26637       (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
    26638       89/<- %ecx 0/r32/eax
    26639     }
    26640     # TODO: assert t->is-atom?
    26641     (size-of-type-id *(ecx+4))  # Type-tree-value => eax
    26642 $size-of-deref:end:
    26643     # . restore registers
    26644     59/pop-to-ecx
    26645     # . epilogue
    26646     89/<- %esp 5/r32/ebp
    26647     5d/pop-to-ebp
    26648     c3/return
    26649
    26650 mu-array?:  # t: (addr type-tree) -> result/eax: boolean
    26651     # . prologue
    26652     55/push-ebp
    26653     89/<- %ebp 4/r32/esp
    26654     # . save registers
    26655     51/push-ecx
    26656     # ecx = t
    26657     8b/-> *(ebp+8) 1/r32/ecx
    26658     # if t->is-atom?, return false
    26659     81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
    26660     75/jump-if-!= $mu-array?:return-false/disp8
    26661     # if !t->left->is-atom?, return false
    26662     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
    26663     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
    26664     74/jump-if-= $mu-array?:return-false/disp8
    26665     # return t->left->value == array
    26666     81 7/subop/compare *(eax+4) 3/imm32/array-type-id  # Type-tree-value
    26667     0f 94/set-if-= %al
    26668     81 4/subop/and %eax 0xff/imm32
    26669     eb/jump $mu-array?:end/disp8
    26670 $mu-array?:return-false:
    26671     b8/copy-to-eax 0/imm32/false
    26672 $mu-array?:end:
    26673     # . restore registers
    26674     59/pop-to-ecx
    26675     # . epilogue
    26676     89/<- %esp 5/r32/ebp
    26677     5d/pop-to-ebp
    26678     c3/return
    26679
    26680 # size of a statically allocated array where the size is part of the type expression
    26681 size-of-array:  # a: (addr type-tree) -> result/eax: int
    26682     # . prologue
    26683     55/push-ebp
    26684     89/<- %ebp 4/r32/esp
    26685     # . save registers
    26686     51/push-ecx
    26687     52/push-edx
    26688     #
    26689     8b/-> *(ebp+8) 1/r32/ecx
    26690     # TODO: assert that a->left is 'array'
    26691     (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
    26692     89/<- %ecx 0/r32/eax
    26693     # var elem-type/edx: type-id = a->right->left->value
    26694     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
    26695     8b/-> *(eax+4) 2/r32/edx  # Type-tree-value
    26696     # TODO: assert that a->right->right->left->value == size
    26697     # var array-size/ecx: int = a->right->right->left->value-size
    26698     (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
    26699     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    26700     8b/-> *(eax+8) 1/r32/ecx  # Type-tree-value-size
    26701     # return 4 + array-size * size-of(elem-type)
    26702     (size-of-type-id-as-array-element %edx)  # => eax
    26703     f7 4/subop/multiply-into-edx-eax %ecx
    26704     05/add-to-eax 4/imm32  # for array size
    26705     # TODO: check edx for overflow
    26706 $size-of-array:end:
    26707     # . restore registers
    26708     5a/pop-to-edx
    26709     59/pop-to-ecx
    26710     # . epilogue
    26711     89/<- %esp 5/r32/ebp
    26712     5d/pop-to-ebp
    26713     c3/return
    26714
    26715 mu-stream?:  # t: (addr type-tree) -> result/eax: boolean
    26716     # . prologue
    26717     55/push-ebp
    26718     89/<- %ebp 4/r32/esp
    26719     # . save registers
    26720     51/push-ecx
    26721     # ecx = t
    26722     8b/-> *(ebp+8) 1/r32/ecx
    26723     # if t->is-atom?, return false
    26724     81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
    26725     75/jump-if-!= $mu-stream?:return-false/disp8
    26726     # if !t->left->is-atom?, return false
    26727     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
    26728     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
    26729     74/jump-if-= $mu-stream?:return-false/disp8
    26730     # return t->left->value == stream
    26731     81 7/subop/compare *(eax+4) 0xb/imm32/stream-type-id  # Type-tree-value
    26732     0f 94/set-if-= %al
    26733     81 4/subop/and %eax 0xff/imm32
    26734     eb/jump $mu-stream?:end/disp8
    26735 $mu-stream?:return-false:
    26736     b8/copy-to-eax 0/imm32/false
    26737 $mu-stream?:end:
    26738     # . restore registers
    26739     59/pop-to-ecx
    26740     # . epilogue
    26741     89/<- %esp 5/r32/ebp
    26742     5d/pop-to-ebp
    26743     c3/return
    26744
    26745 # size of a statically allocated stream where the size is part of the type expression
    26746 size-of-stream:  # a: (addr type-tree) -> result/eax: int
    26747     # . prologue
    26748     55/push-ebp
    26749     89/<- %ebp 4/r32/esp
    26750     #
    26751     (size-of-array *(ebp+8))  # assumes we ignore the actual type name 'array' in the type
    26752     05/add-to-eax 8/imm32  # for read/write pointers
    26753 $size-of-stream:end:
    26754     # . epilogue
    26755     89/<- %esp 5/r32/ebp
    26756     5d/pop-to-ebp
    26757     c3/return
    26758
    26759 size-of-type-id:  # t: type-id -> result/eax: int
    26760     # . prologue
    26761     55/push-ebp
    26762     89/<- %ebp 4/r32/esp
    26763     # . save registers
    26764     51/push-ecx
    26765     # var out/ecx: (handle typeinfo)
    26766     68/push 0/imm32
    26767     68/push 0/imm32
    26768     89/<- %ecx 4/r32/esp
    26769     # eax = t
    26770     8b/-> *(ebp+8) 0/r32/eax
    26771     # if t is a literal, return 0
    26772     3d/compare-eax-and 0/imm32
    26773     0f 84/jump-if-= $size-of-type-id:end/disp32  # eax changes type from type-id to int
    26774     # if t is a byte, return 4 (because we don't really support non-multiples of 4)
    26775     3d/compare-eax-and 8/imm32/byte
    26776     {
    26777       75/jump-if-!= break/disp8
    26778       b8/copy-to-eax 4/imm32
    26779       eb/jump $size-of-type-id:end/disp8
    26780     }
    26781     # if t is a handle, return 8
    26782     3d/compare-eax-and 4/imm32/handle
    26783     {
    26784       75/jump-if-!= break/disp8
    26785       b8/copy-to-eax 8/imm32
    26786       eb/jump $size-of-type-id:end/disp8  # eax changes type from type-id to int
    26787     }
    26788     # if t is a slice, return 8
    26789     3d/compare-eax-and 0xc/imm32/slice
    26790     {
    26791       75/jump-if-!= break/disp8
    26792       b8/copy-to-eax 8/imm32
    26793       eb/jump $size-of-type-id:end/disp8  # eax changes type from type-id to int
    26794     }
    26795     # if t is a user-defined type, return its size
    26796     # TODO: support non-atom type
    26797     (find-typeinfo %eax %ecx)
    26798     {
    26799       81 7/subop/compare *ecx 0/imm32
    26800       74/jump-if-= break/disp8
    26801 $size-of-type-id:user-defined:
    26802       (lookup *ecx *(ecx+4))  # => eax
    26803       8b/-> *(eax+0xc) 0/r32/eax  # Typeinfo-total-size-in-bytes
    26804       eb/jump $size-of-type-id:end/disp8
    26805     }
    26806     # otherwise return the word size
    26807     b8/copy-to-eax 4/imm32
    26808 $size-of-type-id:end:
    26809     # . reclaim locals
    26810     81 0/subop/add %esp 8/imm32
    26811     # . restore registers
    26812     59/pop-to-ecx
    26813     # . epilogue
    26814     89/<- %esp 5/r32/ebp
    26815     5d/pop-to-ebp
    26816     c3/return
    26817
    26818 # Minor violation of our type system since it returns an addr. But we could
    26819 # replace it with a handle some time.
    26820 # Returns null if t is an atom.
    26821 type-tail:  # t: (addr type-tree) -> out/eax: (addr type-tree)
    26822     # . prologue
    26823     55/push-ebp
    26824     89/<- %ebp 4/r32/esp
    26825     # . save registers
    26826     51/push-ecx
    26827     # eax = 0
    26828     b8/copy-to-eax 0/imm32
    26829     # ecx = t
    26830     8b/-> *(ebp+8) 1/r32/ecx
    26831 $type-tail:check-atom:
    26832     # if t->is-atom? return 0
    26833     81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
    26834     0f 85/jump-if-!= $type-tail:end/disp32
    26835     # var tail = t->right
    26836     (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
    26837     89/<- %ecx 0/r32/eax
    26838 $type-tail:check-singleton:
    26839     # if (tail->right == 0) return tail->left
    26840     {
    26841       81 7/subop/compare *(ecx+0xc) 0/imm32  # Type-tree-right
    26842       75/jump-if-!= break/disp8
    26843       (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
    26844       e9/jump $type-tail:end/disp32
    26845     }
    26846     # if tail->right->left is an array-capacity, return tail->left
    26847     {
    26848 $type-tail:check-array-capacity:
    26849       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
    26850       81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
    26851       75/jump-if-!= break/disp8
    26852 $type-tail:check-array-capacity-1:
    26853       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    26854       3d/compare-eax-and 0/imm32
    26855       74/jump-if-= break/disp8
    26856 $type-tail:check-array-capacity-2:
    26857       (simple-mu-type? %eax 9)  # array-capacity => eax
    26858       3d/compare-eax-and 0/imm32/false
    26859       74/jump-if-= break/disp8
    26860 $type-tail:array-capacity:
    26861       (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
    26862       eb/jump $type-tail:end/disp8
    26863     }
    26864 $type-tail:check-compound-left:
    26865     # if !tail->left->is-atom? return tail->left
    26866     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
    26867     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
    26868     74/jump-if-= $type-tail:end/disp8
    26869 $type-tail:return-tail:
    26870     # return tail
    26871     89/<- %eax 1/r32/ecx
    26872 $type-tail:end:
    26873     # . restore registers
    26874     59/pop-to-ecx
    26875     # . epilogue
    26876     89/<- %esp 5/r32/ebp
    26877     5d/pop-to-ebp
    26878     c3/return
    26879
    26880 type-equal?:  # a: (addr type-tree), b: (addr type-tree) -> result/eax: boolean
    26881     # . prologue
    26882     55/push-ebp
    26883     89/<- %ebp 4/r32/esp
    26884     # . save registers
    26885     51/push-ecx
    26886     52/push-edx
    26887     53/push-ebx
    26888     # ecx = a
    26889     8b/-> *(ebp+8) 1/r32/ecx
    26890     # edx = b
    26891     8b/-> *(ebp+0xc) 2/r32/edx
    26892 $type-equal?:compare-addr:
    26893     # if (a == b) return true
    26894     8b/-> %ecx 0/r32/eax  # Var-type
    26895     39/compare %edx 0/r32/eax  # Var-type
    26896     b8/copy-to-eax 1/imm32/true
    26897     0f 84/jump-if-= $type-equal?:end/disp32
    26898 $type-equal?:compare-null-a:
    26899     # if (a == 0) return false
    26900     b8/copy-to-eax 0/imm32/false
    26901     81 7/subop/compare %ecx 0/imm32
    26902     0f 84/jump-if-= $type-equal?:end/disp32
    26903 $type-equal?:compare-null-b:
    26904     # if (b == 0) return false
    26905     81 7/subop/compare %edx 0/imm32
    26906     0f 84/jump-if-= $type-equal?:end/disp32
    26907 $type-equal?:compare-atom-state:
    26908     # if (a->is-atom? != b->is-atom?) return false
    26909     8b/-> *ecx 3/r32/ebx  # Type-tree-is-atom
    26910     39/compare *edx 3/r32/ebx  # Type-tree-is-atom
    26911     b8/copy-to-eax 0/imm32/false
    26912     0f 85/jump-if-!= $type-equal?:end/disp32
    26913     # if a->is-atom? return (a->value == b->value)
    26914     {
    26915 $type-equal?:check-atom:
    26916       81 7/subop/compare %ebx 0/imm32/false
    26917       74/jump-if-= break/disp8
    26918 $type-equal?:is-atom:
    26919       8b/-> *(ecx+4) 0/r32/eax  # Type-tree-value
    26920       39/compare *(edx+4) 0/r32/eax  # Type-tree-value
    26921       0f 94/set-if-= %al
    26922       81 4/subop/and %eax 0xff/imm32
    26923       e9/jump $type-equal?:end/disp32
    26924     }
    26925 $type-equal?:check-left:
    26926     # if (!type-equal?(a->left, b->left)) return false
    26927     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
    26928     89/<- %ebx 0/r32/eax
    26929     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
    26930     (type-equal? %eax %ebx)  # => eax
    26931     3d/compare-eax-and 0/imm32/false
    26932     74/jump-if-= $type-equal?:end/disp8
    26933 $type-equal?:check-right:
    26934     # return type-equal?(a->right, b->right)
    26935     (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
    26936     89/<- %ebx 0/r32/eax
    26937     (lookup *(edx+0xc) *(edx+0x10))  # Type-tree-right Type-tree-right => eax
    26938     (type-equal? %eax %ebx)  # => eax
    26939 $type-equal?:end:
    26940     # . restore registers
    26941     5b/pop-to-ebx
    26942     5a/pop-to-edx
    26943     59/pop-to-ecx
    26944     # . epilogue
    26945     89/<- %esp 5/r32/ebp
    26946     5d/pop-to-ebp
    26947     c3/return
    26948
    26949 #######################################################
    26950 # Code-generation
    26951 #######################################################
    26952
    26953 == data
    26954
    26955 # Global state added to each var record when performing code-generation.
    26956 Curr-local-stack-offset:  # (addr int)
    26957     0/imm32
    26958
    26959 == code
    26960
    26961 # We may not need to pass err/ed everywhere here. I think they're relics of Mu
    26962 # getting type checks later in life.
    26963 # But we do need them for runtime checks, particularly array index bounds checks.
    26964 # So perhaps it's not worth taking them out. They're a safety net.
    26965
    26966 emit-subx:  # out: (addr buffered-file), err: (addr buffered-file), ed: (addr exit-descriptor)
    26967     # . prologue
    26968     55/push-ebp
    26969     89/<- %ebp 4/r32/esp
    26970     # . save registers
    26971     50/push-eax
    26972     # var curr/eax: (addr function) = *Program->functions
    26973     (lookup *_Program-functions *_Program-functions->payload)  # => eax
    26974     {
    26975       # if (curr == null) break
    26976       3d/compare-eax-and 0/imm32
    26977       0f 84/jump-if-= break/disp32
    26978       (emit-subx-function *(ebp+8) %eax *(ebp+0xc) *(ebp+0x10))
    26979       # curr = lookup(curr->next)
    26980       (lookup *(eax+0x20) *(eax+0x24))  # Function-next Function-next => eax
    26981       e9/jump loop/disp32
    26982     }
    26983 $emit-subx:end:
    26984     # . restore registers
    26985     58/pop-to-eax
    26986     # . epilogue
    26987     89/<- %esp 5/r32/ebp
    26988     5d/pop-to-ebp
    26989     c3/return
    26990
    26991 emit-subx-function:  # out: (addr buffered-file), f: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    26992     # . prologue
    26993     55/push-ebp
    26994     89/<- %ebp 4/r32/esp
    26995     # some preprocessing
    26996     (populate-mu-type-offsets-in-inouts *(ebp+0xc))
    26997     # . save registers
    26998     50/push-eax
    26999     51/push-ecx
    27000     52/push-edx
    27001     # initialize some global state
    27002     c7 0/subop/copy *Curr-block-depth 1/imm32  # Important: keep this in sync with the parse phase
    27003     c7 0/subop/copy *Curr-local-stack-offset 0/imm32
    27004     # ecx = f
    27005     8b/-> *(ebp+0xc) 1/r32/ecx
    27006     # var vars/edx: (stack (addr var) 256)
    27007     81 5/subop/subtract %esp 0xc00/imm32
    27008     68/push 0xc00/imm32/size
    27009     68/push 0/imm32/top
    27010     89/<- %edx 4/r32/esp
    27011     # var name/eax: (addr array byte) = lookup(f->name)
    27012     (lookup *ecx *(ecx+4))  # Function-name Function-name => eax
    27013     #
    27014     (write-buffered *(ebp+8) %eax)
    27015     (write-buffered *(ebp+8) ":\n")
    27016     (emit-subx-prologue *(ebp+8))
    27017     # var body/eax: (addr block) = lookup(f->body)
    27018     (lookup *(ecx+0x18) *(ecx+0x1c))  # Function-body Function-body => eax
    27019     #
    27020     (emit-subx-block *(ebp+8) %eax %edx *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    27021     (emit-subx-epilogue *(ebp+8))
    27022     # TODO: validate that *Curr-block-depth and *Curr-local-stack-offset have
    27023     # been cleaned up
    27024 $emit-subx-function:end:
    27025     # . reclaim locals
    27026     81 0/subop/add %esp 0xc08/imm32
    27027     # . restore registers
    27028     5a/pop-to-edx
    27029     59/pop-to-ecx
    27030     58/pop-to-eax
    27031     # . epilogue
    27032     89/<- %esp 5/r32/ebp
    27033     5d/pop-to-ebp
    27034     c3/return
    27035
    27036 populate-mu-type-offsets-in-inouts:  # f: (addr function)
    27037     # . prologue
    27038     55/push-ebp
    27039     89/<- %ebp 4/r32/esp
    27040     # . save registers
    27041     50/push-eax
    27042     51/push-ecx
    27043     52/push-edx
    27044     53/push-ebx
    27045     57/push-edi
    27046     # var next-offset/edx: int = 8
    27047     ba/copy-to-edx 8/imm32
    27048     # var curr/ecx: (addr list var) = lookup(f->inouts)
    27049     8b/-> *(ebp+8) 1/r32/ecx
    27050     (lookup *(ecx+8) *(ecx+0xc))  # Function-inouts Function-inouts => eax
    27051     89/<- %ecx 0/r32/eax
    27052     {
    27053 $populate-mu-type-offsets-in-inouts:loop:
    27054       81 7/subop/compare %ecx 0/imm32
    27055       74/jump-if-= break/disp8
    27056       # var v/ebx: (addr var) = lookup(curr->value)
    27057       (lookup *ecx *(ecx+4))  # List-value List-value => eax
    27058       89/<- %ebx 0/r32/eax
    27059 #?       (lookup *ebx *(ebx+4))
    27060 #?       (write-buffered Stderr "setting offset of fn inout ")
    27061 #?       (write-buffered Stderr %eax)
    27062 #?       (write-buffered Stderr "@")
    27063 #?       (write-int32-hex-buffered Stderr %ebx)
    27064 #?       (write-buffered Stderr " to ")
    27065 #?       (write-int32-hex-buffered Stderr %edx)
    27066 #?       (write-buffered Stderr Newline)
    27067 #?       (flush Stderr)
    27068       # v->offset = next-offset
    27069       89/<- *(ebx+0x14) 2/r32/edx  # Var-offset
    27070       # next-offset += size-of(v)
    27071       (size-of %ebx)  # => eax
    27072       01/add-to %edx 0/r32/eax
    27073       # curr = lookup(curr->next)
    27074       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
    27075       89/<- %ecx 0/r32/eax
    27076       #
    27077       eb/jump loop/disp8
    27078     }
    27079 $populate-mu-type-offsets-in-inouts:end:
    27080     # . restore registers
    27081     5f/pop-to-edi
    27082     5b/pop-to-ebx
    27083     5a/pop-to-edx
    27084     59/pop-to-ecx
    27085     58/pop-to-eax
    27086     # . epilogue
    27087     89/<- %esp 5/r32/ebp
    27088     5d/pop-to-ebp
    27089     c3/return
    27090
    27091 emit-subx-stmt-list:  # out: (addr buffered-file), stmts: (addr list stmt), vars: (addr stack live-var), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    27092     # . prologue
    27093     55/push-ebp
    27094     89/<- %ebp 4/r32/esp
    27095     # . save registers
    27096     50/push-eax
    27097     51/push-ecx
    27098     53/push-ebx
    27099     56/push-esi
    27100     # esi = stmts
    27101     8b/-> *(ebp+0xc) 6/r32/esi
    27102     #
    27103     {
    27104 $emit-subx-stmt-list:loop:
    27105       81 7/subop/compare %esi 0/imm32
    27106       0f 84/jump-if-= break/disp32
    27107       # var curr-stmt/ecx: (addr stmt) = lookup(stmts->value)
    27108       (lookup *esi *(esi+4))  # List-value List-value => eax
    27109       89/<- %ecx 0/r32/eax
    27110       {
    27111 $emit-subx-stmt-list:check-for-block:
    27112         81 7/subop/compare *ecx 0/imm32/block  # Stmt-tag
    27113         75/jump-if-!= break/disp8
    27114 $emit-subx-stmt-list:block:
    27115         (emit-subx-block *(ebp+8) %ecx *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
    27116       }
    27117       {
    27118 $emit-subx-stmt-list:check-for-stmt:
    27119         81 7/subop/compare *ecx 1/imm32/stmt1  # Stmt-tag
    27120         0f 85/jump-if-!= break/disp32
    27121 $emit-subx-stmt-list:stmt1:
    27122         {
    27123           (mu-branch? %ecx)  # => eax
    27124           3d/compare-eax-and 0/imm32/false
    27125           0f 84/jump-if-= break/disp32
    27126 $emit-subx-stmt-list:branch-stmt:
    27127 +-- 25 lines: # unconditional return ----------------------------------------------------------------------------------------------------------------------------------------------------
    27152 +-- 27 lines: # unconditional loops -----------------------------------------------------------------------------------------------------------------------------------------------------
    27179 +-- 16 lines: # unconditional breaks ----------------------------------------------------------------------------------------------------------------------------------------------------
    27195 +-- 38 lines: # simple conditional branches without a target ----------------------------------------------------------------------------------------------------------------------------
    27233 +-- 19 lines: # conditional branches with an explicit target ----------------------------------------------------------------------------------------------------------------------------
    27252         }
    27253 $emit-subx-stmt-list:1-to-1:
    27254         (emit-subx-stmt *(ebp+8) %ecx Primitives *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
    27255         e9/jump $emit-subx-stmt-list:continue/disp32
    27256       }
    27257       {
    27258 $emit-subx-stmt-list:check-for-var-def:
    27259         81 7/subop/compare *ecx 2/imm32/var-def  # Stmt-tag
    27260         75/jump-if-!= break/disp8
    27261 $emit-subx-stmt-list:var-def:
    27262         (emit-subx-var-def *(ebp+8) %ecx *(ebp+0x18) *(ebp+0x1c))
    27263         (push *(ebp+0x10) *(ecx+4))  # Vardef-var
    27264         (push *(ebp+0x10) *(ecx+8))  # Vardef-var
    27265         (push *(ebp+0x10) 0)  # Live-var-register-spilled = 0 for vars on the stack
    27266         #
    27267         eb/jump $emit-subx-stmt-list:continue/disp8
    27268       }
    27269       {
    27270 $emit-subx-stmt-list:check-for-reg-var-def:
    27271         81 7/subop/compare *ecx 3/imm32/reg-var-def  # Stmt-tag
    27272         0f 85/jump-if-!= break/disp32
    27273 $emit-subx-stmt-list:reg-var-def:
    27274         # TODO: ensure that there's exactly one output
    27275         (push-output-and-maybe-emit-spill *(ebp+8) %ecx *(ebp+0x10) %esi *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
    27276         # emit the instruction as usual
    27277         (emit-subx-stmt *(ebp+8) %ecx Primitives *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
    27278         #
    27279         eb/jump $emit-subx-stmt-list:continue/disp8
    27280       }
    27281 $emit-subx-stmt-list:continue:
    27282       # TODO: raise an error on unrecognized Stmt-tag
    27283       (lookup *(esi+8) *(esi+0xc))  # List-next List-next => eax
    27284       89/<- %esi 0/r32/eax
    27285       e9/jump loop/disp32
    27286     }
    27287 $emit-subx-stmt-list:emit-cleanup:
    27288     (emit-cleanup-code-until-depth *(ebp+8) *(ebp+0x10) *Curr-block-depth)
    27289 $emit-subx-stmt-list:clean-up:
    27290     (clean-up-stack-offset-state *(ebp+0x10) *Curr-block-depth)
    27291     (clean-up-blocks *(ebp+0x10) *Curr-block-depth *(ebp+0x14))
    27292 $emit-subx-stmt-list:end:
    27293     # . restore registers
    27294     5e/pop-to-esi
    27295     5b/pop-to-ebx
    27296     59/pop-to-ecx
    27297     58/pop-to-eax
    27298     # . epilogue
    27299     89/<- %esp 5/r32/ebp
    27300     5d/pop-to-ebp
    27301     c3/return
    27302
    27303 # 'later-stmts' includes 'stmt', but will behave the same even without it; reg-var-def stmts are guaranteed not to write to function outputs.
    27304 push-output-and-maybe-emit-spill:  # out: (addr buffered-file), stmt: (addr reg-var-def), vars: (addr stack (handle var)), later-stmts: (addr list stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    27305     # . prologue
    27306     55/push-ebp
    27307     89/<- %ebp 4/r32/esp
    27308     # . save registers
    27309     50/push-eax
    27310     51/push-ecx
    27311     52/push-edx
    27312     # ecx = stmt
    27313     8b/-> *(ebp+0xc) 1/r32/ecx
    27314     # var sv/eax: (addr stmt-var) = lookup(curr-stmt->outputs)
    27315     (lookup *(ecx+0x14) *(ecx+0x18))  # Regvardef-outputs Regvardef-outputs => eax
    27316     # TODO: assert !sv->is-deref?
    27317     # var v/ecx: (addr var) = lookup(sv->value)
    27318     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    27319     89/<- %ecx 0/r32/eax
    27320     # v->block-depth = *Curr-block-depth
    27321     8b/-> *Curr-block-depth 0/r32/eax
    27322     89/<- *(ecx+0x10) 0/r32/eax  # Var-block-depth
    27323 #?     (write-buffered Stderr "var ")
    27324 #?     (lookup *ecx *(ecx+4))
    27325 #?     (write-buffered Stderr %eax)
    27326 #?     (write-buffered Stderr " at depth ")
    27327 #?     (write-int32-hex-buffered Stderr *(ecx+0x10))
    27328 #?     (write-buffered Stderr Newline)
    27329 #?     (flush Stderr)
    27330     # ensure that v is in a register
    27331     81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
    27332     0f 84/jump-if-= $push-output-and-maybe-emit-spill:abort/disp32
    27333     # var emit-spill?/edx: boolean = not-yet-spilled-this-block? && will-not-write-some-register?(fn)
    27334     (not-yet-spilled-this-block? %ecx *(ebp+0x10))  # => eax
    27335     89/<- %edx 0/r32/eax
    27336     3d/compare-eax-and 0/imm32/false
    27337     0f 84/jump-if-= $push-output-and-maybe-emit-spill:push/disp32
    27338     (will-not-write-some-register? %ecx *(ebp+0x14) *(ebp+0x18))  # => eax
    27339     89/<- %edx 0/r32/eax
    27340     # check emit-spill?
    27341     3d/compare-eax-and 0/imm32/false
    27342     0f 84/jump-if-= $push-output-and-maybe-emit-spill:push/disp32
    27343     # TODO: assert(size-of(output) == 4)
    27344     # *Curr-local-stack-offset -= 4
    27345     81 5/subop/subtract *Curr-local-stack-offset 4/imm32
    27346     # emit spill
    27347     (lookup *(ecx+0x18) *(ecx+0x1c))  # Var-register Var-register => eax
    27348     (emit-push-register *(ebp+8) %eax)
    27349 $push-output-and-maybe-emit-spill:push:
    27350     8b/-> *(ebp+0xc) 1/r32/ecx
    27351     (lookup *(ecx+0x14) *(ecx+0x18))  # Regvardef-outputs Regvardef-outputs => eax
    27352     # push(vars, {sv->value, emit-spill?})
    27353     (push *(ebp+0x10) *eax)  # Stmt-var-value
    27354     (push *(ebp+0x10) *(eax+4))  # Stmt-var-value
    27355     (push *(ebp+0x10) %edx)
    27356 $push-output-and-maybe-emit-spill:end:
    27357     # . restore registers
    27358     5a/pop-to-edx
    27359     59/pop-to-ecx
    27360     58/pop-to-eax
    27361     # . epilogue
    27362     89/<- %esp 5/r32/ebp
    27363     5d/pop-to-ebp
    27364     c3/return
    27365
    27366 $push-output-and-maybe-emit-spill:abort:
    27367     # error("var '" var->name "' initialized from an instruction must live in a register\n")
    27368     (write-buffered *(ebp+0x1c) "var '")
    27369     (write-buffered *(ebp+0x1c) *eax)  # Var-name
    27370     (write-buffered *(ebp+0x1c) "' initialized from an instruction must live in a register\n")
    27371     (flush *(ebp+0x1c))
    27372     (stop *(ebp+0x20) 1)
    27373     # never gets here
    27374
    27375 emit-subx-cleanup-and-unconditional-nonlocal-branch:  # out: (addr buffered-file), stmt: (addr stmt1), vars: (addr stack live-var)
    27376     # . prologue
    27377     55/push-ebp
    27378     89/<- %ebp 4/r32/esp
    27379     # . save registers
    27380     50/push-eax
    27381     51/push-ecx
    27382     # ecx = stmt
    27383     8b/-> *(ebp+0xc) 1/r32/ecx
    27384     # var target/eax: (addr array byte) = curr-stmt->inouts->value->name
    27385     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    27386     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    27387     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    27388     # clean up until target block
    27389     (emit-cleanup-code-until-target *(ebp+8) *(ebp+0x10) %eax)
    27390     # emit jump to target block
    27391     (emit-indent *(ebp+8) *Curr-block-depth)
    27392     (write-buffered *(ebp+8) "e9/jump ")
    27393     (write-buffered *(ebp+8) %eax)
    27394     (lookup *(ecx+4) *(ecx+8))  # Stmt1-operation Stmt1-operation => eax
    27395     (string-starts-with? %eax "break")
    27396     3d/compare-eax-and 0/imm32/false
    27397     {
    27398       74/jump-if-= break/disp8
    27399       (write-buffered *(ebp+8) ":break/disp32\n")
    27400       eb/jump $emit-subx-cleanup-and-unconditional-nonlocal-branch:end/disp8
    27401     }
    27402     (write-buffered *(ebp+8) ":loop/disp32\n")
    27403 $emit-subx-cleanup-and-unconditional-nonlocal-branch:end:
    27404     # . restore registers
    27405     59/pop-to-ecx
    27406     58/pop-to-eax
    27407     # . epilogue
    27408     89/<- %esp 5/r32/ebp
    27409     5d/pop-to-ebp
    27410     c3/return
    27411
    27412 emit-outputs:  # out: (addr buffered-file), return-stmt: (addr stmt1), fn: (addr function)
    27413     # . prologue
    27414     55/push-ebp
    27415     89/<- %ebp 4/r32/esp
    27416     # . save registers
    27417     50/push-eax
    27418     51/push-ecx
    27419     56/push-esi
    27420     57/push-edi
    27421     # var curr-inout/esi: (addr stmt-var) = return-stmt->inouts
    27422     8b/-> *(ebp+0xc) 0/r32/eax
    27423     (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    27424     89/<- %esi 0/r32/eax
    27425     # var curr-output/edi: (addr list var) = fn->outputs
    27426     8b/-> *(ebp+0x10) 0/r32/eax
    27427     (lookup *(eax+0x10) *(eax+0x14))  # Function-outputs Function-outputs => eax
    27428     89/<- %edi 0/r32/eax
    27429     {
    27430 $emit-outputs:loop:
    27431       81 7/subop/compare %esi 0/imm32
    27432       0f 84/jump-if-= break/disp32
    27433       # emit copy to output register
    27434       # var curr-output-register/ecx: (addr array byte) = curr-output->value->register
    27435       (lookup *edi *(edi+4))  # List-value List-value => eax
    27436       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    27437       89/<- %ecx 0/r32/eax
    27438       # if curr-output-register starts with "x", emit a floating-point copy
    27439       8a/copy-byte *(ecx+4) 0/r32/AL
    27440       81 4/subop/and %eax 0xff/imm32
    27441       3d/compare-eax-and 0x78/imm32/x
    27442       {
    27443         75/jump-if-!= break/disp8
    27444         (emit-float-output *(ebp+8) %esi %ecx)
    27445         eb/jump $emit-outputs:continue/disp8
    27446       }
    27447       # otherwise emit an int copy
    27448       (emit-int-output *(ebp+8) %esi %ecx)
    27449 $emit-outputs:continue:
    27450       # curr-inout = curr-inout->next
    27451       (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
    27452       89/<- %esi 0/r32/eax
    27453       # curr-output = curr-output->next
    27454       (lookup *(edi+8) *(edi+0xc))  # List-next List-next => eax
    27455       89/<- %edi 0/r32/eax
    27456       #
    27457       e9/jump loop/disp32
    27458     }
    27459 $emit-outputs:end:
    27460     # . restore registers
    27461     5f/pop-to-edi
    27462     5e/pop-to-esi
    27463     59/pop-to-ecx
    27464     58/pop-to-eax
    27465     # . epilogue
    27466     89/<- %esp 5/r32/ebp
    27467     5d/pop-to-ebp
    27468     c3/return
    27469
    27470 emit-int-output:  # out: (addr buffered-file), return-var: (addr stmt-var), dest-reg: (addr array byte)
    27471     # . prologue
    27472     55/push-ebp
    27473     89/<- %ebp 4/r32/esp
    27474     # . save registers
    27475     50/push-eax
    27476     51/push-ecx
    27477     # ecx = return-var->value
    27478     8b/-> *(ebp+0xc) 0/r32/eax
    27479     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    27480     89/<- %ecx 0/r32/eax
    27481     # if curr-var is a literal, emit copy of a literal to the output
    27482     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
    27483     (simple-mu-type? %eax 0)  # literal => eax
    27484     {
    27485       3d/compare-eax-and 0/imm32/false
    27486       0f 84/jump-if-= break/disp32
    27487       (emit-indent *(ebp+8) *Curr-block-depth)
    27488       (write-buffered *(ebp+8) "c7 0/subop/copy %")
    27489       (write-buffered *(ebp+8) *(ebp+0x10))
    27490       (write-buffered *(ebp+8) " ")
    27491       (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    27492       (write-buffered *(ebp+8) %eax)
    27493       (write-buffered *(ebp+8) "/imm32\n")
    27494       e9/jump $emit-int-output:end/disp32
    27495     }
    27496     # otherwise emit an integer copy
    27497     (emit-indent *(ebp+8) *Curr-block-depth)
    27498     (write-buffered *(ebp+8) "8b/->")
    27499     (emit-subx-var-as-rm32 *(ebp+8) *(ebp+0xc))
    27500     (write-buffered *(ebp+8) " ")
    27501     (get Mu-registers *(ebp+0x10) 0xc "Mu-registers")  # => eax
    27502     (write-int32-hex-buffered *(ebp+8) *eax)
    27503     (write-buffered *(ebp+8) "/r32\n")
    27504 $emit-int-output:end:
    27505     # . restore registers
    27506     59/pop-to-ecx
    27507     58/pop-to-eax
    27508     # . epilogue
    27509     89/<- %esp 5/r32/ebp
    27510     5d/pop-to-ebp
    27511     c3/return
    27512
    27513 emit-float-output:  # out: (addr buffered-file), return-var: (addr stmt-var), dest-reg: (addr array byte)
    27514     # . prologue
    27515     55/push-ebp
    27516     89/<- %ebp 4/r32/esp
    27517     # . save registers
    27518     50/push-eax
    27519     #
    27520     (emit-indent *(ebp+8) *Curr-block-depth)
    27521     (write-buffered *(ebp+8) "f3 0f 10/->")
    27522     (emit-subx-var-as-rm32 *(ebp+8) *(ebp+0xc))
    27523     (write-buffered *(ebp+8) " ")
    27524     (get Mu-registers *(ebp+0x10) 0xc "Mu-registers")  # => eax
    27525     (write-int32-hex-buffered *(ebp+8) *eax)
    27526     (write-buffered *(ebp+8) "/x32\n")
    27527 $emit-float-output:end:
    27528     # . restore registers
    27529     58/pop-to-eax
    27530     # . epilogue
    27531     89/<- %esp 5/r32/ebp
    27532     5d/pop-to-ebp
    27533     c3/return
    27534
    27535 mu-branch?:  # stmt: (addr stmt1) -> result/eax: boolean
    27536     # . prologue
    27537     55/push-ebp
    27538     89/<- %ebp 4/r32/esp
    27539     # . save registers
    27540     51/push-ecx
    27541     # ecx = lookup(stmt->operation)
    27542     8b/-> *(ebp+8) 1/r32/ecx
    27543     (lookup *(ecx+4) *(ecx+8))  # Stmt1-operation Stmt1-operation => eax
    27544     89/<- %ecx 0/r32/eax
    27545     # if (stmt->operation starts with "loop") return true
    27546     (string-starts-with? %ecx "loop")  # => eax
    27547     3d/compare-eax-and 0/imm32/false
    27548     75/jump-if-not-equal $mu-branch?:end/disp8
    27549     # if (stmt->operation starts with "break") return true
    27550     (string-starts-with? %ecx "break")  # => eax
    27551     3d/compare-eax-and 0/imm32/false
    27552     75/jump-if-not-equal $mu-branch?:end/disp8
    27553     # otherwise return (stmt->operation starts with "return")
    27554     (string-starts-with? %ecx "return")  # => eax
    27555 $mu-branch?:end:
    27556     # . restore registers
    27557     59/pop-to-ecx
    27558     # . epilogue
    27559     89/<- %esp 5/r32/ebp
    27560     5d/pop-to-ebp
    27561     c3/return
    27562
    27563 emit-reverse-break:  # out: (addr buffered-file), stmt: (addr stmt1)
    27564     # . prologue
    27565     55/push-ebp
    27566     89/<- %ebp 4/r32/esp
    27567     # . save registers
    27568     50/push-eax
    27569     # eax = stmt
    27570     8b/-> *(ebp+0xc) 0/r32/eax
    27571     #
    27572     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
    27573     (get Reverse-branch %eax 0x10 "reverse-branch: ")  # => eax: (addr handle array byte)
    27574     (emit-indent *(ebp+8) *Curr-block-depth)
    27575     (lookup *eax *(eax+4))  # => eax
    27576     (write-buffered *(ebp+8) %eax)
    27577     (write-buffered *(ebp+8) " break/disp32\n")
    27578 $emit-reverse-break:end:
    27579     # . restore registers
    27580     58/pop-to-eax
    27581     # . epilogue
    27582     89/<- %esp 5/r32/ebp
    27583     5d/pop-to-ebp
    27584     c3/return
    27585
    27586 == data
    27587
    27588 # Table from Mu branch instructions to the reverse SubX opcodes for them.
    27589 Reverse-branch:  # (table (handle array byte) (handle array byte))
    27590   # a table is a stream
    27591   0x1c0/imm32/write
    27592   0/imm32/read
    27593   0x1c0/imm32/size
    27594   # data
    27595   0x11/imm32/alloc-id   _string-break-if-=/imm32                0x11/imm32/alloc-id   _string_0f_85_jump_label/imm32
    27596   0x11/imm32/alloc-id   _string-loop-if-=/imm32                 0x11/imm32/alloc-id   _string_0f_85_jump_label/imm32
    27597   0x11/imm32/alloc-id   _string-break-if-!=/imm32               0x11/imm32/alloc-id   _string_0f_84_jump_label/imm32
    27598   0x11/imm32/alloc-id   _string-loop-if-!=/imm32                0x11/imm32/alloc-id   _string_0f_84_jump_label/imm32
    27599   0x11/imm32/alloc-id   _string-break-if-</imm32                0x11/imm32/alloc-id   _string_0f_8d_jump_label/imm32
    27600   0x11/imm32/alloc-id   _string-loop-if-</imm32                 0x11/imm32/alloc-id   _string_0f_8d_jump_label/imm32
    27601   0x11/imm32/alloc-id   _string-break-if->/imm32                0x11/imm32/alloc-id   _string_0f_8e_jump_label/imm32
    27602   0x11/imm32/alloc-id   _string-loop-if->/imm32                 0x11/imm32/alloc-id   _string_0f_8e_jump_label/imm32
    27603   0x11/imm32/alloc-id   _string-break-if-<=/imm32               0x11/imm32/alloc-id   _string_0f_8f_jump_label/imm32
    27604   0x11/imm32/alloc-id   _string-loop-if-<=/imm32                0x11/imm32/alloc-id   _string_0f_8f_jump_label/imm32
    27605   0x11/imm32/alloc-id   _string-break-if->=/imm32               0x11/imm32/alloc-id   _string_0f_8c_jump_label/imm32
    27606   0x11/imm32/alloc-id   _string-loop-if->=/imm32                0x11/imm32/alloc-id   _string_0f_8c_jump_label/imm32
    27607   0x11/imm32/alloc-id   _string-break-if-addr</imm32            0x11/imm32/alloc-id   _string_0f_83_jump_label/imm32
    27608   0x11/imm32/alloc-id   _string-loop-if-addr</imm32             0x11/imm32/alloc-id   _string_0f_83_jump_label/imm32
    27609   0x11/imm32/alloc-id   _string-break-if-addr>/imm32            0x11/imm32/alloc-id   _string_0f_86_jump_label/imm32
    27610   0x11/imm32/alloc-id   _string-loop-if-addr>/imm32             0x11/imm32/alloc-id   _string_0f_86_jump_label/imm32
    27611   0x11/imm32/alloc-id   _string-break-if-addr<=/imm32           0x11/imm32/alloc-id   _string_0f_87_jump_label/imm32
    27612   0x11/imm32/alloc-id   _string-loop-if-addr<=/imm32            0x11/imm32/alloc-id   _string_0f_87_jump_label/imm32
    27613   0x11/imm32/alloc-id   _string-break-if-addr>=/imm32           0x11/imm32/alloc-id   _string_0f_82_jump_label/imm32
    27614   0x11/imm32/alloc-id   _string-loop-if-addr>=/imm32            0x11/imm32/alloc-id   _string_0f_82_jump_label/imm32
    27615   0x11/imm32/alloc-id   _string-break-if-float</imm32           0x11/imm32/alloc-id   _string_0f_83_jump_label/imm32
    27616   0x11/imm32/alloc-id   _string-loop-if-float</imm32            0x11/imm32/alloc-id   _string_0f_83_jump_label/imm32
    27617   0x11/imm32/alloc-id   _string-break-if-float>/imm32           0x11/imm32/alloc-id   _string_0f_86_jump_label/imm32
    27618   0x11/imm32/alloc-id   _string-loop-if-float>/imm32            0x11/imm32/alloc-id   _string_0f_86_jump_label/imm32
    27619   0x11/imm32/alloc-id   _string-break-if-float<=/imm32          0x11/imm32/alloc-id   _string_0f_87_jump_label/imm32
    27620   0x11/imm32/alloc-id   _string-loop-if-float<=/imm32           0x11/imm32/alloc-id   _string_0f_87_jump_label/imm32
    27621   0x11/imm32/alloc-id   _string-break-if-float>=/imm32          0x11/imm32/alloc-id   _string_0f_82_jump_label/imm32
    27622   0x11/imm32/alloc-id   _string-loop-if-float>=/imm32           0x11/imm32/alloc-id   _string_0f_82_jump_label/imm32
    27623
    27624 == code
    27625
    27626 emit-unconditional-jump-to-depth:  # out: (addr buffered-file), vars: (addr stack live-var), depth: int, label-suffix: (addr array byte)
    27627     # . prologue
    27628     55/push-ebp
    27629     89/<- %ebp 4/r32/esp
    27630     # . save registers
    27631     50/push-eax
    27632     51/push-ecx
    27633     52/push-edx
    27634     53/push-ebx
    27635     56/push-esi
    27636     # ecx = vars
    27637     8b/-> *(ebp+0xc) 1/r32/ecx
    27638     # var eax: int = vars->top
    27639     8b/-> *ecx 0/r32/eax
    27640     # var curr/esi: (addr handle var) = &vars->data[vars->top - 12]
    27641     8d/copy-address *(ecx+eax-4) 6/r32/esi  # vars + 8 + vars->top - 12/Live-var-size
    27642     # var min/ecx: (addr handle var) = vars->data
    27643     8d/copy-address *(ecx+8) 1/r32/ecx
    27644     # edx = depth
    27645     8b/-> *(ebp+0x10) 2/r32/edx
    27646     {
    27647 $emit-unconditional-jump-to-depth:loop:
    27648       # if (curr < min) break
    27649       39/compare %esi 1/r32/ecx
    27650       0f 82/jump-if-addr< break/disp32
    27651       # var v/ebx: (addr var) = lookup(*curr)
    27652       (lookup *esi *(esi+4))  # => eax
    27653       89/<- %ebx 0/r32/eax
    27654       # if (v->block-depth < until-block-depth) break
    27655       39/compare *(ebx+0x10) 2/r32/edx  # Var-block-depth
    27656       0f 8c/jump-if-< break/disp32
    27657       {
    27658 $emit-unconditional-jump-to-depth:check:
    27659         # if v->block-depth != until-block-depth, continue
    27660         39/compare *(ebx+0x10) 2/r32/edx  # Var-block-depth
    27661         0f 85/jump-if-!= break/disp32
    27662 $emit-unconditional-jump-to-depth:depth-found:
    27663         # if v is not a literal, continue
    27664         (size-of %ebx)  # => eax
    27665         3d/compare-eax-and 0/imm32
    27666         0f 85/jump-if-!= break/disp32
    27667 $emit-unconditional-jump-to-depth:label-found:
    27668         # emit unconditional jump, then return
    27669         (emit-indent *(ebp+8) *Curr-block-depth)
    27670         (write-buffered *(ebp+8) "e9/jump ")
    27671         (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
    27672         (write-buffered *(ebp+8) %eax)
    27673         (write-buffered *(ebp+8) ":")
    27674         (write-buffered *(ebp+8) *(ebp+0x14))
    27675         (write-buffered *(ebp+8) "/disp32\n")
    27676         eb/jump $emit-unconditional-jump-to-depth:end/disp8
    27677       }
    27678       # curr -= 12
    27679       81 5/subop/subtract %esi 0xc/imm32
    27680       e9/jump loop/disp32
    27681     }
    27682     # TODO: error if no label at 'depth' was found
    27683 $emit-unconditional-jump-to-depth:end:
    27684     # . restore registers
    27685     5e/pop-to-esi
    27686     5b/pop-to-ebx
    27687     5a/pop-to-edx
    27688     59/pop-to-ecx
    27689     58/pop-to-eax
    27690     # . epilogue
    27691     89/<- %esp 5/r32/ebp
    27692     5d/pop-to-ebp
    27693     c3/return
    27694
    27695 # emit clean-up code for 'vars' until some block depth
    27696 # doesn't actually modify 'vars' so we need traverse manually inside the stack
    27697 emit-cleanup-code-until-depth:  # out: (addr buffered-file), vars: (addr stack live-var), until-block-depth: int
    27698     # . prologue
    27699     55/push-ebp
    27700     89/<- %ebp 4/r32/esp
    27701     # . save registers
    27702     50/push-eax
    27703     51/push-ecx
    27704     52/push-edx
    27705     53/push-ebx
    27706     56/push-esi
    27707 #?     (write-buffered Stderr "--- cleanup\n")
    27708 #?     (flush Stderr)
    27709     # ecx = vars
    27710     8b/-> *(ebp+0xc) 1/r32/ecx
    27711     # var esi: int = vars->top
    27712     8b/-> *ecx 6/r32/esi
    27713     # var curr/esi: (addr handle var) = &vars->data[vars->top - 12]
    27714     8d/copy-address *(ecx+esi-4) 6/r32/esi  # vars + 8 + vars->top - 12/Live-var-size
    27715     # var min/ecx: (addr handle var) = vars->data
    27716     81 0/subop/add %ecx 8/imm32
    27717     # edx = until-block-depth
    27718     8b/-> *(ebp+0x10) 2/r32/edx
    27719     {
    27720 $emit-cleanup-code-until-depth:loop:
    27721       # if (curr < min) break
    27722       39/compare %esi 1/r32/ecx
    27723       0f 82/jump-if-addr< break/disp32
    27724       # var v/ebx: (addr var) = lookup(*curr)
    27725       (lookup *esi *(esi+4))  # => eax
    27726       89/<- %ebx 0/r32/eax
    27727 #?       (lookup *ebx *(ebx+4))  # Var-name
    27728 #?       (write-buffered Stderr "var ")
    27729 #?       (write-buffered Stderr %eax)
    27730 #?       (write-buffered Stderr Newline)
    27731 #?       (flush Stderr)
    27732       # if (v->block-depth < until-block-depth) break
    27733       39/compare *(ebx+0x10) 2/r32/edx  # Var-block-depth
    27734       0f 8c/jump-if-< break/disp32
    27735       # if v is in a register
    27736       81 7/subop/compare *(ebx+0x18) 0/imm32  # Var-register
    27737       {
    27738         0f 84/jump-if-= break/disp32
    27739         {
    27740 $emit-cleanup-code-until-depth:check-for-previous-spill:
    27741           8b/-> *(esi+8) 0/r32/eax  # Live-var-register-spilled
    27742           3d/compare-eax-and 0/imm32/false
    27743           74/jump-if-= break/disp8
    27744 $emit-cleanup-code-until-depth:reclaim-var-in-register:
    27745           (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
    27746           (emit-pop-register *(ebp+8) %eax)
    27747         }
    27748         eb/jump $emit-cleanup-code-until-depth:continue/disp8
    27749       }
    27750       # otherwise v is on the stack
    27751       {
    27752         75/jump-if-!= break/disp8
    27753 $emit-cleanup-code-until-depth:var-on-stack:
    27754         (size-of %ebx)  # => eax
    27755         # don't emit code for labels
    27756         3d/compare-eax-and 0/imm32
    27757         74/jump-if-= break/disp8
    27758 $emit-cleanup-code-until-depth:reclaim-var-on-stack:
    27759         (emit-indent *(ebp+8) *Curr-block-depth)
    27760         (write-buffered *(ebp+8) "81 0/subop/add %esp ")
    27761         (write-int32-hex-buffered *(ebp+8) %eax)
    27762         (write-buffered *(ebp+8) "/imm32\n")
    27763       }
    27764 $emit-cleanup-code-until-depth:continue:
    27765       # curr -= 12
    27766       81 5/subop/subtract %esi 0xc/imm32
    27767       e9/jump loop/disp32
    27768     }
    27769 $emit-cleanup-code-until-depth:end:
    27770     # . restore registers
    27771     5e/pop-to-esi
    27772     5b/pop-to-ebx
    27773     5a/pop-to-edx
    27774     59/pop-to-ecx
    27775     58/pop-to-eax
    27776     # . epilogue
    27777     89/<- %esp 5/r32/ebp
    27778     5d/pop-to-ebp
    27779     c3/return
    27780
    27781 # emit clean-up code for 'vars' that don't conflict with output registers
    27782 # doesn't actually modify 'vars' so we need traverse manually inside the stack
    27783 emit-cleanup-code-for-non-outputs:  # out: (addr buffered-file), vars: (addr stack live-var), fn: (addr function)
    27784     # . prologue
    27785     55/push-ebp
    27786     89/<- %ebp 4/r32/esp
    27787     # . save registers
    27788     50/push-eax
    27789     51/push-ecx
    27790     52/push-edx
    27791     53/push-ebx
    27792     56/push-esi
    27793     57/push-edi
    27794     # ecx = vars
    27795     8b/-> *(ebp+0xc) 1/r32/ecx
    27796     # var esi: int = vars->top
    27797     8b/-> *ecx 6/r32/esi
    27798     # var curr/esi: (addr handle var) = &vars->data[vars->top - 12]
    27799     8d/copy-address *(ecx+esi-4) 6/r32/esi  # vars + 8 + vars->top - 12/Live-var-size
    27800     # var min/ecx: (addr handle var) = vars->data
    27801     81 0/subop/add %ecx 8/imm32
    27802     {
    27803 $emit-cleanup-code-for-non-outputs:loop:
    27804       # if (curr < min) break
    27805       39/compare %esi 1/r32/ecx
    27806       0f 82/jump-if-addr< break/disp32
    27807       # var v/ebx: (addr var) = lookup(*curr)
    27808       (lookup *esi *(esi+4))  # => eax
    27809       89/<- %ebx 0/r32/eax
    27810       # if v is in a register
    27811       81 7/subop/compare *(ebx+0x18) 0/imm32  # Var-register
    27812       {
    27813         0f 84/jump-if-= break/disp32
    27814         {
    27815 $emit-cleanup-code-for-non-outputs:check-for-previous-spill:
    27816           8b/-> *(esi+8) 0/r32/eax  # Live-var-register-spilled
    27817           3d/compare-eax-and 0/imm32/false
    27818           0f 84/jump-if-= break/disp32
    27819 $emit-cleanup-code-for-non-outputs:reclaim-var-in-register:
    27820           # var reg/edi: (addr array name) = v->register
    27821           (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
    27822           89/<- %edi 0/r32/eax
    27823           # if reg is not in function outputs, emit a pop
    27824           (reg-in-function-outputs? *(ebp+0x10) %edi)  # => eax
    27825           3d/compare-eax-and 0/imm32/false
    27826           {
    27827             75/jump-if-!= break/disp8
    27828             (emit-pop-register *(ebp+8) %edi)
    27829             eb/jump $emit-cleanup-code-for-non-outputs:reclaim-var-in-register-done/disp8
    27830           }
    27831           # otherwise just drop it from the stack
    27832           (emit-indent *(ebp+8) *Curr-block-depth)
    27833           (write-buffered *(ebp+8) "81 0/subop/add %esp 4/imm32\n")
    27834         }
    27835 $emit-cleanup-code-for-non-outputs:reclaim-var-in-register-done:
    27836         eb/jump $emit-cleanup-code-for-non-outputs:continue/disp8
    27837       }
    27838       # otherwise v is on the stack
    27839       {
    27840         75/jump-if-!= break/disp8
    27841 $emit-cleanup-code-for-non-outputs:var-on-stack:
    27842         (size-of %ebx)  # => eax
    27843         # don't emit code for labels
    27844         3d/compare-eax-and 0/imm32
    27845         74/jump-if-= break/disp8
    27846 $emit-cleanup-code-for-non-outputs:reclaim-var-on-stack:
    27847         (emit-indent *(ebp+8) *Curr-block-depth)
    27848         (write-buffered *(ebp+8) "81 0/subop/add %esp ")
    27849         (write-int32-hex-buffered *(ebp+8) %eax)
    27850         (write-buffered *(ebp+8) "/imm32\n")
    27851       }
    27852 $emit-cleanup-code-for-non-outputs:continue:
    27853       # curr -= 12
    27854       81 5/subop/subtract %esi 0xc/imm32
    27855       e9/jump loop/disp32
    27856     }
    27857 $emit-cleanup-code-for-non-outputs:end:
    27858     # . restore registers
    27859     5f/pop-to-edi
    27860     5e/pop-to-esi
    27861     5b/pop-to-ebx
    27862     5a/pop-to-edx
    27863     59/pop-to-ecx
    27864     58/pop-to-eax
    27865     # . epilogue
    27866     89/<- %esp 5/r32/ebp
    27867     5d/pop-to-ebp
    27868     c3/return
    27869
    27870 emit-push-register:  # out: (addr buffered-file), reg: (addr array byte)
    27871     # . prologue
    27872     55/push-ebp
    27873     89/<- %ebp 4/r32/esp
    27874     # eax = reg
    27875     8b/-> *(ebp+0xc) 0/r32/eax
    27876     # var prefix/eax: byte = reg->data[0]
    27877     8a/copy-byte *(eax+4) 0/r32/AL
    27878     81 4/subop/and %eax 0xff/imm32
    27879     # if (prefix == 'x') push xmm register
    27880     {
    27881       3d/compare-eax-and 0x78/imm32/x
    27882       0f 85/jump-if-!= break/disp32
    27883       # TODO validate register
    27884       (emit-indent *(ebp+8) *Curr-block-depth)
    27885       (write-buffered *(ebp+8) "81 5/subop/subtract %esp 4/imm32\n")
    27886       (emit-indent *(ebp+8) *Curr-block-depth)
    27887       (write-buffered *(ebp+8) "f3 0f 11/<- *esp ")
    27888       # var prefix/eax: byte = reg->data[3]
    27889       8b/-> *(ebp+0xc) 0/r32/eax
    27890       8a/copy-byte *(eax+7) 0/r32/AL
    27891       81 4/subop/and %eax 0xff/imm32
    27892       (write-byte-buffered *(ebp+8) %eax)
    27893       (write-buffered *(ebp+8) "/x32\n")
    27894       e9/jump $emit-push-register:end/disp32
    27895     }
    27896     # otherwise push gp register
    27897     (emit-indent *(ebp+8) *Curr-block-depth)
    27898     (write-buffered *(ebp+8) "ff 6/subop/push %")
    27899     (write-buffered *(ebp+8) *(ebp+0xc))
    27900     (write-buffered *(ebp+8) Newline)
    27901 $emit-push-register:end:
    27902     # . epilogue
    27903     89/<- %esp 5/r32/ebp
    27904     5d/pop-to-ebp
    27905     c3/return
    27906
    27907 emit-pop-register:  # out: (addr buffered-file), reg: (addr array byte)
    27908     # . prologue
    27909     55/push-ebp
    27910     89/<- %ebp 4/r32/esp
    27911     # . save registers
    27912     50/push-eax
    27913     # eax = reg
    27914     8b/-> *(ebp+0xc) 0/r32/eax
    27915     # var prefix/eax: byte = reg->data[0]
    27916     8a/copy-byte *(eax+4) 0/r32/AL
    27917     81 4/subop/and %eax 0xff/imm32
    27918     # if (prefix == 'x') pop to xmm register
    27919     {
    27920       3d/compare-eax-and 0x78/imm32/x
    27921       0f 85/jump-if-!= break/disp32
    27922       # TODO validate register
    27923       (emit-indent *(ebp+8) *Curr-block-depth)
    27924       (write-buffered *(ebp+8) "f3 0f 10/-> *esp ")
    27925       # var prefix/eax: byte = reg->data[3]
    27926       8b/-> *(ebp+0xc) 0/r32/eax
    27927       8a/copy-byte *(eax+7) 0/r32/AL
    27928       81 4/subop/and %eax 0xff/imm32
    27929       (write-byte-buffered *(ebp+8) %eax)
    27930       (write-buffered *(ebp+8) "/x32\n")
    27931       (emit-indent *(ebp+8) *Curr-block-depth)
    27932       (write-buffered *(ebp+8) "81 0/subop/add %esp 4/imm32\n")
    27933       e9/jump $emit-pop-register:end/disp32
    27934     }
    27935     # otherwise pop to gp register
    27936     (emit-indent *(ebp+8) *Curr-block-depth)
    27937     (write-buffered *(ebp+8) "8f 0/subop/pop %")
    27938     (write-buffered *(ebp+8) *(ebp+0xc))
    27939     (write-buffered *(ebp+8) Newline)
    27940 $emit-pop-register:end:
    27941     # . restore registers
    27942     58/pop-to-eax
    27943     # . epilogue
    27944     89/<- %esp 5/r32/ebp
    27945     5d/pop-to-ebp
    27946     c3/return
    27947
    27948 # emit clean-up code for 'vars' until a given label is encountered
    27949 # doesn't actually modify 'vars' so we need traverse manually inside the stack
    27950 emit-cleanup-code-until-target:  # out: (addr buffered-file), vars: (addr stack live-var), until-block-label: (addr array byte)
    27951     # . prologue
    27952     55/push-ebp
    27953     89/<- %ebp 4/r32/esp
    27954     # . save registers
    27955     50/push-eax
    27956     51/push-ecx
    27957     52/push-edx
    27958     53/push-ebx
    27959     # ecx = vars
    27960     8b/-> *(ebp+0xc) 1/r32/ecx
    27961     # var eax: int = vars->top
    27962     8b/-> *ecx 0/r32/eax
    27963     # var curr/edx: (addr handle var) = &vars->data[vars->top - 12]
    27964     8d/copy-address *(ecx+eax-4) 2/r32/edx  # vars + 8 + vars->top - 12/Live-var-size
    27965     # var min/ecx: (addr handle var) = vars->data
    27966     81 0/subop/add %ecx 8/imm32
    27967     {
    27968 $emit-cleanup-code-until-target:loop:
    27969       # if (curr < min) break
    27970       39/compare %edx 1/r32/ecx
    27971       0f 82/jump-if-addr< break/disp32
    27972       # var v/ebx: (handle var) = lookup(*curr)
    27973       (lookup *edx *(edx+4))  # => eax
    27974       89/<- %ebx 0/r32/eax
    27975       # if (v->name == until-block-label) break
    27976       (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
    27977       (string-equal? %eax *(ebp+0x10))  # => eax
    27978       3d/compare-eax-and 0/imm32/false
    27979       0f 85/jump-if-!= break/disp32
    27980       # if v is in a register
    27981       81 7/subop/compare *(ebx+0x18) 0/imm32  # Var-register
    27982       {
    27983         0f 84/jump-if-= break/disp32
    27984         {
    27985 $emit-cleanup-code-until-target:check-for-previous-spill:
    27986           8b/-> *(edx+8) 0/r32/eax  # Live-var-register-spilled
    27987           3d/compare-eax-and 0/imm32/false
    27988           74/jump-if-= break/disp8
    27989 $emit-cleanup-code-until-target:reclaim-var-in-register:
    27990           (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
    27991           (emit-pop-register *(ebp+8) %eax)
    27992         }
    27993         eb/jump $emit-cleanup-code-until-target:continue/disp8
    27994       }
    27995       # otherwise v is on the stack
    27996       {
    27997         75/jump-if-!= break/disp8
    27998 $emit-cleanup-code-until-target:reclaim-var-on-stack:
    27999         (size-of %ebx)  # => eax
    28000         # don't emit code for labels
    28001         3d/compare-eax-and 0/imm32
    28002         74/jump-if-= break/disp8
    28003         #
    28004         (emit-indent *(ebp+8) *Curr-block-depth)
    28005         (write-buffered *(ebp+8) "81 0/subop/add %esp ")
    28006         (write-int32-hex-buffered *(ebp+8) %eax)
    28007         (write-buffered *(ebp+8) "/imm32\n")
    28008       }
    28009 $emit-cleanup-code-until-target:continue:
    28010       # curr -= 12
    28011       81 5/subop/subtract %edx 0xc/imm32
    28012       e9/jump loop/disp32
    28013     }
    28014 $emit-cleanup-code-until-target:end:
    28015     # . restore registers
    28016     5b/pop-to-ebx
    28017     5a/pop-to-edx
    28018     59/pop-to-ecx
    28019     58/pop-to-eax
    28020     # . epilogue
    28021     89/<- %esp 5/r32/ebp
    28022     5d/pop-to-ebp
    28023     c3/return
    28024
    28025 # update Curr-local-stack-offset assuming vars until some block depth are popped
    28026 # doesn't actually modify 'vars', so we need traverse manually inside the stack
    28027 clean-up-stack-offset-state:  # vars: (addr stack live-var), until-block-depth: int
    28028     # . prologue
    28029     55/push-ebp
    28030     89/<- %ebp 4/r32/esp
    28031     # . save registers
    28032     50/push-eax
    28033     51/push-ecx
    28034     52/push-edx
    28035     53/push-ebx
    28036     56/push-esi
    28037     # ecx = vars
    28038     8b/-> *(ebp+8) 1/r32/ecx
    28039     # var esi: int = vars->top
    28040     8b/-> *ecx 6/r32/esi
    28041     # var curr/esi: (addr handle var) = &vars->data[vars->top - 12]
    28042     8d/copy-address *(ecx+esi-4) 6/r32/esi  # vars + 8 + vars->top - 12/Live-var-size
    28043     # var min/ecx: (addr handle var) = vars->data
    28044     81 0/subop/add %ecx 8/imm32
    28045     # edx = until-block-depth
    28046     8b/-> *(ebp+0xc) 2/r32/edx
    28047     {
    28048 $clean-up-stack-offset-state:loop:
    28049       # if (curr < min) break
    28050       39/compare %esi 1/r32/ecx
    28051       0f 82/jump-if-addr< break/disp32
    28052       # var v/ebx: (addr var) = lookup(*curr)
    28053       (lookup *esi *(esi+4))  # => eax
    28054       89/<- %ebx 0/r32/eax
    28055       # if (v->block-depth < until-block-depth) break
    28056       39/compare *(ebx+0x10) 2/r32/edx  # Var-block-depth
    28057       0f 8c/jump-if-< break/disp32
    28058       # if v is in a register
    28059       81 7/subop/compare *(ebx+0x18) 0/imm32  # Var-register
    28060       {
    28061         0f 84/jump-if-= break/disp32
    28062         {
    28063 $clean-up-stack-offset-state:check-for-previous-spill:
    28064           8b/-> *(esi+8) 0/r32/eax  # Live-var-register-spilled
    28065           3d/compare-eax-and 0/imm32/false
    28066           74/jump-if-= break/disp8
    28067 $clean-up-stack-offset-state:reclaim-var-in-register:
    28068           81 0/subop/add *Curr-local-stack-offset 4/imm32
    28069         }
    28070         eb/jump $clean-up-stack-offset-state:continue/disp8
    28071       }
    28072       # otherwise v is on the stack
    28073       {
    28074         75/jump-if-!= break/disp8
    28075 $clean-up-stack-offset-state:var-on-stack:
    28076         (size-of %ebx)  # => eax
    28077         01/add-to *Curr-local-stack-offset 0/r32/eax
    28078       }
    28079 $clean-up-stack-offset-state:continue:
    28080       # curr -= 12
    28081       81 5/subop/subtract %esi 0xc/imm32
    28082       e9/jump loop/disp32
    28083     }
    28084 $clean-up-stack-offset-state:end:
    28085     # . restore registers
    28086     5e/pop-to-esi
    28087     5b/pop-to-ebx
    28088     5a/pop-to-edx
    28089     59/pop-to-ecx
    28090     58/pop-to-eax
    28091     # . epilogue
    28092     89/<- %esp 5/r32/ebp
    28093     5d/pop-to-ebp
    28094     c3/return
    28095
    28096 # Return true if there isn't a variable in 'vars' with the same block-depth
    28097 # and register as 'v'.
    28098 # 'v' is guaranteed not to be within 'vars'.
    28099 not-yet-spilled-this-block?:  # v: (addr var), vars: (addr stack live-var) -> result/eax: boolean
    28100     # . prologue
    28101     55/push-ebp
    28102     89/<- %ebp 4/r32/esp
    28103     # . save registers
    28104     51/push-ecx
    28105     52/push-edx
    28106     53/push-ebx
    28107     56/push-esi
    28108     57/push-edi
    28109     # ecx = vars
    28110     8b/-> *(ebp+0xc) 1/r32/ecx
    28111     # var eax: int = vars->top
    28112     8b/-> *ecx 0/r32/eax
    28113     # var curr/edx: (addr handle var) = &vars->data[vars->top - 12]
    28114     8d/copy-address *(ecx+eax-4) 2/r32/edx  # vars + 8 + vars->top - 12/Live-var-size
    28115     # var min/ecx: (addr handle var) = vars->data
    28116     8d/copy-address *(ecx+8) 1/r32/ecx
    28117     # var depth/ebx: int = v->block-depth
    28118     8b/-> *(ebp+8) 3/r32/ebx
    28119     8b/-> *(ebx+0x10) 3/r32/ebx  # Var-block-depth
    28120     # var needle/esi: (addr array byte) = v->register
    28121     8b/-> *(ebp+8) 6/r32/esi
    28122     (lookup *(esi+0x18) *(esi+0x1c))  # Var-register Var-register => eax
    28123     89/<- %esi 0/r32/eax
    28124     {
    28125 $not-yet-spilled-this-block?:loop:
    28126       # if (curr < min) break
    28127       39/compare %edx 1/r32/ecx
    28128       0f 82/jump-if-addr< break/disp32
    28129       # var cand/edi: (addr var) = lookup(*curr)
    28130       (lookup *edx *(edx+4))  # => eax
    28131       89/<- %edi 0/r32/eax
    28132       # if (cand->block-depth < depth) break
    28133       39/compare *(edi+0x10) 3/r32/ebx  # Var-block-depth
    28134       0f 8c/jump-if-< break/disp32
    28135       # var cand-reg/edi: (array array byte) = cand->reg
    28136       (lookup *(edi+0x18) *(edi+0x1c))  # Var-register Var-register => eax
    28137       89/<- %edi 0/r32/eax
    28138       # if (cand-reg == null) continue
    28139       {
    28140 $not-yet-spilled-this-block?:check-reg:
    28141         81 7/subop/compare %edi 0/imm32
    28142         0f 84/jump-if-= break/disp32
    28143         # if (cand-reg == needle) return true
    28144         (string-equal? %esi %edi)  # => eax
    28145         3d/compare-eax-and 0/imm32/false
    28146         74/jump-if-= break/disp8
    28147 $not-yet-spilled-this-block?:return-false:
    28148         b8/copy-to-eax 0/imm32/false
    28149         eb/jump $not-yet-spilled-this-block?:end/disp8
    28150       }
    28151 $not-yet-spilled-this-block?:continue:
    28152       # curr -= 12
    28153       81 5/subop/subtract %edx 0xc/imm32
    28154       e9/jump loop/disp32
    28155     }
    28156 $not-yet-spilled-this-block?:return-true:
    28157     # return true
    28158     b8/copy-to-eax 1/imm32/true
    28159 $not-yet-spilled-this-block?:end:
    28160     # . restore registers
    28161     5f/pop-to-edi
    28162     5e/pop-to-esi
    28163     5b/pop-to-ebx
    28164     5a/pop-to-edx
    28165     59/pop-to-ecx
    28166     # . epilogue
    28167     89/<- %esp 5/r32/ebp
    28168     5d/pop-to-ebp
    28169     c3/return
    28170
    28171 # could the register of 'v' ever be written to by one of the vars in fn-outputs?
    28172 will-not-write-some-register?:  # v: (addr var), stmts: (addr list stmt), fn: (addr function) -> result/eax: boolean
    28173     # . prologue
    28174     55/push-ebp
    28175     89/<- %ebp 4/r32/esp
    28176     # eax = v
    28177     8b/-> *(ebp+8) 0/r32/eax
    28178     # var reg/eax: (addr array byte) = lookup(v->register)
    28179     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    28180     # var target/eax: (addr var) = find-register(fn-outputs, reg)
    28181     (find-register *(ebp+0x10) %eax)  # => eax
    28182     # if (target == 0) return true
    28183     {
    28184       3d/compare-eax-and 0/imm32
    28185       75/jump-if-!= break/disp8
    28186       b8/copy-to-eax 1/imm32/true
    28187       eb/jump $will-not-write-some-register?:end/disp8
    28188     }
    28189     # return !assigns-in-stmts?(stmts, target)
    28190     (assigns-in-stmts? *(ebp+0xc) %eax)  # => eax
    28191     3d/compare-eax-and 0/imm32/false
    28192     # assume: true = 1, so no need to mask with 0x000000ff
    28193     0f 94/set-if-= %al
    28194 $will-not-write-some-register?:end:
    28195     # . epilogue
    28196     89/<- %esp 5/r32/ebp
    28197     5d/pop-to-ebp
    28198     c3/return
    28199
    28200 # return fn output with matching register
    28201 # always returns false if 'reg' is null
    28202 find-register:  # fn: (addr function), reg: (addr array byte) -> result/eax: (addr var)
    28203     # . prologue
    28204     55/push-ebp
    28205     89/<- %ebp 4/r32/esp
    28206     # . save registers
    28207     51/push-ecx
    28208     # var curr/ecx: (addr list var) = lookup(fn->outputs)
    28209     8b/-> *(ebp+8) 1/r32/ecx
    28210     (lookup *(ecx+0x10) *(ecx+0x14))  # Function-outputs Function-outputs => eax
    28211     89/<- %ecx 0/r32/eax
    28212     {
    28213 $find-register:loop:
    28214       # if (curr == 0) break
    28215       81 7/subop/compare %ecx 0/imm32
    28216       74/jump-if-= break/disp8
    28217       # eax = curr->value->register
    28218       (lookup *ecx *(ecx+4))  # List-value List-value => eax
    28219       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    28220       # if (eax == reg) return curr->value
    28221 $find-register:compare:
    28222       (string-equal? *(ebp+0xc) %eax)  # => eax
    28223       {
    28224         3d/compare-eax-and 0/imm32/false
    28225         74/jump-if-= break/disp8
    28226 $find-register:found:
    28227         (lookup *ecx *(ecx+4))  # List-value List-value => eax
    28228         eb/jump $find-register:end/disp8
    28229       }
    28230       # curr = lookup(curr->next)
    28231       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
    28232       89/<- %ecx 0/r32/eax
    28233       #
    28234       eb/jump loop/disp8
    28235     }
    28236 $find-register:end:
    28237     # . restore registers
    28238     59/pop-to-ecx
    28239     # . epilogue
    28240     89/<- %esp 5/r32/ebp
    28241     5d/pop-to-ebp
    28242     c3/return
    28243
    28244 assigns-in-stmts?:  # stmts: (addr list stmt), v: (addr var) -> result/eax: boolean
    28245     # . prologue
    28246     55/push-ebp
    28247     89/<- %ebp 4/r32/esp
    28248     # . save registers
    28249     51/push-ecx
    28250     # var curr/ecx: (addr list stmt) = stmts
    28251     8b/-> *(ebp+8) 1/r32/ecx
    28252     {
    28253       # if (curr == 0) break
    28254       81 7/subop/compare %ecx 0/imm32
    28255       74/jump-if-= break/disp8
    28256       # if assigns-in-stmt?(curr->value, v) return true
    28257       (lookup *ecx *(ecx+4))  # List-value List-value => eax
    28258       (assigns-in-stmt? %eax *(ebp+0xc))  # => eax
    28259       3d/compare-eax-and 0/imm32/false
    28260       75/jump-if-!= break/disp8
    28261       # curr = lookup(curr->next)
    28262       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
    28263       89/<- %ecx 0/r32/eax
    28264       #
    28265       eb/jump loop/disp8
    28266     }
    28267 $assigns-in-stmts?:end:
    28268     # . restore registers
    28269     59/pop-to-ecx
    28270     # . epilogue
    28271     89/<- %esp 5/r32/ebp
    28272     5d/pop-to-ebp
    28273     c3/return
    28274
    28275 assigns-in-stmt?:  # stmt: (addr stmt), v: (addr var) -> result/eax: boolean
    28276     # . prologue
    28277     55/push-ebp
    28278     89/<- %ebp 4/r32/esp
    28279     # . save registers
    28280     51/push-ecx
    28281     # ecx = stmt
    28282     8b/-> *(ebp+8) 1/r32/ecx
    28283     # if stmt is a stmt1, return assigns-in-stmt-vars?(stmt->outputs, v)
    28284     {
    28285       81 7/subop/compare *ecx 1/imm32/stmt1  # Stmt-tag
    28286       75/jump-if-!= break/disp8
    28287       (lookup *(ecx+0x14) *(ecx+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    28288       (assigns-in-stmt-vars? %eax *(ebp+0xc))  # => eax
    28289       eb/jump $assigns-in-stmt?:end/disp8
    28290     }
    28291     # if stmt is a block, return assigns-in-stmts?(stmt->stmts, v)
    28292     {
    28293       81 7/subop/compare *ecx 0/imm32/block  # Stmt-tag
    28294       75/jump-if-!= break/disp8
    28295       (lookup *(ecx+4) *(ecx+8))  # Block-stmts Block-stmts => eax
    28296       (assigns-in-stmts? %eax *(ebp+0xc))  # => eax
    28297       eb/jump $assigns-in-stmt?:end/disp8
    28298     }
    28299     # otherwise return false
    28300     b8/copy 0/imm32/false
    28301 $assigns-in-stmt?:end:
    28302     # . restore registers
    28303     59/pop-to-ecx
    28304     # . epilogue
    28305     89/<- %esp 5/r32/ebp
    28306     5d/pop-to-ebp
    28307     c3/return
    28308
    28309 assigns-in-stmt-vars?:  # stmt-var: (addr stmt-var), v: (addr var) -> result/eax: boolean
    28310     # . prologue
    28311     55/push-ebp
    28312     89/<- %ebp 4/r32/esp
    28313     # . save registers
    28314     51/push-ecx
    28315     # var curr/ecx: (addr stmt-var) = stmt-var
    28316     8b/-> *(ebp+8) 1/r32/ecx
    28317     {
    28318       # if (curr == 0) break
    28319       81 7/subop/compare %ecx 0/imm32
    28320       74/jump-if-= break/disp8
    28321       # eax = lookup(curr->value)
    28322       (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
    28323       # if (eax == v  &&  curr->is-deref? == false) return true
    28324       {
    28325         39/compare *(ebp+0xc) 0/r32/eax
    28326         75/jump-if-!= break/disp8
    28327         81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
    28328         75/jump-if-!= break/disp8
    28329         b8/copy-to-eax 1/imm32/true
    28330         eb/jump $assigns-in-stmt-vars?:end/disp8
    28331       }
    28332       # curr = lookup(curr->next)
    28333       (lookup *(ecx+8) *(ecx+0xc))  # Stmt-var-next Stmt-var-next => eax
    28334       89/<- %ecx 0/r32/eax
    28335       #
    28336       eb/jump loop/disp8
    28337     }
    28338 $assigns-in-stmt-vars?:end:
    28339     # . restore registers
    28340     59/pop-to-ecx
    28341     # . epilogue
    28342     89/<- %esp 5/r32/ebp
    28343     5d/pop-to-ebp
    28344     c3/return
    28345
    28346 # is there a var before 'v' with the same block-depth and register on the 'vars' stack?
    28347 # v is guaranteed to be within vars
    28348 # 'start' is provided as an optimization, a pointer within vars
    28349 # *start == v
    28350 same-register-spilled-before?:  # v: (addr var), vars: (addr stack (handle var)), start: (addr var) -> result/eax: boolean
    28351     # . prologue
    28352     55/push-ebp
    28353     89/<- %ebp 4/r32/esp
    28354     # . save registers
    28355     51/push-ecx
    28356     52/push-edx
    28357     53/push-ebx
    28358     56/push-esi
    28359     57/push-edi
    28360     # ecx = v
    28361     8b/-> *(ebp+8) 1/r32/ecx
    28362     # var reg/edx: (addr array byte) = lookup(v->register)
    28363     (lookup *(ecx+0x18) *(ecx+0x1c))  # Var-register Var-register => eax
    28364     89/<- %edx 0/r32/eax
    28365     # var depth/ebx: int = v->block-depth
    28366     8b/-> *(ecx+0x10) 3/r32/ebx  # Var-block-depth
    28367     # var min/ecx: (addr handle var) = vars->data
    28368     8b/-> *(ebp+0xc) 1/r32/ecx
    28369     81 0/subop/add %ecx 8/imm32
    28370     # TODO: check that start >= min and start < &vars->data[top]
    28371     # TODO: check that *start == v
    28372     # var curr/esi: (addr handle var) = start
    28373     8b/-> *(ebp+0x10) 6/r32/esi
    28374     # curr -= 8
    28375     81 5/subop/subtract %esi 8/imm32
    28376     {
    28377 $same-register-spilled-before?:loop:
    28378       # if (curr < min) break
    28379       39/compare %esi 1/r32/ecx
    28380       0f 82/jump-if-addr< break/disp32
    28381       # var x/eax: (addr var) = lookup(*curr)
    28382       (lookup *esi *(esi+4))  # => eax
    28383       # if (x->block-depth < depth) break
    28384       39/compare *(eax+0x10) 3/r32/ebx  # Var-block-depth
    28385       0f 8c/jump-if-< break/disp32
    28386       # if (x->register == 0) continue
    28387       81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
    28388       74/jump-if-= $same-register-spilled-before?:continue/disp8
    28389       # if (x->register == reg) return true
    28390       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    28391       (string-equal? %eax %edx)  # => eax
    28392       3d/compare-eax-and 0/imm32/false
    28393       b8/copy-to-eax 1/imm32/true
    28394       75/jump-if-!= $same-register-spilled-before?:end/disp8
    28395 $same-register-spilled-before?:continue:
    28396       # curr -= 8
    28397       81 5/subop/subtract %esi 8/imm32
    28398       e9/jump loop/disp32
    28399     }
    28400 $same-register-spilled-before?:false:
    28401     b8/copy-to-eax 0/imm32/false
    28402 $same-register-spilled-before?:end:
    28403     # . restore registers
    28404     5f/pop-to-edi
    28405     5e/pop-to-esi
    28406     5b/pop-to-ebx
    28407     5a/pop-to-edx
    28408     59/pop-to-ecx
    28409     # . epilogue
    28410     89/<- %esp 5/r32/ebp
    28411     5d/pop-to-ebp
    28412     c3/return
    28413
    28414 # clean up global state for 'vars' until some block depth (inclusive)
    28415 clean-up-blocks:  # vars: (addr stack live-var), until-block-depth: int, fn: (addr function)
    28416     # . prologue
    28417     55/push-ebp
    28418     89/<- %ebp 4/r32/esp
    28419     # . save registers
    28420     50/push-eax
    28421     51/push-ecx
    28422     56/push-esi
    28423     # esi = vars
    28424     8b/-> *(ebp+8) 6/r32/esi
    28425     # ecx = until-block-depth
    28426     8b/-> *(ebp+0xc) 1/r32/ecx
    28427     {
    28428 $clean-up-blocks:reclaim-loop:
    28429       # if (vars->top <= 0) break
    28430       8b/-> *esi 0/r32/eax  # Stack-top
    28431       3d/compare-eax-and 0/imm32
    28432       0f 8e/jump-if-<= break/disp32
    28433       # var v/eax: (addr var) = lookup(vars[vars->top-12])
    28434       (lookup *(esi+eax-4) *(esi+eax))  # vars + 8 + vars->top - 12 => eax
    28435       # if (v->block-depth < until-block-depth) break
    28436       39/compare *(eax+0x10) 1/r32/ecx  # Var-block-depth
    28437       0f 8c/jump-if-< break/disp32
    28438       (pop %esi)  # => eax
    28439       (pop %esi)  # => eax
    28440       (pop %esi)  # => eax
    28441       e9/jump loop/disp32
    28442     }
    28443 $clean-up-blocks:end:
    28444     # . restore registers
    28445     5e/pop-to-esi
    28446     59/pop-to-ecx
    28447     58/pop-to-eax
    28448     # . epilogue
    28449     89/<- %esp 5/r32/ebp
    28450     5d/pop-to-ebp
    28451     c3/return
    28452
    28453 reg-in-function-outputs?:  # fn: (addr function), target: (addr array byte) -> result/eax: boolean
    28454     # . prologue
    28455     55/push-ebp
    28456     89/<- %ebp 4/r32/esp
    28457     # . save registers
    28458     51/push-ecx
    28459     # var curr/ecx: (addr list var) = lookup(fn->outputs)
    28460     8b/-> *(ebp+8) 0/r32/eax
    28461     (lookup *(eax+0x10) *(eax+0x14))  # Function-outputs Function-outputs => eax
    28462     89/<- %ecx 0/r32/eax
    28463     # while curr != null
    28464     {
    28465       81 7/subop/compare %ecx 0/imm32
    28466       74/jump-if-= break/disp8
    28467       # var v/eax: (addr var) = lookup(curr->value)
    28468       (lookup *ecx *(ecx+4))  # List-value List-value => eax
    28469       # var reg/eax: (addr array byte) = lookup(v->register)
    28470       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    28471       # if (reg == target) return true
    28472       (string-equal? %eax *(ebp+0xc))  # => eax
    28473       3d/compare-eax-and 0/imm32/false
    28474       75/jump-if-!= $reg-in-function-outputs?:end/disp8
    28475       # curr = curr->next
    28476       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
    28477       89/<- %ecx 0/r32/eax
    28478       #
    28479       eb/jump loop/disp8
    28480     }
    28481     # return false
    28482     b8/copy-to-eax 0/imm32
    28483 $reg-in-function-outputs?:end:
    28484     # . restore registers
    28485     59/pop-to-ecx
    28486     # . epilogue
    28487     89/<- %esp 5/r32/ebp
    28488     5d/pop-to-ebp
    28489     c3/return
    28490
    28491 emit-subx-var-def:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
    28492     # . prologue
    28493     55/push-ebp
    28494     89/<- %ebp 4/r32/esp
    28495     # . save registers
    28496     50/push-eax
    28497     51/push-ecx
    28498     52/push-edx
    28499     # eax = stmt
    28500     8b/-> *(ebp+0xc) 0/r32/eax
    28501     # var v/ecx: (addr var)
    28502     (lookup *(eax+4) *(eax+8))  # Vardef-var Vardef-var => eax
    28503     89/<- %ecx 0/r32/eax
    28504     # v->block-depth = *Curr-block-depth
    28505     8b/-> *Curr-block-depth 0/r32/eax
    28506     89/<- *(ecx+0x10) 0/r32/eax  # Var-block-depth
    28507     # var n/edx: int = size-of(stmt->var)
    28508     (size-of %ecx)  # => eax
    28509     89/<- %edx 0/r32/eax
    28510     # *Curr-local-stack-offset -= n
    28511     29/subtract-from *Curr-local-stack-offset 2/r32/edx
    28512     # v->offset = *Curr-local-stack-offset
    28513     8b/-> *Curr-local-stack-offset 0/r32/eax
    28514     89/<- *(ecx+0x14) 0/r32/eax  # Var-offset
    28515     # if v is an array, do something special to initialize it
    28516     {
    28517       (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
    28518       (mu-array? %eax)  # => eax
    28519       3d/compare-eax-and 0/imm32/false
    28520       0f 84/jump-if-= break/disp32
    28521       # var array-size-without-size/edx: int = n-4
    28522       81 5/subop/subtract %edx 4/imm32
    28523       #
    28524       (emit-array-data-initialization *(ebp+8) %edx)
    28525       e9/jump $emit-subx-var-def:end/disp32
    28526     }
    28527     # another special-case for initializing streams
    28528     # a stream is an array with 2 extra pointers
    28529     {
    28530       (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
    28531       (mu-stream? %eax)  # => eax
    28532       3d/compare-eax-and 0/imm32/false
    28533       0f 84/jump-if-= break/disp32
    28534       # var array-size-without-size/edx: int = n-12
    28535       81 5/subop/subtract %edx 0xc/imm32
    28536       (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
    28537       (emit-stream-data-initialization *(ebp+8) %edx %eax *(ebp+0x10) *(ebp+0x14))
    28538       # emit read and write pointers
    28539       (emit-indent *(ebp+8) *Curr-block-depth)
    28540       (write-buffered *(ebp+8) "68/push 0/imm32\n")
    28541       (emit-indent *(ebp+8) *Curr-block-depth)
    28542       (write-buffered *(ebp+8) "68/push 0/imm32\n")
    28543       #
    28544       eb/jump $emit-subx-var-def:end/disp8
    28545     }
    28546     # while n > 0
    28547     {
    28548       81 7/subop/compare %edx 0/imm32
    28549       7e/jump-if-<= break/disp8
    28550       (emit-indent *(ebp+8) *Curr-block-depth)
    28551       (write-buffered *(ebp+8) "68/push 0/imm32\n")
    28552       # n -= 4
    28553       81 5/subop/subtract %edx 4/imm32
    28554       #
    28555       eb/jump loop/disp8
    28556     }
    28557 $emit-subx-var-def:end:
    28558     # . restore registers
    28559     5a/pop-to-edx
    28560     59/pop-to-ecx
    28561     58/pop-to-eax
    28562     # . epilogue
    28563     89/<- %esp 5/r32/ebp
    28564     5d/pop-to-ebp
    28565     c3/return
    28566
    28567 emit-array-data-initialization:  # out: (addr buffered-file), n: int
    28568     # . prologue
    28569     55/push-ebp
    28570     89/<- %ebp 4/r32/esp
    28571     #
    28572     (emit-indent *(ebp+8) *Curr-block-depth)
    28573     (write-buffered *(ebp+8) "(push-n-zero-bytes ")
    28574     (write-int32-hex-buffered *(ebp+8) *(ebp+0xc))
    28575     (write-buffered *(ebp+8) ")\n")
    28576     (emit-indent *(ebp+8) *Curr-block-depth)
    28577     (write-buffered *(ebp+8) "68/push ")
    28578     (write-int32-hex-buffered *(ebp+8) *(ebp+0xc))
    28579     (write-buffered *(ebp+8) "/imm32\n")
    28580 $emit-array-data-initialization:end:
    28581     # . epilogue
    28582     89/<- %esp 5/r32/ebp
    28583     5d/pop-to-ebp
    28584     c3/return
    28585
    28586 emit-stream-data-initialization:  # out: (addr buffered-file), n: int, type: (addr type-tree), err: (addr buffered-file), ed: (addr exit-descriptor)
    28587     # . prologue
    28588     55/push-ebp
    28589     89/<- %ebp 4/r32/esp
    28590     # . save registers
    28591     50/push-eax
    28592     # Optimization: if it's a stream of bytes, don't initialize.
    28593     #
    28594     # We often construct large temporary streams on the stack for 'trace'
    28595     # statements. Initializing such streams can significantly slow programs
    28596     # down.
    28597     #
    28598     # Mu doesn't really depend on initializing stream contents for type- or
    28599     # memory-safety; we're mostly doing so to make it easy to debug unsafe
    28600     # SubX code that misuses stream objects by manipulating read/write
    28601     # pointers. But you can't _really_ protect from unsafe SubX, so I think we
    28602     # don't give up much safety or security here.
    28603     {
    28604       (stream-element-type-id *(ebp+0x10) *(ebp+0x14) *(ebp+0x18))  # => eax
    28605       3d/compare-eax-and 8/imm32/byte
    28606       75/jump-if-!= break/disp8
    28607       (emit-indent *(ebp+8) *Curr-block-depth)
    28608       (write-buffered *(ebp+8) "81 5/subop/subtract %esp ")
    28609       (write-int32-hex-buffered *(ebp+8) *(ebp+0xc))
    28610       (write-buffered *(ebp+8) "/imm32\n")
    28611       eb/jump $emit-stream-data-initialization:emit-length/disp8
    28612     }
    28613     (emit-indent *(ebp+8) *Curr-block-depth)
    28614     (write-buffered *(ebp+8) "(push-n-zero-bytes ")
    28615     (write-int32-hex-buffered *(ebp+8) *(ebp+0xc))
    28616     (write-buffered *(ebp+8) ")\n")
    28617 $emit-stream-data-initialization:emit-length:
    28618     (emit-indent *(ebp+8) *Curr-block-depth)
    28619     (write-buffered *(ebp+8) "68/push ")
    28620     (write-int32-hex-buffered *(ebp+8) *(ebp+0xc))
    28621     (write-buffered *(ebp+8) "/imm32\n")
    28622 $emit-stream-data-initialization:end:
    28623     # . restore registers
    28624     58/pop-to-eax
    28625     # . epilogue
    28626     89/<- %esp 5/r32/ebp
    28627     5d/pop-to-ebp
    28628     c3/return
    28629
    28630 emit-subx-stmt:  # out: (addr buffered-file), stmt: (addr stmt), primitives: (addr primitive), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    28631     # . prologue
    28632     55/push-ebp
    28633     89/<- %ebp 4/r32/esp
    28634     # . save registers
    28635     50/push-eax
    28636     51/push-ecx
    28637     # - some special-case primitives that don't actually use the 'primitives' data structure
    28638     # var op/ecx: (addr array byte) = lookup(stmt->operation)
    28639     8b/-> *(ebp+0xc) 1/r32/ecx
    28640     (lookup *(ecx+4) *(ecx+8))  # Stmt1-operation Stmt1-operation => eax
    28641     89/<- %ecx 0/r32/eax
    28642     # copy byte (can be a primitive except we need to emit a second instruction)
    28643     {
    28644       # if (!string-equal?(stmt->operation, "copy-byte")) break
    28645       (string-equal? %ecx "copy-byte")  # => eax
    28646       3d/compare-eax-and 0/imm32/false
    28647       0f 84/jump-if-= break/disp32
    28648       (translate-mu-copy-byte-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
    28649       e9/jump $emit-subx-stmt:end/disp32
    28650     }
    28651     # copy-byte-to can be a primitive; writes to memory don't need to clear surrounding bytes
    28652     # array size
    28653     {
    28654       # if (!string-equal?(stmt->operation, "length")) break
    28655       (string-equal? %ecx "length")  # => eax
    28656       3d/compare-eax-and 0/imm32/false
    28657       0f 84/jump-if-= break/disp32
    28658       (translate-mu-length-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
    28659       e9/jump $emit-subx-stmt:end/disp32
    28660     }
    28661     # index into array
    28662     {
    28663       # if (!string-equal?(stmt->operation, "index")) break
    28664       (string-equal? %ecx "index")  # => eax
    28665       3d/compare-eax-and 0/imm32/false
    28666       0f 84/jump-if-= break/disp32
    28667       (translate-mu-index-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
    28668       e9/jump $emit-subx-stmt:end/disp32
    28669     }
    28670     # compute-offset for index into array
    28671     {
    28672       # if (!string-equal?(stmt->operation, "compute-offset")) break
    28673       (string-equal? %ecx "compute-offset")  # => eax
    28674       3d/compare-eax-and 0/imm32/false
    28675       0f 84/jump-if-= break/disp32
    28676       (translate-mu-compute-index-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
    28677       e9/jump $emit-subx-stmt:end/disp32
    28678     }
    28679     # get field from record
    28680     {
    28681       # if (!string-equal?(stmt->operation, "get")) break
    28682       (string-equal? %ecx "get")  # => eax
    28683       3d/compare-eax-and 0/imm32/false
    28684       0f 84/jump-if-= break/disp32
    28685       (translate-mu-get-stmt *(ebp+8) *(ebp+0xc))
    28686       e9/jump $emit-subx-stmt:end/disp32
    28687     }
    28688     # allocate scalar
    28689     {
    28690       # if (!string-equal?(stmt->operation, "allocate")) break
    28691       (string-equal? %ecx "allocate")  # => eax
    28692       3d/compare-eax-and 0/imm32/false
    28693       0f 84/jump-if-= break/disp32
    28694       (translate-mu-allocate-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
    28695       e9/jump $emit-subx-stmt:end/disp32
    28696     }
    28697     # copy-object
    28698     {
    28699       # if (!string-equal?(stmt->operation, "copy-object")) break
    28700       (string-equal? %ecx "copy-object")  # => eax
    28701       3d/compare-eax-and 0/imm32/false
    28702       0f 84/jump-if-= break/disp32
    28703       (translate-mu-copy-object-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
    28704       e9/jump $emit-subx-stmt:end/disp32
    28705     }
    28706     # clear-object
    28707     {
    28708       # if (!string-equal?(stmt->operation, "clear-object")) break
    28709       (string-equal? %ecx "clear-object")  # => eax
    28710       3d/compare-eax-and 0/imm32/false
    28711       0f 84/jump-if-= break/disp32
    28712       (translate-mu-clear-object-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
    28713       e9/jump $emit-subx-stmt:end/disp32
    28714     }
    28715     # allocate array
    28716     {
    28717       # if (!string-equal?(stmt->operation, "populate")) break
    28718       (string-equal? %ecx "populate")  # => eax
    28719       3d/compare-eax-and 0/imm32/false
    28720       0f 84/jump-if-= break/disp32
    28721       (translate-mu-populate-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
    28722       e9/jump $emit-subx-stmt:end/disp32
    28723     }
    28724     # allocate stream
    28725     {
    28726       # if (!string-equal?(stmt->operation, "populate-stream")) break
    28727       (string-equal? %ecx "populate-stream")  # => eax
    28728       3d/compare-eax-and 0/imm32/false
    28729       0f 84/jump-if-= break/disp32
    28730       (translate-mu-populate-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
    28731       e9/jump $emit-subx-stmt:end/disp32
    28732     }
    28733     # read from stream
    28734     {
    28735       # if (!string-equal?(stmt->operation, "read-from-stream")) break
    28736       (string-equal? %ecx "read-from-stream")  # => eax
    28737       3d/compare-eax-and 0/imm32/false
    28738       0f 84/jump-if-= break/disp32
    28739       (translate-mu-read-from-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
    28740       e9/jump $emit-subx-stmt:end/disp32
    28741     }
    28742     # write to stream
    28743     {
    28744       # if (!string-equal?(stmt->operation, "write-to-stream")) break
    28745       (string-equal? %ecx "write-to-stream")  # => eax
    28746       3d/compare-eax-and 0/imm32/false
    28747       0f 84/jump-if-= break/disp32
    28748       (translate-mu-write-to-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
    28749       e9/jump $emit-subx-stmt:end/disp32
    28750     }
    28751     # - optimizations
    28752     # if copy instruction has same register in source and destination, emit nothing
    28753     (redundant-copy? *(ebp+0xc))  # => eax
    28754     3d/compare-eax-and 0/imm32/false
    28755     75/jump-if-!= $emit-subx-stmt:end/disp8
    28756     # - if stmt matches a primitive, emit it
    28757     {
    28758 $emit-subx-stmt:check-for-primitive:
    28759       # var curr/eax: (addr primitive)
    28760       (find-matching-primitive *(ebp+0x10) *(ebp+0xc))  # primitives, stmt => eax
    28761       3d/compare-eax-and 0/imm32
    28762       74/jump-if-= break/disp8
    28763 $emit-subx-stmt:primitive:
    28764       (emit-subx-primitive *(ebp+8) *(ebp+0xc) %eax)  # out, stmt, curr
    28765       e9/jump $emit-subx-stmt:end/disp32
    28766     }
    28767     # - otherwise emit a call
    28768     # TODO: type-checking
    28769 $emit-subx-stmt:call:
    28770     (emit-call *(ebp+8) *(ebp+0xc))
    28771 $emit-subx-stmt:end:
    28772     # . restore registers
    28773     59/pop-to-ecx
    28774     58/pop-to-eax
    28775     # . epilogue
    28776     89/<- %esp 5/r32/ebp
    28777     5d/pop-to-ebp
    28778     c3/return
    28779
    28780 redundant-copy?:  # stmt: (addr stmt) -> result/eax: boolean
    28781     # . prologue
    28782     55/push-ebp
    28783     89/<- %ebp 4/r32/esp
    28784     # . save registers
    28785     56/push-esi
    28786     57/push-edi
    28787     # esi = stmt
    28788     8b/-> *(ebp+8) 6/r32/esi
    28789     # if stmt->operation != "copy" return false
    28790     (lookup *(esi+4) *(esi+8))  # Stmt1-operation Stmt1-operation => eax
    28791     (string-equal? %eax "copy")  # => eax
    28792     3d/compare-eax-and 0/imm32/false
    28793     0f 84/jump-if-= $redundant-copy?:end/disp32
    28794     # var output-reg/edi: (addr stmt-var) = stmt->outputs->value->register
    28795     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    28796     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    28797     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    28798     # . if output-reg == null, return false
    28799     3d/compare-eax-and 0/imm32
    28800     74/jump-if-= $redundant-copy?:end/disp8
    28801     89/<- %edi 0/r32/eax
    28802     # return (inout->value->register == output->value->register)
    28803     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    28804     # . if inout->is-deref return false
    28805     81 7/subop/compare *(eax+0x10) 0/imm32/false  # Stmt-var-is-deref
    28806     {
    28807       74/jump-if-= break/disp8
    28808       b8/copy-to-eax 0/imm32/false
    28809       e9/jump $redundant-copy?:end/disp32
    28810     }
    28811     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    28812     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    28813     # . if inout-reg == null, return false
    28814     3d/compare-eax-and 0/imm32
    28815     74/jump-if-= $redundant-copy?:end/disp8
    28816     (string-equal? %eax %edi)  # => eax
    28817 $redundant-copy?:end:
    28818     # . restore registers
    28819     5f/pop-to-edi
    28820     5e/pop-to-esi
    28821     # . epilogue
    28822     89/<- %esp 5/r32/ebp
    28823     5d/pop-to-ebp
    28824     c3/return
    28825
    28826 translate-mu-length-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
    28827     # . prologue
    28828     55/push-ebp
    28829     89/<- %ebp 4/r32/esp
    28830     # . save registers
    28831     50/push-eax
    28832     51/push-ecx
    28833     52/push-edx
    28834     53/push-ebx
    28835     56/push-esi
    28836     # esi = stmt
    28837     8b/-> *(ebp+0xc) 6/r32/esi
    28838     # var base/ebx: (addr var) = stmt->inouts[0]->value
    28839     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    28840     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    28841     89/<- %ebx 0/r32/eax
    28842     # var elemsize/ecx: int = array-element-size(base)
    28843     (array-element-size %ebx *(ebp+0x10) *(ebp+0x14))  # => eax
    28844     89/<- %ecx 0/r32/eax
    28845     # var outreg/edx: (addr array byte) = stmt->outputs[0]->value->register
    28846     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    28847     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    28848     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    28849     89/<- %edx 0/r32/eax
    28850     # if elemsize == 1
    28851     {
    28852       81 7/subop/compare %ecx 1/imm32
    28853       75/jump-if-!= break/disp8
    28854 $translate-mu-length-stmt:size-1:
    28855       (emit-save-size-to *(ebp+8) %ebx %edx)
    28856       e9/jump $translate-mu-length-stmt:end/disp32
    28857     }
    28858     # if elemsize is a power of 2 less than 256
    28859     {
    28860       (power-of-2? %ecx *(ebp+0x10) *(ebp+0x14))  # => eax
    28861       3d/compare-eax-and 0/imm32/false
    28862       74/jump-if-= break/disp8
    28863       81 7/subop/compare %ecx 0xff/imm32
    28864       7f/jump-if-> break/disp8
    28865 $translate-mu-length-stmt:size-power-of-2:
    28866       (emit-save-size-to *(ebp+8) %ebx %edx)
    28867       (emit-divide-by-shift-right *(ebp+8) %edx %ecx)
    28868       e9/jump $translate-mu-length-stmt:end/disp32
    28869     }
    28870     # otherwise, the complex case
    28871     # . emit register spills
    28872     {
    28873 $translate-mu-length-stmt:complex:
    28874       (string-equal? %edx "eax")  # => eax
    28875       3d/compare-eax-and 0/imm32/false
    28876       75/break-if-!= break/disp8
    28877       (emit-indent *(ebp+8) *Curr-block-depth)
    28878       (write-buffered *(ebp+8) "50/push-eax\n")
    28879     }
    28880     {
    28881       (string-equal? %edx "ecx")  # => eax
    28882       3d/compare-eax-and 0/imm32/false
    28883       75/break-if-!= break/disp8
    28884       (emit-indent *(ebp+8) *Curr-block-depth)
    28885       (write-buffered *(ebp+8) "51/push-ecx\n")
    28886     }
    28887     {
    28888       (string-equal? %edx "edx")  # => eax
    28889       3d/compare-eax-and 0/imm32/false
    28890       75/break-if-!= break/disp8
    28891       (emit-indent *(ebp+8) *Curr-block-depth)
    28892       (write-buffered *(ebp+8) "52/push-edx\n")
    28893     }
    28894     # .
    28895     (emit-save-size-to *(ebp+8) %ebx "eax")
    28896     (emit-indent *(ebp+8) *Curr-block-depth)
    28897     (write-buffered *(ebp+8) "31/xor %edx 2/r32/edx\n")
    28898     (emit-indent *(ebp+8) *Curr-block-depth)
    28899     (write-buffered *(ebp+8) "b9/copy-to-ecx ")
    28900     (write-int32-hex-buffered *(ebp+8) %ecx)
    28901     (write-buffered *(ebp+8) "/imm32\n")
    28902     (emit-indent *(ebp+8) *Curr-block-depth)
    28903     (write-buffered *(ebp+8) "f7 7/subop/idiv-eax-edx-by %ecx\n")
    28904     {
    28905       (string-equal? %edx "eax")  # => eax
    28906       3d/compare-eax-and 0/imm32/false
    28907       75/break-if-!= break/disp8
    28908       (emit-indent *(ebp+8) *Curr-block-depth)
    28909       (write-buffered *(ebp+8) "89/<- %")
    28910       (write-buffered *(ebp+8) %edx)
    28911       (write-buffered *(ebp+8) " 0/r32/eax\n")
    28912     }
    28913     # . emit register restores
    28914     {
    28915       (string-equal? %edx "edx")  # => eax
    28916       3d/compare-eax-and 0/imm32/false
    28917       75/break-if-!= break/disp8
    28918       (emit-indent *(ebp+8) *Curr-block-depth)
    28919       (write-buffered *(ebp+8) "5a/pop-to-edx\n")
    28920     }
    28921     {
    28922       (string-equal? %edx "ecx")  # => eax
    28923       3d/compare-eax-and 0/imm32/false
    28924       75/break-if-!= break/disp8
    28925       (emit-indent *(ebp+8) *Curr-block-depth)
    28926       (write-buffered *(ebp+8) "59/pop-to-ecx\n")
    28927     }
    28928     {
    28929       (string-equal? %edx "eax")  # => eax
    28930       3d/compare-eax-and 0/imm32/false
    28931       75/break-if-!= break/disp8
    28932       (emit-indent *(ebp+8) *Curr-block-depth)
    28933       (write-buffered *(ebp+8) "58/pop-to-eax\n")
    28934     }
    28935 $translate-mu-length-stmt:end:
    28936     # . restore registers
    28937     5e/pop-to-esi
    28938     5b/pop-to-ebx
    28939     5a/pop-to-edx
    28940     59/pop-to-ecx
    28941     58/pop-to-eax
    28942     # . epilogue
    28943     89/<- %esp 5/r32/ebp
    28944     5d/pop-to-ebp
    28945     c3/return
    28946
    28947 array-element-size:  # arr: (addr var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
    28948     # . prologue
    28949     55/push-ebp
    28950     89/<- %ebp 4/r32/esp
    28951     #
    28952     (array-element-type-id *(ebp+8) *(ebp+0xc) *(ebp+0x10))  # => eax
    28953     (size-of-type-id-as-array-element %eax)  # => eax
    28954 $array-element-size:end:
    28955     # . epilogue
    28956     89/<- %esp 5/r32/ebp
    28957     5d/pop-to-ebp
    28958     c3/return
    28959
    28960 array-element-type-id:  # v: (addr var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: type-id
    28961     # precondition: n is positive
    28962     # . prologue
    28963     55/push-ebp
    28964     89/<- %ebp 4/r32/esp
    28965     #
    28966     8b/-> *(ebp+8) 0/r32/eax
    28967     # var t/eax: (addr type-tree)
    28968     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    28969     # if t == 0 abort
    28970     3d/compare-eax-with 0/imm32
    28971     0f 84/jump-if-== $array-element-type-id:error0/disp32
    28972     # if t->is-atom? abort
    28973     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
    28974     0f 85/jump-if-!= $array-element-type-id:error1/disp32
    28975     # if (t->left == addr) t = t->right
    28976     {
    28977       50/push-eax
    28978       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    28979       (simple-mu-type? %eax 2)  # addr => eax
    28980       3d/compare-eax-with 0/imm32/false
    28981       58/pop-to-eax
    28982       74/jump-if-= break/disp8
    28983 $array-element-type-id:skip-addr:
    28984       (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
    28985     }
    28986     # if t == 0 abort
    28987     3d/compare-eax-with 0/imm32
    28988     0f 84/jump-if-= $array-element-type-id:error2/disp32
    28989     # if t->is-atom? abort
    28990     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
    28991     0f 85/jump-if-!= $array-element-type-id:error2/disp32
    28992     # if t->left != array abort
    28993     {
    28994       50/push-eax
    28995       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    28996       (simple-mu-type? %eax 3)  # array => eax
    28997       3d/compare-eax-with 0/imm32/false
    28998       58/pop-to-eax
    28999 $array-element-type-id:no-array:
    29000       0f 84/jump-if-= $array-element-type-id:error2/disp32
    29001     }
    29002 $array-element-type-id:skip-array:
    29003     # t = t->right
    29004     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
    29005     # if t == 0 abort
    29006     3d/compare-eax-with 0/imm32
    29007     0f 84/jump-if-= $array-element-type-id:error2/disp32
    29008     # if t->is-atom? abort
    29009     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
    29010     0f 85/jump-if-!= $array-element-type-id:error2/disp32
    29011     # t = t->left
    29012     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    29013     # if (!t->is-atom?) t = t->left     # TODO: assumes array element size can be determined from just first word of array element type
    29014     # if (t->is-atom == false) t = lookup(t->left)
    29015     {
    29016       81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
    29017       75/jump-if-!= break/disp8
    29018       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    29019     }
    29020     # return t->value
    29021     8b/-> *(eax+4) 0/r32/eax  # Type-tree-value
    29022 $array-element-type-id:end:
    29023     # . epilogue
    29024     89/<- %esp 5/r32/ebp
    29025     5d/pop-to-ebp
    29026     c3/return
    29027
    29028 $array-element-type-id:error0:
    29029     (write-buffered *(ebp+0xc) "array-element-type-id: var '")
    29030     50/push-eax
    29031     8b/-> *(ebp+8) 0/r32/eax
    29032     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    29033     (write-buffered *(ebp+0xc) %eax)
    29034     58/pop-to-eax
    29035     (write-buffered *(ebp+0xc) "' has no type\n")
    29036     (flush *(ebp+0xc))
    29037     (stop *(ebp+0x10) 1)
    29038     # never gets here
    29039
    29040 $array-element-type-id:error1:
    29041     (write-buffered *(ebp+0xc) "array-element-type-id: var '")
    29042     50/push-eax
    29043     8b/-> *(ebp+8) 0/r32/eax
    29044     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    29045     (write-buffered *(ebp+0xc) %eax)
    29046     58/pop-to-eax
    29047     (write-buffered *(ebp+0xc) "' has atomic type ")
    29048     (write-int32-hex-buffered *(ebp+0xc) *(eax+4))  # Type-tree-value
    29049     (write-buffered *(ebp+0xc) Newline)
    29050     (flush *(ebp+0xc))
    29051     (stop *(ebp+0x10) 1)
    29052     # never gets here
    29053
    29054 $array-element-type-id:error2:
    29055     (write-buffered *(ebp+0xc) "array-element-type-id: var '")
    29056     50/push-eax
    29057     8b/-> *(ebp+8) 0/r32/eax
    29058     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    29059     (write-buffered *(ebp+0xc) %eax)
    29060     58/pop-to-eax
    29061     (write-buffered *(ebp+0xc) "' has non-array type\n")
    29062     (flush *(ebp+0xc))
    29063     (stop *(ebp+0x10) 1)
    29064     # never gets here
    29065
    29066 size-of-type-id-as-array-element:  # t: type-id -> result/eax: int
    29067     # . prologue
    29068     55/push-ebp
    29069     89/<- %ebp 4/r32/esp
    29070     # eax = t
    29071     8b/-> *(ebp+8) 0/r32/eax
    29072     # if t is 'byte', size is 1
    29073     3d/compare-eax-and 8/imm32/byte
    29074     {
    29075       75/jump-if-!= break/disp8
    29076       b8/copy-to-eax 1/imm32
    29077       eb/jump $size-of-type-id-as-array-element:end/disp8
    29078     }
    29079     # otherwise proceed as usual
    29080     (size-of-type-id %eax)  # => eax
    29081 $size-of-type-id-as-array-element:end:
    29082     # . epilogue
    29083     89/<- %esp 5/r32/ebp
    29084     5d/pop-to-ebp
    29085     c3/return
    29086
    29087 stream-element-type-id:  # type: (addr type-tree), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: type-id
    29088     # precondition: n is positive
    29089     # . prologue
    29090     55/push-ebp
    29091     89/<- %ebp 4/r32/esp
    29092     # eax = type
    29093     8b/-> *(ebp+8) 0/r32/eax
    29094     # if type == 0 abort
    29095     3d/compare-eax-with 0/imm32
    29096     0f 84/jump-if-== $stream-element-type-id:error0/disp32
    29097     # if type->is-atom? abort
    29098     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
    29099     0f 85/jump-if-!= $stream-element-type-id:error1/disp32
    29100     # if (type->left == addr) type = type->right
    29101     {
    29102       50/push-eax
    29103       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    29104       (simple-mu-type? %eax 2)  # addr => eax
    29105       3d/compare-eax-with 0/imm32/false
    29106       58/pop-to-eax
    29107       74/jump-if-= break/disp8
    29108 $stream-element-type-id:skip-addr:
    29109       (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
    29110     }
    29111     # if type == 0 abort
    29112     3d/compare-eax-with 0/imm32
    29113     0f 84/jump-if-= $stream-element-type-id:error2/disp32
    29114     # if type->is-atom? abort
    29115     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
    29116     0f 85/jump-if-!= $stream-element-type-id:error2/disp32
    29117     # if type->left != stream abort
    29118     {
    29119       50/push-eax
    29120       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    29121       (simple-mu-type? %eax 0xb)  # stream => eax
    29122       3d/compare-eax-with 0/imm32/false
    29123       58/pop-to-eax
    29124 $stream-element-type-id:no-stream:
    29125       0f 84/jump-if-= $stream-element-type-id:error2/disp32
    29126     }
    29127 $stream-element-type-id:skip-stream:
    29128     # type = type->right
    29129     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
    29130     # if type == 0 abort
    29131     3d/compare-eax-with 0/imm32
    29132     0f 84/jump-if-= $stream-element-type-id:error2/disp32
    29133     # if type->is-atom? abort
    29134     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
    29135     0f 85/jump-if-!= $stream-element-type-id:error2/disp32
    29136     # t = type->left
    29137     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    29138     # if (!type->is-atom?) type = type->left     # TODO: assumes stream element size can be determined from just first word of stream element type
    29139     {
    29140       81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
    29141       75/jump-if-!= break/disp8
    29142       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    29143     }
    29144     # return type->value
    29145     8b/-> *(eax+4) 0/r32/eax  # Type-tree-value
    29146 $stream-element-type-id:end:
    29147     # . epilogue
    29148     89/<- %esp 5/r32/ebp
    29149     5d/pop-to-ebp
    29150     c3/return
    29151
    29152 $stream-element-type-id:error0:
    29153     (write-buffered *(ebp+0xc) "stream-element-type-id: var '")
    29154     50/push-eax
    29155     8b/-> *(ebp+8) 0/r32/eax
    29156     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    29157     (write-buffered *(ebp+0xc) %eax)
    29158     58/pop-to-eax
    29159     (write-buffered *(ebp+0xc) "' has no type\n")
    29160     (flush *(ebp+0xc))
    29161     (stop *(ebp+0x10) 1)
    29162     # never gets here
    29163
    29164 $stream-element-type-id:error1:
    29165     (write-buffered *(ebp+0xc) "stream-element-type-id: var '")
    29166     50/push-eax
    29167     8b/-> *(ebp+8) 0/r32/eax
    29168     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    29169     (write-buffered *(ebp+0xc) %eax)
    29170     58/pop-to-eax
    29171     (write-buffered *(ebp+0xc) "' has atomic type ")
    29172     (write-int32-hex-buffered *(ebp+0xc) *(eax+4))  # Type-tree-value
    29173     (write-buffered *(ebp+0xc) Newline)
    29174     (flush *(ebp+0xc))
    29175     (stop *(ebp+0x10) 1)
    29176     # never gets here
    29177
    29178 $stream-element-type-id:error2:
    29179     (write-buffered *(ebp+0xc) "stream-element-type-id: var '")
    29180     50/push-eax
    29181     8b/-> *(ebp+8) 0/r32/eax
    29182     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    29183     (write-buffered *(ebp+0xc) %eax)
    29184     58/pop-to-eax
    29185     (write-buffered *(ebp+0xc) "' has non-stream type\n")
    29186     (flush *(ebp+0xc))
    29187     (stop *(ebp+0x10) 1)
    29188     # never gets here
    29189
    29190 emit-save-size-to:  # out: (addr buffered-file), base: (addr var), outreg: (addr array byte)
    29191     # . prologue
    29192     55/push-ebp
    29193     89/<- %ebp 4/r32/esp
    29194     # . save registers
    29195     50/push-eax
    29196     53/push-ebx
    29197     # ebx = base
    29198     8b/-> *(ebp+0xc) 3/r32/ebx
    29199     (emit-indent *(ebp+8) *Curr-block-depth)
    29200     (write-buffered *(ebp+8) "8b/-> *")
    29201     # if base is an (addr array ...) in a register
    29202     {
    29203       81 7/subop/compare *(ebx+0x18)) 0/imm32  # Var-register
    29204       74/jump-if-= break/disp8
    29205 $emit-save-size-to:emit-base-from-register:
    29206       (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
    29207       (write-buffered *(ebp+8) %eax)
    29208       eb/jump $emit-save-size-to:emit-output/disp8
    29209     }
    29210     # otherwise if base is an (array ...) on the stack
    29211     {
    29212       81 7/subop/compare *(ebx+0x14)) 0/imm32  # Var-offset
    29213       74/jump-if-= break/disp8
    29214 $emit-save-size-to:emit-base-from-stack:
    29215       (write-buffered *(ebp+8) "(ebp+")
    29216       (write-int32-hex-buffered *(ebp+8) *(ebx+0x14))  # Var-offset
    29217       (write-buffered *(ebp+8) ")")
    29218     }
    29219 $emit-save-size-to:emit-output:
    29220     (write-buffered *(ebp+8) " ")
    29221     (get Mu-registers *(ebp+0x10) 0xc "Mu-registers")  # => eax
    29222     (write-int32-hex-buffered *(ebp+8) *eax)
    29223     (write-buffered *(ebp+8) "/r32\n")
    29224 $emit-save-size-to:end:
    29225     # . restore registers
    29226     5b/pop-to-ebx
    29227     58/pop-to-eax
    29228     # . epilogue
    29229     89/<- %esp 5/r32/ebp
    29230     5d/pop-to-ebp
    29231     c3/return
    29232
    29233 emit-divide-by-shift-right:  # out: (addr buffered-file), reg: (addr array byte), size: int
    29234     # . prologue
    29235     55/push-ebp
    29236     89/<- %ebp 4/r32/esp
    29237     # . save registers
    29238     50/push-eax
    29239     #
    29240     (emit-indent *(ebp+8) *Curr-block-depth)
    29241     (write-buffered *(ebp+8) "c1/shift 5/subop/>> %")
    29242     (write-buffered *(ebp+8) *(ebp+0xc))
    29243     (write-buffered *(ebp+8) Space)
    29244     (num-shift-rights *(ebp+0x10))  # => eax
    29245     (write-int32-hex-buffered *(ebp+8) %eax)
    29246     (write-buffered *(ebp+8) "/imm8\n")
    29247 $emit-divide-by-shift-right:end:
    29248     # . restore registers
    29249     58/pop-to-eax
    29250     # . epilogue
    29251     89/<- %esp 5/r32/ebp
    29252     5d/pop-to-ebp
    29253     c3/return
    29254
    29255 translate-mu-copy-byte-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
    29256     # . prologue
    29257     55/push-ebp
    29258     89/<- %ebp 4/r32/esp
    29259     # . save registers
    29260     50/push-eax
    29261     56/push-esi
    29262     # esi = stmt
    29263     8b/-> *(ebp+0xc) 6/r32/esi
    29264     #
    29265     (emit-indent *(ebp+8) *Curr-block-depth)
    29266     (write-buffered *(ebp+8) "8a/byte->")
    29267     # emit stmt->inouts[0]
    29268     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    29269     (emit-subx-var-as-rm32 *(ebp+8) %eax)
    29270     # emit /r32 for stmt->outputs[0]->register
    29271     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    29272     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    29273     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    29274     (maybe-get Mu-registers %eax 0xc)  # => eax: (addr register-index)
    29275     (write-buffered *(ebp+8) Space)
    29276     (write-int32-hex-buffered *(ebp+8) *eax)
    29277     (write-buffered *(ebp+8) "/r32\n")
    29278     # clear rest of register
    29279     (emit-indent *(ebp+8) *Curr-block-depth)
    29280     (write-buffered *(ebp+8) "81 4/subop/and %")
    29281     8b/-> *(ebp+0xc) 0/r32/eax
    29282     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    29283     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    29284     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    29285     (write-buffered *(ebp+8) %eax)
    29286     (write-buffered *(ebp+8) " 0xff/imm32\n")
    29287 $translate-mu-copy-byte-stmt:end:
    29288     # . restore registers
    29289     5e/pop-to-esi
    29290     58/pop-to-eax
    29291     # . epilogue
    29292     89/<- %esp 5/r32/ebp
    29293     5d/pop-to-ebp
    29294     c3/return
    29295
    29296 # a little different from other translate- functions; notice the extra 'fn' argument
    29297 translate-mu-index-stmt:  # out: (addr buffered-file), stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    29298     # . prologue
    29299     55/push-ebp
    29300     89/<- %ebp 4/r32/esp
    29301     # . save registers
    29302     53/push-ebx
    29303     # ebx = stmt
    29304     8b/-> *(ebp+0xc) 3/r32/ebx
    29305     # var base/ebx: (addr var) = stmt->inouts[0]
    29306     (lookup *(ebx+0xc) *(ebx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    29307     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    29308     89/<- %ebx 0/r32/eax
    29309     # emit bounds-check
    29310     (emit-mu-index-bounds-check *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14) *(ebp+0x18))
    29311     # if (var->register) do one thing
    29312     {
    29313       81 7/subop/compare *(ebx+0x18) 0/imm32  # Var-register
    29314       74/jump-if-= break/disp8
    29315       # TODO: ensure there's no dereference
    29316       (translate-mu-index-stmt-with-array-in-register *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))
    29317       eb/jump $translate-mu-index-stmt:end/disp8
    29318     }
    29319     # if (var->offset) do a different thing
    29320     {
    29321       81 7/subop/compare *(ebx+0x14) 0/imm32  # Var-offset
    29322       74/jump-if-= break/disp8
    29323       # TODO: ensure there's no dereference
    29324       (translate-mu-index-stmt-with-array-on-stack *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))
    29325       eb/jump $translate-mu-index-stmt:end/disp8
    29326     }
    29327 $translate-mu-index-stmt:end:
    29328     # . restore registers
    29329     5b/pop-to-ebx
    29330     # . epilogue
    29331     89/<- %esp 5/r32/ebp
    29332     5d/pop-to-ebp
    29333     c3/return
    29334
    29335 $translate-mu-index-stmt:error1:
    29336     (write-buffered *(ebp+0x14) "couldn't translate an index instruction. second (index) input must either lie in a register or be a literal\n")
    29337     (flush *(ebp+0x14))
    29338     (stop *(ebp+0x18) 1)
    29339     # never gets here
    29340
    29341 $translate-mu-index-stmt:error2:
    29342     (write-buffered *(ebp+0x14) "couldn't translate an index instruction. second (index) input when in a register must be an int or offset\n")
    29343     (flush *(ebp+0x14))
    29344     (stop *(ebp+0x18) 1)
    29345     # never gets here
    29346
    29347 emit-mu-index-bounds-check:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
    29348     # . prologue
    29349     55/push-ebp
    29350     89/<- %ebp 4/r32/esp
    29351     # . save registers
    29352     50/push-eax
    29353     51/push-ecx
    29354     52/push-edx
    29355     53/push-ebx
    29356     # ecx = stmt
    29357     8b/-> *(ebp+0xc) 1/r32/ecx
    29358     #
    29359     (emit-indent *(ebp+8) *Curr-block-depth)
    29360     (write-buffered *(ebp+8) "(__check-mu-array-bounds ")
    29361 $emit-mu-index-bounds-check:compute-base:
    29362     # var base/ebx: (addr var) = inouts[0]
    29363     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    29364     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    29365     89/<- %ebx 0/r32/eax
    29366 $emit-mu-index-bounds-check:emit-index:
    29367     # var index/edx: (addr var) = inouts[1]
    29368     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    29369     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    29370     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    29371     89/<- %edx 0/r32/eax
    29372     # if index->register, print its code
    29373     81 7/subop/compare *(edx+0x18) 0/imm32  # Var-register
    29374     {
    29375       0f 84/jump-if-= break/disp32
    29376 $emit-mu-index-bounds-check:emit-register-index:
    29377       (write-buffered *(ebp+8) "%")
    29378       (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
    29379       (write-buffered *(ebp+8) %eax)
    29380       eb/jump $emit-mu-index-bounds-check:index-done/disp8
    29381     }
    29382     # otherwise if index is a literal, print it
    29383 $emit-mu-index-bounds-check:emit-literal-index:
    29384     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
    29385     (simple-mu-type? %eax 0)  # => eax
    29386     3d/compare-eax-and 0/imm32/false
    29387     {
    29388       0f 84/jump-if-= break/disp32
    29389       (lookup *edx *(edx+4))  # Var-name Var-name => eax
    29390       (write-buffered *(ebp+8) %eax)
    29391     }
    29392 $emit-mu-index-bounds-check:index-done:
    29393     (write-buffered *(ebp+8) " ")
    29394 $emit-mu-index-bounds-check:emit-element-size:
    29395     # if index is a literal or int, print size of array element
    29396     {
    29397       {
    29398         (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
    29399         (simple-mu-type? %eax 0)  # literal => eax
    29400         3d/compare-eax-and 0/imm32/false
    29401         75/jump-if-!= break/disp8
    29402         (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
    29403         (simple-mu-type? %eax 1)  # int => eax
    29404         3d/compare-eax-and 0/imm32/false
    29405         75/jump-if-!= break/disp8
    29406         eb/jump $emit-mu-index-bounds-check:emit-element-size-offset/disp8
    29407       }
    29408 $emit-mu-index-bounds-check:emit-int-register-index:
    29409       (array-element-size %ebx *(ebp+0x14) *(ebp+0x18))  # => eax
    29410       (write-int32-hex-buffered *(ebp+8) %eax)
    29411       e9/jump $emit-mu-index-bounds-check:emit-base/disp32
    29412     }
    29413 $emit-mu-index-bounds-check:emit-element-size-offset:
    29414     # if index has type (offset ...), print "1"
    29415     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
    29416     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
    29417     {
    29418       75/jump-if-!= break/disp8
    29419       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    29420       (simple-mu-type? %eax 7)  # => eax
    29421       3d/compare-eax-and 0/imm32/false
    29422       {
    29423         0f 84/jump-if-= break/disp32
    29424 $emit-mu-index-bounds-check:emit-offset-register-index:
    29425         (write-buffered *(ebp+8) "1")
    29426       }
    29427     }
    29428 $emit-mu-index-bounds-check:emit-base:
    29429     # if base is in a register, print " *" base->register
    29430     81 7/subop/compare *(ebx+0x18) 0/imm32  # Var-register
    29431     {
    29432       74/jump-if-= break/disp8
    29433       (write-buffered *(ebp+8) " *")
    29434       (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
    29435       (write-buffered *(ebp+8) %eax)
    29436       e9/jump $emit-mu-index-bounds-check:emit-function-name/disp32
    29437     }
    29438     # otherwise print " *(ebp+" base->offset ")"
    29439     (write-buffered *(ebp+8) " *(ebp+")
    29440     (write-int32-hex-buffered *(ebp+8) *(ebx+0x14))  # Var-offset
    29441     (write-buffered *(ebp+8) ")")
    29442 $emit-mu-index-bounds-check:emit-function-name:
    29443     # " \"" function-name "\""
    29444     (write-buffered *(ebp+8) " \"")
    29445     8b/-> *(ebp+0x10) 1/r32/ecx
    29446     (lookup *ecx *(ecx+4))  # Function-name Function-name => eax
    29447     (write-buffered *(ebp+8) %eax)
    29448     (write-buffered *(ebp+8) "\"")
    29449 $emit-mu-index-bounds-check:emit-array-name:
    29450     # " \"" base->name "\""
    29451     (write-buffered *(ebp+8) " \"")
    29452     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
    29453     (write-buffered *(ebp+8) %eax)
    29454     (write-buffered *(ebp+8) "\")\n")
    29455 $emit-mu-index-bounds-check:end:
    29456     # . restore registers
    29457     5b/pop-to-ebx
    29458     5a/pop-to-edx
    29459     59/pop-to-ecx
    29460     58/pop-to-eax
    29461     # . epilogue
    29462     89/<- %esp 5/r32/ebp
    29463     5d/pop-to-ebp
    29464     c3/return
    29465
    29466 translate-mu-index-stmt-with-array-in-register:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
    29467     # . prologue
    29468     55/push-ebp
    29469     89/<- %ebp 4/r32/esp
    29470     # . save registers
    29471     50/push-eax
    29472     51/push-ecx
    29473     52/push-edx
    29474     53/push-ebx
    29475     #
    29476     (emit-indent *(ebp+8) *Curr-block-depth)
    29477     (write-buffered *(ebp+8) "8d/copy-address *(")
    29478     # TODO: ensure inouts[0] is in a register and not dereferenced
    29479 $translate-mu-index-stmt-with-array-in-register:emit-base:
    29480     # ecx = stmt
    29481     8b/-> *(ebp+0xc) 1/r32/ecx
    29482     # var base/ebx: (addr var) = inouts[0]
    29483     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    29484     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    29485     89/<- %ebx 0/r32/eax
    29486     # print base->register " + "
    29487     (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
    29488     (write-buffered *(ebp+8) %eax)
    29489     (write-buffered *(ebp+8) " + ")
    29490     # var index/edx: (addr var) = inouts[1]
    29491     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    29492     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    29493     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    29494     89/<- %edx 0/r32/eax
    29495     # if index->register
    29496     81 7/subop/compare *(edx+0x18) 0/imm32  # Var-register
    29497     {
    29498       0f 84/jump-if-= break/disp32
    29499 $translate-mu-index-stmt-with-array-in-register:emit-register-index:
    29500       # if index is an int
    29501       (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
    29502       (simple-mu-type? %eax 1)  # int => eax
    29503       3d/compare-eax-and 0/imm32/false
    29504       {
    29505         0f 84/jump-if-= break/disp32
    29506 $translate-mu-index-stmt-with-array-in-register:emit-int-register-index:
    29507         # print index->register "<<" log2(array-element-size(base)) " + 4) "
    29508         # . index->register "<<"
    29509         (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
    29510         (write-buffered *(ebp+8) %eax)
    29511         (write-buffered *(ebp+8) "<<")
    29512         # . log2(array-element-size(base->type))
    29513         # we know size is a power of 2
    29514         (array-element-size %ebx *(ebp+0x10) *(ebp+0x14))  # => eax
    29515         (num-shift-rights %eax)  # => eax
    29516         (write-int32-hex-buffered *(ebp+8) %eax)
    29517         e9/jump $translate-mu-index-stmt-with-array-in-register:emit-register-index-done/disp32
    29518       }
    29519       # if index->type is any other atom, abort
    29520       (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
    29521       81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
    29522       0f 85/jump-if-!= $translate-mu-index-stmt:error2/disp32
    29523       # if index has type (offset ...)
    29524       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    29525       (simple-mu-type? %eax 7)  # => eax
    29526       3d/compare-eax-and 0/imm32/false
    29527       {
    29528         0f 84/jump-if-= break/disp32
    29529         # print index->register
    29530 $translate-mu-index-stmt-with-array-in-register:emit-offset-register-index:
    29531         (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
    29532         (write-buffered *(ebp+8) %eax)
    29533       }
    29534 $translate-mu-index-stmt-with-array-in-register:emit-register-index-done:
    29535       (write-buffered *(ebp+8) " + 4) ")
    29536       e9/jump $translate-mu-index-stmt-with-array-in-register:emit-output/disp32
    29537     }
    29538     # otherwise if index is a literal
    29539     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
    29540     (simple-mu-type? %eax 0)  # => eax
    29541     3d/compare-eax-and 0/imm32/false
    29542     {
    29543       0f 84/jump-if-= break/disp32
    29544 $translate-mu-index-stmt-with-array-in-register:emit-literal-index:
    29545       # var index-value/edx: int = parse-hex-int(index->name)
    29546       (lookup *edx *(edx+4))  # Var-name Var-name => eax
    29547       (parse-hex-int %eax)  # => eax
    29548       89/<- %edx 0/r32/eax
    29549       # offset = idx-value * array-element-size(base->type)
    29550       (array-element-size %ebx *(ebp+0x10) *(ebp+0x14))  # => eax
    29551       f7 4/subop/multiply-into-edx-eax %edx  # clobbers edx
    29552       # offset += 4 for array size
    29553       05/add-to-eax 4/imm32
    29554       # TODO: check edx for overflow
    29555       # print offset
    29556       (write-int32-hex-buffered *(ebp+8) %eax)
    29557       (write-buffered *(ebp+8) ") ")
    29558       e9/jump $translate-mu-index-stmt-with-array-in-register:emit-output/disp32
    29559     }
    29560     # otherwise abort
    29561     e9/jump $translate-mu-index-stmt:error1/disp32
    29562 $translate-mu-index-stmt-with-array-in-register:emit-output:
    29563     # outputs[0] "/r32"
    29564     8b/-> *(ebp+0xc) 1/r32/ecx
    29565     (lookup *(ecx+0x14) *(ecx+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    29566     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    29567     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    29568     (get Mu-registers %eax 0xc "Mu-registers")  # => eax: (addr int)
    29569     (write-int32-hex-buffered *(ebp+8) *eax)
    29570     (write-buffered *(ebp+8) "/r32\n")
    29571 $translate-mu-index-stmt-with-array-in-register:end:
    29572     # . restore registers
    29573     5b/pop-to-ebx
    29574     5a/pop-to-edx
    29575     59/pop-to-ecx
    29576     58/pop-to-eax
    29577     # . epilogue
    29578     89/<- %esp 5/r32/ebp
    29579     5d/pop-to-ebp
    29580     c3/return
    29581
    29582 translate-mu-index-stmt-with-array-on-stack:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
    29583     # . prologue
    29584     55/push-ebp
    29585     89/<- %ebp 4/r32/esp
    29586     # . save registers
    29587     50/push-eax
    29588     51/push-ecx
    29589     52/push-edx
    29590     53/push-ebx
    29591     #
    29592     (emit-indent *(ebp+8) *Curr-block-depth)
    29593     (write-buffered *(ebp+8) "8d/copy-address *(ebp + ")
    29594     # var curr/edx: (addr stmt-var) = lookup(stmt->inouts)
    29595     8b/-> *(ebp+0xc) 0/r32/eax
    29596     (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    29597     89/<- %edx 0/r32/eax
    29598     # var base/ecx: (addr var) = lookup(curr->value)
    29599     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    29600     89/<- %ecx 0/r32/eax
    29601     # var curr2/eax: (addr stmt-var) = lookup(curr->next)
    29602     (lookup *(edx+8) *(edx+0xc))  # Stmt-var-next Stmt-var-next => eax
    29603     # var index/edx: (handle var) = curr2->value
    29604     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    29605     89/<- %edx 0/r32/eax
    29606     # if index->register
    29607     81 7/subop/compare *(edx+0x18) 0/imm32  # Var-register
    29608     {
    29609       0f 84/jump-if-= break/disp32
    29610 $translate-mu-index-stmt-with-array-on-stack:emit-register-index:
    29611       # if index is an int
    29612       (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
    29613       (simple-mu-type? %eax 1)  # int => eax
    29614       3d/compare-eax-and 0/imm32/false
    29615       {
    29616         0f 84/jump-if-= break/disp32
    29617 $translate-mu-index-stmt-with-array-on-stack:emit-int-register-index:
    29618         # print index->register "<<" log2(array-element-size(base)) " + " base->offset+4
    29619         # . inouts[1]->register "<<"
    29620         (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
    29621         (write-buffered *(ebp+8) %eax)
    29622         (write-buffered *(ebp+8) "<<")
    29623         # . log2(array-element-size(base))
    29624         # TODO: ensure size is a power of 2
    29625         (array-element-size %ecx *(ebp+0x10) *(ebp+0x14))  # => eax
    29626         (num-shift-rights %eax)  # => eax
    29627         (write-int32-hex-buffered *(ebp+8) %eax)
    29628         #
    29629         (write-buffered *(ebp+8) " + ")
    29630         #
    29631         8b/-> *(ecx+0x14) 0/r32/eax  # Var-offset
    29632         05/add-to-eax 4/imm32  # for array length
    29633         (write-int32-hex-buffered *(ebp+8) %eax)
    29634         e9/jump $translate-mu-index-stmt-with-array-on-stack:emit-register-index-done/disp32
    29635       }
    29636       # if index->type is any other atom, abort
    29637       (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
    29638       81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
    29639       0f 85/jump-if-!= $translate-mu-index-stmt:error2/disp32
    29640       # if index has type (offset ...)
    29641       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    29642       (simple-mu-type? %eax 7)  # => eax
    29643       3d/compare-eax-and 0/imm32/false
    29644       {
    29645         0f 84/jump-if-= break/disp32
    29646         # print index->register
    29647 $translate-mu-index-stmt-with-array-on-stack:emit-offset-register-index:
    29648         (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
    29649         (write-buffered *(ebp+8) %eax)
    29650       }
    29651 $translate-mu-index-stmt-with-array-on-stack:emit-register-index-done:
    29652       (write-buffered *(ebp+8) ") ")
    29653       e9/jump $translate-mu-index-stmt-with-array-on-stack:emit-output/disp32
    29654     }
    29655     # otherwise if index is a literal
    29656     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
    29657     (simple-mu-type? %eax 0)  # => eax
    29658     3d/compare-eax-and 0/imm32/false
    29659     {
    29660       0f 84/jump-if-= break/disp32
    29661 $translate-mu-index-stmt-with-array-on-stack:emit-literal-index:
    29662       # var idx-value/edx: int = parse-hex-int(index->name)
    29663       (lookup *edx *(edx+4))  # Var-name Var-name => eax
    29664       (parse-hex-int %eax)  # Var-name => eax
    29665       89/<- %edx 0/r32/eax
    29666       # offset = idx-value * array-element-size(base)
    29667       (array-element-size %ecx *(ebp+0x10) *(ebp+0x14))  # => eax
    29668       f7 4/subop/multiply-into-edx-eax %edx  # clobbers edx
    29669       # offset += base->offset
    29670       03/add *(ecx+0x14) 0/r32/eax  # Var-offset
    29671       # offset += 4 for array size
    29672       05/add-to-eax 4/imm32
    29673       # TODO: check edx for overflow
    29674       # print offset
    29675       (write-int32-hex-buffered *(ebp+8) %eax)
    29676       (write-buffered *(ebp+8) ") ")
    29677       e9/jump $translate-mu-index-stmt-with-array-on-stack:emit-output/disp32
    29678     }
    29679     # otherwise abort
    29680     e9/jump $translate-mu-index-stmt:error1/disp32
    29681 $translate-mu-index-stmt-with-array-on-stack:emit-output:
    29682     # outputs[0] "/r32"
    29683     8b/-> *(ebp+0xc) 0/r32/eax
    29684     (lookup *(eax+0x14) *(eax+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    29685     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    29686     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    29687     (get Mu-registers %eax 0xc "Mu-registers")  # => eax: (addr int)
    29688     (write-int32-hex-buffered *(ebp+8) *eax)
    29689     (write-buffered *(ebp+8) "/r32\n")
    29690 $translate-mu-index-stmt-with-array-on-stack:end:
    29691     # . restore registers
    29692     5b/pop-to-ebx
    29693     5a/pop-to-edx
    29694     59/pop-to-ecx
    29695     58/pop-to-eax
    29696     # . epilogue
    29697     89/<- %esp 5/r32/ebp
    29698     5d/pop-to-ebp
    29699     c3/return
    29700
    29701 translate-mu-compute-index-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
    29702     # . prologue
    29703     55/push-ebp
    29704     89/<- %ebp 4/r32/esp
    29705     # . save registers
    29706     50/push-eax
    29707     51/push-ecx
    29708     52/push-edx
    29709     53/push-ebx
    29710     #
    29711     (emit-indent *(ebp+8) *Curr-block-depth)
    29712     (write-buffered *(ebp+8) "69/multiply")
    29713     # ecx = stmt
    29714     8b/-> *(ebp+0xc) 1/r32/ecx
    29715     # var first-inout/ebx: (addr stmt-var) = stmt->inouts[0]
    29716     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    29717     89/<- %ebx 0/r32/eax
    29718 $translate-mu-compute-index-stmt:emit-index:
    29719     (lookup *(ebx+8) *(ebx+0xc))  # Stmt-var-next Stmt-var-next => eax
    29720     (emit-subx-var-as-rm32 *(ebp+8) %eax)
    29721     (write-buffered *(ebp+8) Space)
    29722 $translate-mu-compute-index-stmt:emit-elem-size:
    29723     # var base/ebx: (addr var)
    29724     (lookup *ebx *(ebx+4))  # Stmt-var-value Stmt-var-value => eax
    29725     89/<- %ebx 0/r32/eax
    29726     # print array-element-size(base)
    29727     (array-element-size %ebx *(ebp+0x10) *(ebp+0x14))  # => eax
    29728     (write-int32-hex-buffered *(ebp+8) %eax)
    29729     (write-buffered *(ebp+8) "/imm32 ")
    29730 $translate-mu-compute-index-stmt:emit-output:
    29731     # outputs[0] "/r32"
    29732     (lookup *(ecx+0x14) *(ecx+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    29733     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    29734     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    29735     (get Mu-registers %eax 0xc "Mu-registers")  # => eax: (addr int)
    29736     (write-int32-hex-buffered *(ebp+8) *eax)
    29737     (write-buffered *(ebp+8) "/r32\n")
    29738 $translate-mu-compute-index-stmt:end:
    29739     # . restore registers
    29740     5b/pop-to-ebx
    29741     5a/pop-to-edx
    29742     59/pop-to-ecx
    29743     58/pop-to-eax
    29744     # . epilogue
    29745     89/<- %esp 5/r32/ebp
    29746     5d/pop-to-ebp
    29747     c3/return
    29748
    29749 translate-mu-get-stmt:  # out: (addr buffered-file), stmt: (addr stmt)
    29750     # . prologue
    29751     55/push-ebp
    29752     89/<- %ebp 4/r32/esp
    29753     # . save registers
    29754     50/push-eax
    29755     51/push-ecx
    29756     52/push-edx
    29757     #
    29758     (emit-indent *(ebp+8) *Curr-block-depth)
    29759     (write-buffered *(ebp+8) "8d/copy-address ")
    29760     # ecx = stmt
    29761     8b/-> *(ebp+0xc) 1/r32/ecx
    29762     # var offset/edx: int = get offset of stmt
    29763     (mu-get-offset %ecx)  # => eax
    29764     89/<- %edx 0/r32/eax
    29765     # var base/eax: (addr var) = stmt->inouts->value
    29766     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    29767     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    29768     # if base is in a register
    29769     81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
    29770     {
    29771       0f 84/jump-if-= break/disp32
    29772 $translate-mu-get-stmt:emit-register-input:
    29773       # emit "*(" base->register " + " offset ") "
    29774       (write-buffered *(ebp+8) "*(")
    29775       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    29776       (write-buffered *(ebp+8) %eax)
    29777       (write-buffered *(ebp+8) " + ")
    29778       (write-int32-hex-buffered *(ebp+8) %edx)
    29779       (write-buffered *(ebp+8) ") ")
    29780       e9/jump $translate-mu-get-stmt:emit-output/disp32
    29781     }
    29782     # otherwise base is on the stack
    29783     {
    29784 $translate-mu-get-stmt:emit-stack-input:
    29785       # emit "*(ebp + " inouts[0]->stack-offset + offset ") "
    29786       (write-buffered *(ebp+8) "*(ebp+")
    29787       03/add *(eax+0x14) 2/r32/edx  # Var-offset
    29788       (write-int32-hex-buffered *(ebp+8) %edx)
    29789       (write-buffered *(ebp+8) ") ")
    29790       eb/jump $translate-mu-get-stmt:emit-output/disp8
    29791     }
    29792 $translate-mu-get-stmt:emit-output:
    29793     # var output/eax: (addr var) = stmt->outputs->value
    29794     (lookup *(ecx+0x14) *(ecx+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    29795     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    29796     # emit offset->register "/r32"
    29797     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    29798     (get Mu-registers %eax 0xc "Mu-registers")  # => eax: (addr int)
    29799     (write-int32-hex-buffered *(ebp+8) *eax)
    29800     (write-buffered *(ebp+8) "/r32\n")
    29801 $translate-mu-get-stmt:end:
    29802     # . restore registers
    29803     5a/pop-to-edx
    29804     59/pop-to-ecx
    29805     58/pop-to-eax
    29806     # . epilogue
    29807     89/<- %esp 5/r32/ebp
    29808     5d/pop-to-ebp
    29809     c3/return
    29810
    29811 translate-mu-copy-object-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
    29812     # . prologue
    29813     55/push-ebp
    29814     89/<- %ebp 4/r32/esp
    29815     # . save registers
    29816     50/push-eax
    29817     #
    29818     (emit-indent *(ebp+8) *Curr-block-depth)
    29819     (write-buffered *(ebp+8) "(copy-bytes")
    29820     # eax = stmt
    29821     8b/-> *(ebp+0xc) 0/r32/eax
    29822     # var first-inout/eax: (addr stmt-var) = stmt->inouts[0]
    29823     (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    29824     (emit-subx-call-operand *(ebp+8) %eax)
    29825     # var second-inout/eax: (addr stmt-var) = stmt->inouts[1]
    29826     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    29827     (emit-subx-call-operand *(ebp+8) %eax)
    29828     # emit size of inouts
    29829     (write-buffered *(ebp+8) Space)
    29830     (addr-payload-size %eax *(ebp+0x10) *(ebp+0x14))  # => eax
    29831     (write-int32-hex-buffered *(ebp+8) %eax)
    29832     (write-buffered *(ebp+8) ")\n")
    29833 $translate-mu-copy-object-stmt:end:
    29834     # . restore registers
    29835     58/pop-to-eax
    29836     # . epilogue
    29837     89/<- %esp 5/r32/ebp
    29838     5d/pop-to-ebp
    29839     c3/return
    29840
    29841 translate-mu-clear-object-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
    29842     # . prologue
    29843     55/push-ebp
    29844     89/<- %ebp 4/r32/esp
    29845     # . save registers
    29846     50/push-eax
    29847     #
    29848     (emit-indent *(ebp+8) *Curr-block-depth)
    29849     (write-buffered *(ebp+8) "(zero-out")
    29850     # eax = stmt
    29851     8b/-> *(ebp+0xc) 0/r32/eax
    29852     # var dest/eax: (addr stmt-var) = stmt->inouts[0]
    29853     (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    29854     #
    29855     (emit-subx-call-operand *(ebp+8) %eax)
    29856     (write-buffered *(ebp+8) Space)
    29857     (addr-payload-size %eax *(ebp+0x10) *(ebp+0x14))  # => eax
    29858     (write-int32-hex-buffered *(ebp+8) %eax)
    29859     (write-buffered *(ebp+8) ")\n")
    29860 $translate-mu-clear-object-stmt:end:
    29861     # . restore registers
    29862     58/pop-to-eax
    29863     # . epilogue
    29864     89/<- %esp 5/r32/ebp
    29865     5d/pop-to-ebp
    29866     c3/return
    29867
    29868 translate-mu-allocate-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
    29869     # . prologue
    29870     55/push-ebp
    29871     89/<- %ebp 4/r32/esp
    29872     # . save registers
    29873     50/push-eax
    29874     56/push-esi
    29875     57/push-edi
    29876     # esi = stmt
    29877     8b/-> *(ebp+0xc) 6/r32/esi
    29878     # var target/edi: (addr stmt-var) = stmt->inouts[0]
    29879     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    29880     89/<- %edi 0/r32/eax
    29881     #
    29882     (emit-indent *(ebp+8) *Curr-block-depth)
    29883     (write-buffered *(ebp+8) "(allocate Heap ")
    29884     (addr-handle-payload-size %edi *(ebp+0x10) *(ebp+0x14))  # => eax
    29885     (write-int32-hex-buffered *(ebp+8) %eax)
    29886     (emit-subx-call-operand *(ebp+8) %edi)
    29887     (write-buffered *(ebp+8) ")\n")
    29888 $translate-mu-allocate-stmt:end:
    29889     # . restore registers
    29890     5f/pop-to-edi
    29891     5e/pop-to-esi
    29892     58/pop-to-eax
    29893     # . epilogue
    29894     89/<- %esp 5/r32/ebp
    29895     5d/pop-to-ebp
    29896     c3/return
    29897
    29898 addr-handle-payload-size:  # s: (addr stmt-var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
    29899     # . prologue
    29900     55/push-ebp
    29901     89/<- %ebp 4/r32/esp
    29902     # var t/eax: (addr type-tree) = s->value->type
    29903     8b/-> *(ebp+8) 0/r32/eax
    29904     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    29905     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    29906     # TODO: check eax != 0
    29907     # TODO: check !t->is-atom?
    29908     # TODO: check t->left == addr
    29909     # t = t->right
    29910 $addr-handle-payload-size:skip-addr:
    29911     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
    29912     # TODO: check eax != 0
    29913     # TODO: check !t->is-atom?
    29914     # TODO: check t->left == handle
    29915     # t = t->right
    29916 $addr-handle-payload-size:skip-handle:
    29917     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
    29918     # TODO: check eax != 0
    29919     # if !t->is-atom? t = t->left
    29920     81 7/subop/compare *eax 0/imm32/false
    29921     {
    29922       75/jump-if-!= break/disp8
    29923       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    29924     }
    29925     # TODO: check t->is-atom?
    29926     # return size(t->value)
    29927     (size-of-type-id *(eax+4))  # Type-tree-value => eax
    29928 $addr-handle-payload-size:end:
    29929     # . epilogue
    29930     89/<- %esp 5/r32/ebp
    29931     5d/pop-to-ebp
    29932     c3/return
    29933
    29934 addr-payload-size:  # s: (addr stmt-var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
    29935     # . prologue
    29936     55/push-ebp
    29937     89/<- %ebp 4/r32/esp
    29938     # var t/eax: (addr type-tree) = s->value->type
    29939     8b/-> *(ebp+8) 0/r32/eax
    29940     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    29941     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    29942     # TODO: check eax != 0
    29943     # TODO: check !t->is-atom?
    29944     # TODO: check t->left == addr
    29945     # t = t->right
    29946 $addr-payload-size:skip-addr:
    29947     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
    29948     # TODO: check eax != 0
    29949     # if !t->is-atom? t = t->left
    29950     81 7/subop/compare *eax 0/imm32/false
    29951     {
    29952       75/jump-if-!= break/disp8
    29953       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    29954     }
    29955     # TODO: check t->is-atom?
    29956     # return size(t->value)
    29957     (size-of-type-id *(eax+4))  # Type-tree-value => eax
    29958 $addr-payload-size:end:
    29959     # . epilogue
    29960     89/<- %esp 5/r32/ebp
    29961     5d/pop-to-ebp
    29962     c3/return
    29963
    29964 translate-mu-populate-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
    29965     # . prologue
    29966     55/push-ebp
    29967     89/<- %ebp 4/r32/esp
    29968     # . save registers
    29969     50/push-eax
    29970     51/push-ecx
    29971     56/push-esi
    29972     57/push-edi
    29973     # esi = stmt
    29974     8b/-> *(ebp+0xc) 6/r32/esi
    29975     # var target/edi: (addr stmt-var) = stmt->inouts[0]
    29976     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    29977     89/<- %edi 0/r32/eax
    29978     # var len/ecx: (addr stmt-var) = stmt->inouts[1]
    29979     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
    29980     89/<- %ecx 0/r32/eax
    29981     #
    29982     (emit-indent *(ebp+8) *Curr-block-depth)
    29983     (write-buffered *(ebp+8) "(allocate-array2 Heap ")
    29984     (addr-handle-array-payload-size %edi *(ebp+0x10) *(ebp+0x14))  # => eax
    29985     (write-int32-hex-buffered *(ebp+8) %eax)
    29986     (emit-subx-call-operand *(ebp+8) %ecx)
    29987     (emit-subx-call-operand *(ebp+8) %edi)
    29988     (write-buffered *(ebp+8) ")\n")
    29989 $translate-mu-populate-stmt:end:
    29990     # . restore registers
    29991     5f/pop-to-edi
    29992     5e/pop-to-esi
    29993     59/pop-to-ecx
    29994     58/pop-to-eax
    29995     # . epilogue
    29996     89/<- %esp 5/r32/ebp
    29997     5d/pop-to-ebp
    29998     c3/return
    29999
    30000 translate-mu-populate-stream-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
    30001     # . prologue
    30002     55/push-ebp
    30003     89/<- %ebp 4/r32/esp
    30004     # . save registers
    30005     50/push-eax
    30006     51/push-ecx
    30007     56/push-esi
    30008     57/push-edi
    30009     # esi = stmt
    30010     8b/-> *(ebp+0xc) 6/r32/esi
    30011     # var target/edi: (addr stmt-var) = stmt->inouts[0]
    30012     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    30013     89/<- %edi 0/r32/eax
    30014     # var len/ecx: (addr stmt-var) = stmt->inouts[1]
    30015     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
    30016     89/<- %ecx 0/r32/eax
    30017     #
    30018     (emit-indent *(ebp+8) *Curr-block-depth)
    30019     (write-buffered *(ebp+8) "(new-stream Heap ")
    30020     (addr-handle-stream-payload-size %edi *(ebp+0x10) *(ebp+0x14))  # => eax
    30021     (write-int32-hex-buffered *(ebp+8) %eax)
    30022     (emit-subx-call-operand *(ebp+8) %ecx)
    30023     (emit-subx-call-operand *(ebp+8) %edi)
    30024     (write-buffered *(ebp+8) ")\n")
    30025 $translate-mu-populate-stream-stmt:end:
    30026     # . restore registers
    30027     5f/pop-to-edi
    30028     5e/pop-to-esi
    30029     59/pop-to-ecx
    30030     58/pop-to-eax
    30031     # . epilogue
    30032     89/<- %esp 5/r32/ebp
    30033     5d/pop-to-ebp
    30034     c3/return
    30035
    30036 translate-mu-read-from-stream-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
    30037     # . prologue
    30038     55/push-ebp
    30039     89/<- %ebp 4/r32/esp
    30040     # . save registers
    30041     50/push-eax
    30042     51/push-ecx
    30043     56/push-esi
    30044     57/push-edi
    30045     # esi = stmt
    30046     8b/-> *(ebp+0xc) 6/r32/esi
    30047     # var stream/ecx: (addr stmt-var) = stmt->inouts[0]
    30048     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    30049     89/<- %ecx 0/r32/eax
    30050     # var target/edi: (addr stmt-var) = stmt->inouts[1]
    30051     (lookup *(ecx+8) *(ecx+0xc))  # Stmt-var-next Stmt-var-next => eax
    30052     89/<- %edi 0/r32/eax
    30053     #
    30054     (emit-indent *(ebp+8) *Curr-block-depth)
    30055     (write-buffered *(ebp+8) "(read-from-stream")
    30056     (emit-subx-call-operand *(ebp+8) %ecx)
    30057     (emit-subx-call-operand *(ebp+8) %edi)
    30058     (write-buffered *(ebp+8) Space)
    30059     (addr-payload-size %edi *(ebp+0x10) *(ebp+0x14))  # => eax
    30060     (write-int32-hex-buffered *(ebp+8) %eax)
    30061     (write-buffered *(ebp+8) ")\n")
    30062 $translate-mu-read-from-stream-stmt:end:
    30063     # . restore registers
    30064     5f/pop-to-edi
    30065     5e/pop-to-esi
    30066     59/pop-to-ecx
    30067     58/pop-to-eax
    30068     # . epilogue
    30069     89/<- %esp 5/r32/ebp
    30070     5d/pop-to-ebp
    30071     c3/return
    30072
    30073 translate-mu-write-to-stream-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
    30074     # . prologue
    30075     55/push-ebp
    30076     89/<- %ebp 4/r32/esp
    30077     # . save registers
    30078     50/push-eax
    30079     51/push-ecx
    30080     56/push-esi
    30081     57/push-edi
    30082     # esi = stmt
    30083     8b/-> *(ebp+0xc) 6/r32/esi
    30084     # var stream/ecx: (addr stmt-var) = stmt->inouts[0]
    30085     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    30086     89/<- %ecx 0/r32/eax
    30087     # var target/edi: (addr stmt-var) = stmt->inouts[1]
    30088     (lookup *(ecx+8) *(ecx+0xc))  # Stmt-var-next Stmt-var-next => eax
    30089     89/<- %edi 0/r32/eax
    30090     #
    30091     (emit-indent *(ebp+8) *Curr-block-depth)
    30092     (write-buffered *(ebp+8) "(write-to-stream")
    30093     (emit-subx-call-operand *(ebp+8) %ecx)
    30094     (flush *(ebp+8))
    30095     (emit-subx-call-operand *(ebp+8) %edi)
    30096     (flush *(ebp+8))
    30097     (write-buffered *(ebp+8) Space)
    30098     (flush *(ebp+8))
    30099     (addr-payload-size %edi *(ebp+0x10) *(ebp+0x14))  # => eax
    30100     (write-int32-hex-buffered *(ebp+8) %eax)
    30101     (write-buffered *(ebp+8) ")\n")
    30102 $translate-mu-write-to-stream-stmt:end:
    30103     # . restore registers
    30104     5f/pop-to-edi
    30105     5e/pop-to-esi
    30106     59/pop-to-ecx
    30107     58/pop-to-eax
    30108     # . epilogue
    30109     89/<- %esp 5/r32/ebp
    30110     5d/pop-to-ebp
    30111     c3/return
    30112
    30113 addr-handle-array-payload-size:  # s: (addr stmt-var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
    30114     # . prologue
    30115     55/push-ebp
    30116     89/<- %ebp 4/r32/esp
    30117     # var t/eax: (addr type-tree) = s->value->type
    30118     8b/-> *(ebp+8) 0/r32/eax
    30119     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    30120     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    30121     # TODO: check eax != 0
    30122     # TODO: check !t->is-atom?
    30123     # TODO: check t->left == addr
    30124     # t = t->right
    30125 $addr-handle-array-payload-size:skip-addr:
    30126     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
    30127     # TODO: check eax != 0
    30128     # TODO: check !t->is-atom?
    30129     # TODO: check t->left == handle
    30130     # t = t->right
    30131 $addr-handle-array-payload-size:skip-handle:
    30132     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
    30133     # TODO: check eax != 0
    30134     # TODO: check !t->is-atom?
    30135     # TODO: check t->left == array
    30136     # t = t->right
    30137 $addr-handle-array-payload-size:skip-array:
    30138     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
    30139     # TODO: check eax != 0
    30140     # if !t->is-atom? t = t->left
    30141     81 7/subop/compare *eax 0/imm32/false
    30142     {
    30143       75/jump-if-!= break/disp8
    30144       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    30145     }
    30146 $addr-handle-array-payload-size:compute-size:
    30147     # TODO: check t->is-atom?
    30148     # return size(t->value)
    30149     (size-of-type-id-as-array-element *(eax+4))  # Type-tree-value => eax
    30150 $addr-handle-array-payload-size:end:
    30151     # . epilogue
    30152     89/<- %esp 5/r32/ebp
    30153     5d/pop-to-ebp
    30154     c3/return
    30155
    30156 addr-handle-stream-payload-size:  # s: (addr stmt-var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
    30157     # . prologue
    30158     55/push-ebp
    30159     89/<- %ebp 4/r32/esp
    30160     # var t/eax: (addr type-tree) = s->value->type
    30161     8b/-> *(ebp+8) 0/r32/eax
    30162     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    30163     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    30164     # TODO: check eax != 0
    30165     # TODO: check !t->is-atom?
    30166     # TODO: check t->left == addr
    30167     # t = t->right
    30168 $addr-handle-stream-payload-size:skip-addr:
    30169     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
    30170     # TODO: check eax != 0
    30171     # TODO: check !t->is-atom?
    30172     # TODO: check t->left == handle
    30173     # t = t->right
    30174 $addr-handle-stream-payload-size:skip-handle:
    30175     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
    30176     # TODO: check eax != 0
    30177     # TODO: check !t->is-atom?
    30178     # TODO: check t->left == stream
    30179     # t = t->right
    30180 $addr-handle-stream-payload-size:skip-stream:
    30181     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
    30182     # TODO: check eax != 0
    30183     # if !t->is-atom? t = t->left
    30184     81 7/subop/compare *eax 0/imm32/false
    30185     {
    30186       75/jump-if-!= break/disp8
    30187       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    30188     }
    30189 $addr-handle-stream-payload-size:compute-size:
    30190     # TODO: check t->is-atom?
    30191     # return size(t->value)
    30192     (size-of-type-id-as-array-element *(eax+4))  # Type-tree-value => eax
    30193 $addr-handle-stream-payload-size:end:
    30194     # . epilogue
    30195     89/<- %esp 5/r32/ebp
    30196     5d/pop-to-ebp
    30197     c3/return
    30198
    30199 power-of-2?:  # n: int, err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: boolean
    30200     # precondition: n is positive
    30201     # . prologue
    30202     55/push-ebp
    30203     89/<- %ebp 4/r32/esp
    30204     # eax = n
    30205     8b/-> *(ebp+8) 0/r32/eax
    30206     # if (n < 0) abort
    30207     3d/compare-eax-with 0/imm32
    30208     0f 8c/jump-if-< $power-of-2?:abort/disp32
    30209     # var tmp/eax: int = n-1
    30210     48/decrement-eax
    30211     # var tmp2/eax: int = n & tmp
    30212     23/and-> *(ebp+8) 0/r32/eax
    30213     # return (tmp2 == 0)
    30214     3d/compare-eax-and 0/imm32
    30215     0f 94/set-byte-if-= %al
    30216     81 4/subop/and %eax 0xff/imm32
    30217 $power-of-2?:end:
    30218     # . epilogue
    30219     89/<- %esp 5/r32/ebp
    30220     5d/pop-to-ebp
    30221     c3/return
    30222
    30223 $power-of-2?:abort:
    30224     (write-buffered *(ebp+0xc) "power-of-2?: negative number\n")
    30225     (flush *(ebp+0xc))
    30226     (stop *(ebp+0x10) 1)
    30227     # never gets here
    30228
    30229 num-shift-rights:  # n: int -> result/eax: int
    30230     # precondition: n is a positive power of 2
    30231     # . prologue
    30232     55/push-ebp
    30233     89/<- %ebp 4/r32/esp
    30234     # . save registers
    30235     51/push-ecx
    30236     # var curr/ecx: int = n
    30237     8b/-> *(ebp+8) 1/r32/ecx
    30238     # result = 0
    30239     b8/copy-to-eax 0/imm32
    30240     {
    30241       # if (curr <= 1) break
    30242       81 7/subop/compare %ecx 1/imm32
    30243       7e/jump-if-<= break/disp8
    30244       40/increment-eax
    30245       c1/shift 5/subop/arithmetic-right %ecx 1/imm8
    30246       eb/jump loop/disp8
    30247     }
    30248 $num-shift-rights:end:
    30249     # . restore registers
    30250     59/pop-to-ecx
    30251     # . epilogue
    30252     89/<- %esp 5/r32/ebp
    30253     5d/pop-to-ebp
    30254     c3/return
    30255
    30256 mu-get-offset:  # stmt: (addr stmt) -> result/eax: int
    30257     # . prologue
    30258     55/push-ebp
    30259     89/<- %ebp 4/r32/esp
    30260     # var second-inout/eax: (addr stmt-var) = stmt->inouts->next
    30261     8b/-> *(ebp+8) 0/r32/eax
    30262     (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    30263     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    30264     # var output-var/eax: (addr var) = second-inout->value
    30265     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    30266 #?     (write-buffered Stderr "mu-get-offset: ")
    30267 #?     (write-int32-hex-buffered Stderr %eax)
    30268 #?     (write-buffered Stderr " name: ")
    30269 #?     50/push-eax
    30270 #?     (lookup *eax *(eax+4))  # Var-name
    30271 #?     (write-buffered Stderr %eax)
    30272 #?     58/pop-to-eax
    30273 #?     (write-buffered Stderr Newline)
    30274 #?     (flush Stderr)
    30275     # return output-var->stack-offset
    30276     8b/-> *(eax+0x14) 0/r32/eax  # Var-offset
    30277 #?     (write-buffered Stderr "=> ")
    30278 #?     (write-int32-hex-buffered Stderr %eax)
    30279 #?     (write-buffered Stderr Newline)
    30280 #?     (flush Stderr)
    30281 $emit-get-offset:end:
    30282     # . epilogue
    30283     89/<- %esp 5/r32/ebp
    30284     5d/pop-to-ebp
    30285     c3/return
    30286
    30287 emit-subx-block:  # out: (addr buffered-file), block: (addr block), vars: (addr stack live-var), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    30288     # . prologue
    30289     55/push-ebp
    30290     89/<- %ebp 4/r32/esp
    30291     # . save registers
    30292     50/push-eax
    30293     51/push-ecx
    30294     56/push-esi
    30295     # esi = block
    30296     8b/-> *(ebp+0xc) 6/r32/esi
    30297     # block->var->block-depth = *Curr-block-depth
    30298     (lookup *(esi+0xc) *(esi+0x10))  # Block-var Block-var => eax
    30299     8b/-> *Curr-block-depth 1/r32/ecx
    30300     89/<- *(eax+0x10) 1/r32/ecx  # Var-block-depth
    30301     # var stmts/eax: (addr list stmt) = lookup(block->statements)
    30302     (lookup *(esi+4) *(esi+8))  # Block-stmts Block-stmts => eax
    30303     #
    30304     {
    30305 $emit-subx-block:check-empty:
    30306       3d/compare-eax-and 0/imm32
    30307       0f 84/jump-if-= break/disp32
    30308       (emit-indent *(ebp+8) *Curr-block-depth)
    30309       (write-buffered *(ebp+8) "{\n")
    30310       # var v/ecx: (addr var) = lookup(block->var)
    30311       (lookup *(esi+0xc) *(esi+0x10))  # Block-var Block-var => eax
    30312       89/<- %ecx 0/r32/eax
    30313       #
    30314       (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    30315       (write-buffered *(ebp+8) %eax)
    30316       (write-buffered *(ebp+8) ":loop:\n")
    30317       ff 0/subop/increment *Curr-block-depth
    30318       (push *(ebp+0x10) *(esi+0xc))  # Block-var
    30319       (push *(ebp+0x10) *(esi+0x10))  # Block-var
    30320       (push *(ebp+0x10) 0)  # false
    30321       # emit block->statements
    30322       (lookup *(esi+4) *(esi+8))  # Block-stmts Block-stmts => eax
    30323       (emit-subx-stmt-list *(ebp+8) %eax *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
    30324       (pop *(ebp+0x10))  # => eax
    30325       (pop *(ebp+0x10))  # => eax
    30326       (pop *(ebp+0x10))  # => eax
    30327       ff 1/subop/decrement *Curr-block-depth
    30328       (emit-indent *(ebp+8) *Curr-block-depth)
    30329       (write-buffered *(ebp+8) "}\n")
    30330       (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    30331       (write-buffered *(ebp+8) %eax)
    30332       (write-buffered *(ebp+8) ":break:\n")
    30333     }
    30334 $emit-subx-block:end:
    30335     # . restore registers
    30336     5e/pop-to-esi
    30337     59/pop-to-ecx
    30338     58/pop-to-eax
    30339     # . epilogue
    30340     89/<- %esp 5/r32/ebp
    30341     5d/pop-to-ebp
    30342     c3/return
    30343
    30344 # Primitives supported
    30345 # See mu_instructions for a summary of this linked-list data structure.
    30346 #
    30347 # For each operation, put variants with hard-coded registers before flexible ones.
    30348 #
    30349 # Unfortunately, our restrictions on addresses require that various fields in
    30350 # primitives be handles, which complicates these definitions.
    30351 #   - we need to insert dummy fields all over the place for fake alloc-ids
    30352 #   - we can't use our syntax sugar of quoted literals for string fields
    30353 #
    30354 # Fake alloc-ids are needed because our type definitions up top require
    30355 # handles but it's clearer to statically allocate these long-lived objects.
    30356 # Fake alloc-ids are perfectly safe, but they can't be reclaimed.
    30357 #
    30358 # Every 'object' below starts with a fake alloc-id. It may also contain other
    30359 # fake alloc-ids for various handle fields.
    30360 #
    30361 # I think of objects starting with a fake alloc-id as having type 'payload'.
    30362 # It's not really intended to be created dynamically; for that use `allocate`
    30363 # as usual.
    30364 #
    30365 # Idea for a notation to simplify such definitions:
    30366 #   _Primitive-increment-eax:  # (payload primitive)
    30367 #     0x11/alloc-id:fake:payload
    30368 #     0x11 @(0x11 "increment")  # name
    30369 #     0 0                       # inouts
    30370 #     0x11 @(0x11/payload
    30371 #            0x11 @(0x11/payload  # List-value
    30372 #                   0 0             # Var-name
    30373 #                   0x11 @(0x11     # Var-type
    30374 #                          1/is-atom
    30375 #                          1/value 0/unused   # Type-tree-left
    30376 #                          0 0                # Type-tree-right
    30377 #                         )
    30378 #                   1               # block-depth
    30379 #                   0               # stack-offset
    30380 #                   0x11 @(0x11 "eax")  # Var-register
    30381 #                  )
    30382 #            0 0)                 # List-next
    30383 #     ...
    30384 #     _Primitive-increment-ecx/imm32/next
    30385 #   ...
    30386 # Awfully complex and non-obvious. But also clearly signals there's something
    30387 # to learn here, so may be worth trying.
    30388 #
    30389 # '@' is just an initial thought. Punctuation used so far in Mu: () * % # / "
    30390 #
    30391 # For now we'll continue to just use comments and manually ensure they stay up
    30392 # to date.
    30393 == data
    30394 Primitives:  # (addr primitive)
    30395 # - increment/decrement
    30396 _Primitive-increment-eax:  # (addr primitive)
    30397     # var/eax <- increment => 40/increment-eax
    30398     0x11/imm32/alloc-id:fake
    30399     _string-increment/imm32/name
    30400     0/imm32/no-inouts
    30401     0/imm32/no-inouts
    30402     0x11/imm32/alloc-id:fake
    30403     Single-int-var-in-eax/imm32/outputs
    30404     0x11/imm32/alloc-id:fake
    30405     _string_40_increment_eax/imm32/subx-name
    30406     0/imm32/no-rm32
    30407     0/imm32/no-r32
    30408     0/imm32/no-imm32
    30409     0/imm32/no-imm8
    30410     0/imm32/no-disp32
    30411     0/imm32/no-xm32
    30412     0/imm32/no-x32
    30413     0x11/imm32/alloc-id:fake
    30414     _Primitive-increment-ecx/imm32/next
    30415 _Primitive-increment-ecx:  # (payload primitive)
    30416     0x11/imm32/alloc-id:fake:payload
    30417     # var/ecx <- increment => 41/increment-ecx
    30418     0x11/imm32/alloc-id:fake
    30419     _string-increment/imm32/name
    30420     0/imm32/no-inouts
    30421     0/imm32/no-inouts
    30422     0x11/imm32/alloc-id:fake
    30423     Single-int-var-in-ecx/imm32/outputs
    30424     0x11/imm32/alloc-id:fake
    30425     _string_41_increment_ecx/imm32/subx-name
    30426     0/imm32/no-rm32
    30427     0/imm32/no-r32
    30428     0/imm32/no-imm32
    30429     0/imm32/no-imm8
    30430     0/imm32/no-disp32
    30431     0/imm32/no-xm32
    30432     0/imm32/no-x32
    30433     0x11/imm32/alloc-id:fake
    30434     _Primitive-increment-edx/imm32/next
    30435 _Primitive-increment-edx:  # (payload primitive)
    30436     0x11/imm32/alloc-id:fake:payload
    30437     # var/edx <- increment => 42/increment-edx
    30438     0x11/imm32/alloc-id:fake
    30439     _string-increment/imm32/name
    30440     0/imm32/no-inouts
    30441     0/imm32/no-inouts
    30442     0x11/imm32/alloc-id:fake
    30443     Single-int-var-in-edx/imm32/outputs
    30444     0x11/imm32/alloc-id:fake
    30445     _string_42_increment_edx/imm32/subx-name
    30446     0/imm32/no-rm32
    30447     0/imm32/no-r32
    30448     0/imm32/no-imm32
    30449     0/imm32/no-imm8
    30450     0/imm32/no-disp32
    30451     0/imm32/no-xm32
    30452     0/imm32/no-x32
    30453     0x11/imm32/alloc-id:fake
    30454     _Primitive-increment-ebx/imm32/next
    30455 _Primitive-increment-ebx:  # (payload primitive)
    30456     0x11/imm32/alloc-id:fake:payload
    30457     # var/ebx <- increment => 43/increment-ebx
    30458     0x11/imm32/alloc-id:fake
    30459     _string-increment/imm32/name
    30460     0/imm32/no-inouts
    30461     0/imm32/no-inouts
    30462     0x11/imm32/alloc-id:fake
    30463     Single-int-var-in-ebx/imm32/outputs
    30464     0x11/imm32/alloc-id:fake
    30465     _string_43_increment_ebx/imm32/subx-name
    30466     0/imm32/no-rm32
    30467     0/imm32/no-r32
    30468     0/imm32/no-imm32
    30469     0/imm32/no-imm8
    30470     0/imm32/no-disp32
    30471     0/imm32/no-xm32
    30472     0/imm32/no-x32
    30473     0x11/imm32/alloc-id:fake
    30474     _Primitive-increment-esi/imm32/next
    30475 _Primitive-increment-esi:  # (payload primitive)
    30476     0x11/imm32/alloc-id:fake:payload
    30477     # var/esi <- increment => 46/increment-esi
    30478     0x11/imm32/alloc-id:fake
    30479     _string-increment/imm32/name
    30480     0/imm32/no-inouts
    30481     0/imm32/no-inouts
    30482     0x11/imm32/alloc-id:fake
    30483     Single-int-var-in-esi/imm32/outputs
    30484     0x11/imm32/alloc-id:fake
    30485     _string_46_increment_esi/imm32/subx-name
    30486     0/imm32/no-rm32
    30487     0/imm32/no-r32
    30488     0/imm32/no-imm32
    30489     0/imm32/no-imm8
    30490     0/imm32/no-disp32
    30491     0/imm32/no-xm32
    30492     0/imm32/no-x32
    30493     0x11/imm32/alloc-id:fake
    30494     _Primitive-increment-edi/imm32/next
    30495 _Primitive-increment-edi:  # (payload primitive)
    30496     0x11/imm32/alloc-id:fake:payload
    30497     # var/edi <- increment => 47/increment-edi
    30498     0x11/imm32/alloc-id:fake
    30499     _string-increment/imm32/name
    30500     0/imm32/no-inouts
    30501     0/imm32/no-inouts
    30502     0x11/imm32/alloc-id:fake
    30503     Single-int-var-in-edi/imm32/outputs
    30504     0x11/imm32/alloc-id:fake
    30505     _string_47_increment_edi/imm32/subx-name
    30506     0/imm32/no-rm32
    30507     0/imm32/no-r32
    30508     0/imm32/no-imm32
    30509     0/imm32/no-imm8
    30510     0/imm32/no-disp32
    30511     0/imm32/no-xm32
    30512     0/imm32/no-x32
    30513     0x11/imm32/alloc-id:fake
    30514     _Primitive-decrement-eax/imm32/next
    30515 _Primitive-decrement-eax:  # (payload primitive)
    30516     0x11/imm32/alloc-id:fake:payload
    30517     # var/eax <- decrement => 48/decrement-eax
    30518     0x11/imm32/alloc-id:fake
    30519     _string-decrement/imm32/name
    30520     0/imm32/no-inouts
    30521     0/imm32/no-inouts
    30522     0x11/imm32/alloc-id:fake
    30523     Single-int-var-in-eax/imm32/outputs
    30524     0x11/imm32/alloc-id:fake
    30525     _string_48_decrement_eax/imm32/subx-name
    30526     0/imm32/no-rm32
    30527     0/imm32/no-r32
    30528     0/imm32/no-imm32
    30529     0/imm32/no-imm8
    30530     0/imm32/no-disp32
    30531     0/imm32/no-xm32
    30532     0/imm32/no-x32
    30533     0x11/imm32/alloc-id:fake
    30534     _Primitive-decrement-ecx/imm32/next
    30535 _Primitive-decrement-ecx:  # (payload primitive)
    30536     0x11/imm32/alloc-id:fake:payload
    30537     # var/ecx <- decrement => 49/decrement-ecx
    30538     0x11/imm32/alloc-id:fake
    30539     _string-decrement/imm32/name
    30540     0/imm32/no-inouts
    30541     0/imm32/no-inouts
    30542     0x11/imm32/alloc-id:fake
    30543     Single-int-var-in-ecx/imm32/outputs
    30544     0x11/imm32/alloc-id:fake
    30545     _string_49_decrement_ecx/imm32/subx-name
    30546     0/imm32/no-rm32
    30547     0/imm32/no-r32
    30548     0/imm32/no-imm32
    30549     0/imm32/no-imm8
    30550     0/imm32/no-disp32
    30551     0/imm32/no-xm32
    30552     0/imm32/no-x32
    30553     0x11/imm32/alloc-id:fake
    30554     _Primitive-decrement-edx/imm32/next
    30555 _Primitive-decrement-edx:  # (payload primitive)
    30556     0x11/imm32/alloc-id:fake:payload
    30557     # var/edx <- decrement => 4a/decrement-edx
    30558     0x11/imm32/alloc-id:fake
    30559     _string-decrement/imm32/name
    30560     0/imm32/no-inouts
    30561     0/imm32/no-inouts
    30562     0x11/imm32/alloc-id:fake
    30563     Single-int-var-in-edx/imm32/outputs
    30564     0x11/imm32/alloc-id:fake
    30565     _string_4a_decrement_edx/imm32/subx-name
    30566     0/imm32/no-rm32
    30567     0/imm32/no-r32
    30568     0/imm32/no-imm32
    30569     0/imm32/no-imm8
    30570     0/imm32/no-disp32
    30571     0/imm32/no-xm32
    30572     0/imm32/no-x32
    30573     0x11/imm32/alloc-id:fake
    30574     _Primitive-decrement-ebx/imm32/next
    30575 _Primitive-decrement-ebx:  # (payload primitive)
    30576     0x11/imm32/alloc-id:fake:payload
    30577     # var/ebx <- decrement => 4b/decrement-ebx
    30578     0x11/imm32/alloc-id:fake
    30579     _string-decrement/imm32/name
    30580     0/imm32/no-inouts
    30581     0/imm32/no-inouts
    30582     0x11/imm32/alloc-id:fake
    30583     Single-int-var-in-ebx/imm32/outputs
    30584     0x11/imm32/alloc-id:fake
    30585     _string_4b_decrement_ebx/imm32/subx-name
    30586     0/imm32/no-rm32
    30587     0/imm32/no-r32
    30588     0/imm32/no-imm32
    30589     0/imm32/no-imm8
    30590     0/imm32/no-disp32
    30591     0/imm32/no-xm32
    30592     0/imm32/no-x32
    30593     0x11/imm32/alloc-id:fake
    30594     _Primitive-decrement-esi/imm32/next
    30595 _Primitive-decrement-esi:  # (payload primitive)
    30596     0x11/imm32/alloc-id:fake:payload
    30597     # var/esi <- decrement => 4e/decrement-esi
    30598     0x11/imm32/alloc-id:fake
    30599     _string-decrement/imm32/name
    30600     0/imm32/no-inouts
    30601     0/imm32/no-inouts
    30602     0x11/imm32/alloc-id:fake
    30603     Single-int-var-in-esi/imm32/outputs
    30604     0x11/imm32/alloc-id:fake
    30605     _string_4e_decrement_esi/imm32/subx-name
    30606     0/imm32/no-rm32
    30607     0/imm32/no-r32
    30608     0/imm32/no-imm32
    30609     0/imm32/no-imm8
    30610     0/imm32/no-disp32
    30611     0/imm32/no-xm32
    30612     0/imm32/no-x32
    30613     0x11/imm32/alloc-id:fake
    30614     _Primitive-decrement-edi/imm32/next
    30615 _Primitive-decrement-edi:  # (payload primitive)
    30616     0x11/imm32/alloc-id:fake:payload
    30617     # var/edi <- decrement => 4f/decrement-edi
    30618     0x11/imm32/alloc-id:fake
    30619     _string-decrement/imm32/name
    30620     0/imm32/no-inouts
    30621     0/imm32/no-inouts
    30622     0x11/imm32/alloc-id:fake
    30623     Single-int-var-in-edi/imm32/outputs
    30624     0x11/imm32/alloc-id:fake
    30625     _string_4f_decrement_edi/imm32/subx-name
    30626     0/imm32/no-rm32
    30627     0/imm32/no-r32
    30628     0/imm32/no-imm32
    30629     0/imm32/no-imm8
    30630     0/imm32/no-disp32
    30631     0/imm32/no-xm32
    30632     0/imm32/no-x32
    30633     0x11/imm32/alloc-id:fake
    30634     _Primitive-increment-mem/imm32/next
    30635 _Primitive-increment-mem:  # (payload primitive)
    30636     0x11/imm32/alloc-id:fake:payload
    30637     # increment var => ff 0/subop/increment *(ebp+__)
    30638     0x11/imm32/alloc-id:fake
    30639     _string-increment/imm32/name
    30640     0x11/imm32/alloc-id:fake
    30641     Single-int-var-in-mem/imm32/inouts
    30642     0/imm32/no-outputs
    30643     0/imm32/no-outputs
    30644     0x11/imm32/alloc-id:fake
    30645     _string_ff_subop_increment/imm32/subx-name
    30646     1/imm32/rm32-is-first-inout
    30647     0/imm32/no-r32
    30648     0/imm32/no-imm32
    30649     0/imm32/no-imm8
    30650     0/imm32/no-disp32
    30651     0/imm32/no-xm32
    30652     0/imm32/no-x32
    30653     0x11/imm32/alloc-id:fake
    30654     _Primitive-increment-reg/imm32/next
    30655 _Primitive-increment-reg:  # (payload primitive)
    30656     0x11/imm32/alloc-id:fake:payload
    30657     # var/reg <- increment => ff 0/subop/increment %__
    30658     0x11/imm32/alloc-id:fake
    30659     _string-increment/imm32/name
    30660     0/imm32/no-inouts
    30661     0/imm32/no-inouts
    30662     0x11/imm32/alloc-id:fake
    30663     Single-int-var-in-some-register/imm32/outputs
    30664     0x11/imm32/alloc-id:fake
    30665     _string_ff_subop_increment/imm32/subx-name
    30666     3/imm32/rm32-is-first-output
    30667     0/imm32/no-r32
    30668     0/imm32/no-imm32
    30669     0/imm32/no-imm8
    30670     0/imm32/no-disp32
    30671     0/imm32/no-xm32
    30672     0/imm32/no-x32
    30673     0x11/imm32/alloc-id:fake
    30674     _Primitive-decrement-mem/imm32/next
    30675 _Primitive-decrement-mem:  # (payload primitive)
    30676     0x11/imm32/alloc-id:fake:payload
    30677     # decrement var => ff 1/subop/decrement *(ebp+__)
    30678     0x11/imm32/alloc-id:fake
    30679     _string-decrement/imm32/name
    30680     0x11/imm32/alloc-id:fake
    30681     Single-int-var-in-mem/imm32/inouts
    30682     0/imm32/no-outputs
    30683     0/imm32/no-outputs
    30684     0x11/imm32/alloc-id:fake
    30685     _string_ff_subop_decrement/imm32/subx-name
    30686     1/imm32/rm32-is-first-inout
    30687     0/imm32/no-r32
    30688     0/imm32/no-imm32
    30689     0/imm32/no-imm8
    30690     0/imm32/no-disp32
    30691     0/imm32/no-xm32
    30692     0/imm32/no-x32
    30693     0x11/imm32/alloc-id:fake
    30694     _Primitive-decrement-reg/imm32/next
    30695 _Primitive-decrement-reg:  # (payload primitive)
    30696     0x11/imm32/alloc-id:fake:payload
    30697     # var/reg <- decrement => ff 1/subop/decrement %__
    30698     0x11/imm32/alloc-id:fake
    30699     _string-decrement/imm32/name
    30700     0/imm32/no-inouts
    30701     0/imm32/no-inouts
    30702     0x11/imm32/alloc-id:fake
    30703     Single-int-var-in-some-register/imm32/outputs
    30704     0x11/imm32/alloc-id:fake
    30705     _string_ff_subop_decrement/imm32/subx-name
    30706     3/imm32/rm32-is-first-output
    30707     0/imm32/no-r32
    30708     0/imm32/no-imm32
    30709     0/imm32/no-imm8
    30710     0/imm32/no-disp32
    30711     0/imm32/no-xm32
    30712     0/imm32/no-x32
    30713     0x11/imm32/alloc-id:fake
    30714     _Primitive-add-to-eax/imm32/next
    30715 # - add
    30716 _Primitive-add-to-eax:  # (payload primitive)
    30717     0x11/imm32/alloc-id:fake:payload
    30718     # var/eax <- add lit => 05/add-to-eax lit/imm32
    30719     0x11/imm32/alloc-id:fake
    30720     _string-add/imm32/name
    30721     0x11/imm32/alloc-id:fake
    30722     Single-lit-var/imm32/inouts
    30723     0x11/imm32/alloc-id:fake
    30724     Single-int-var-in-eax/imm32/outputs
    30725     0x11/imm32/alloc-id:fake
    30726     _string_05_add_to_eax/imm32/subx-name
    30727     0/imm32/no-rm32
    30728     0/imm32/no-r32
    30729     1/imm32/imm32-is-first-inout
    30730     0/imm32/no-imm8
    30731     0/imm32/no-disp32
    30732     0/imm32/no-xm32
    30733     0/imm32/no-x32
    30734     0x11/imm32/alloc-id:fake
    30735     _Primitive-add-reg-to-reg/imm32/next
    30736 _Primitive-add-reg-to-reg:  # (payload primitive)
    30737     0x11/imm32/alloc-id:fake:payload
    30738     # var1/reg <- add var2/reg => 01/add-to var1/rm32 var2/r32
    30739     0x11/imm32/alloc-id:fake
    30740     _string-add/imm32/name
    30741     0x11/imm32/alloc-id:fake
    30742     Single-int-var-in-some-register/imm32/inouts
    30743     0x11/imm32/alloc-id:fake
    30744     Single-int-var-in-some-register/imm32/outputs
    30745     0x11/imm32/alloc-id:fake
    30746     _string_01_add_to/imm32/subx-name
    30747     3/imm32/rm32-is-first-output
    30748     1/imm32/r32-is-first-inout
    30749     0/imm32/no-imm32
    30750     0/imm32/no-imm8
    30751     0/imm32/no-disp32
    30752     0/imm32/no-xm32
    30753     0/imm32/no-x32
    30754     0x11/imm32/alloc-id:fake
    30755     _Primitive-add-reg-to-mem/imm32/next
    30756 _Primitive-add-reg-to-mem:  # (payload primitive)
    30757     0x11/imm32/alloc-id:fake:payload
    30758     # add-to var1 var2/reg => 01/add-to var1 var2/r32
    30759     0x11/imm32/alloc-id:fake
    30760     _string-add-to/imm32/name
    30761     0x11/imm32/alloc-id:fake
    30762     Two-args-int-stack-int-reg/imm32/inouts
    30763     0/imm32/no-outputs
    30764     0/imm32/no-outputs
    30765     0x11/imm32/alloc-id:fake
    30766     _string_01_add_to/imm32/subx-name
    30767     1/imm32/rm32-is-first-inout
    30768     2/imm32/r32-is-second-inout
    30769     0/imm32/no-imm32
    30770     0/imm32/no-imm8
    30771     0/imm32/no-disp32
    30772     0/imm32/no-xm32
    30773     0/imm32/no-x32
    30774     0x11/imm32/alloc-id:fake
    30775     _Primitive-add-mem-to-reg/imm32/next
    30776 _Primitive-add-mem-to-reg:  # (payload primitive)
    30777     0x11/imm32/alloc-id:fake:payload
    30778     # var1/reg <- add var2 => 03/add var2/rm32 var1/r32
    30779     0x11/imm32/alloc-id:fake
    30780     _string-add/imm32/name
    30781     0x11/imm32/alloc-id:fake
    30782     Single-int-var-in-mem/imm32/inouts
    30783     0x11/imm32/alloc-id:fake
    30784     Single-int-var-in-some-register/imm32/outputs
    30785     0x11/imm32/alloc-id:fake
    30786     _string_03_add/imm32/subx-name
    30787     1/imm32/rm32-is-first-inout
    30788     3/imm32/r32-is-first-output
    30789     0/imm32/no-imm32
    30790     0/imm32/no-imm8
    30791     0/imm32/no-disp32
    30792     0/imm32/no-xm32
    30793     0/imm32/no-x32
    30794     0x11/imm32/alloc-id:fake
    30795     _Primitive-add-lit-to-reg/imm32/next
    30796 _Primitive-add-lit-to-reg:  # (payload primitive)
    30797     0x11/imm32/alloc-id:fake:payload
    30798     # var1/reg <- add lit => 81 0/subop/add var1/rm32 lit/imm32
    30799     0x11/imm32/alloc-id:fake
    30800     _string-add/imm32/name
    30801     0x11/imm32/alloc-id:fake
    30802     Single-lit-var/imm32/inouts
    30803     0x11/imm32/alloc-id:fake
    30804     Single-int-var-in-some-register/imm32/outputs
    30805     0x11/imm32/alloc-id:fake
    30806     _string_81_subop_add/imm32/subx-name
    30807     3/imm32/rm32-is-first-output
    30808     0/imm32/no-r32
    30809     1/imm32/imm32-is-first-inout
    30810     0/imm32/no-imm8
    30811     0/imm32/no-disp32
    30812     0/imm32/no-xm32
    30813     0/imm32/no-x32
    30814     0x11/imm32/alloc-id:fake
    30815     _Primitive-add-lit-to-mem/imm32/next
    30816 _Primitive-add-lit-to-mem:  # (payload primitive)
    30817     0x11/imm32/alloc-id:fake:payload
    30818     # add-to var1, lit => 81 0/subop/add var1/rm32 lit/imm32
    30819     0x11/imm32/alloc-id:fake
    30820     _string-add-to/imm32/name
    30821     0x11/imm32/alloc-id:fake
    30822     Int-var-and-literal/imm32/inouts
    30823     0/imm32/no-outputs
    30824     0/imm32/no-outputs
    30825     0x11/imm32/alloc-id:fake
    30826     _string_81_subop_add/imm32/subx-name
    30827     1/imm32/rm32-is-first-inout
    30828     0/imm32/no-r32
    30829     2/imm32/imm32-is-second-inout
    30830     0/imm32/no-imm8
    30831     0/imm32/no-disp32
    30832     0/imm32/no-xm32
    30833     0/imm32/no-x32
    30834     0x11/imm32/alloc-id:fake
    30835     _Primitive-subtract-from-eax/imm32/next
    30836 # - subtract
    30837 _Primitive-subtract-from-eax:  # (payload primitive)
    30838     0x11/imm32/alloc-id:fake:payload
    30839     # var/eax <- subtract lit => 2d/subtract-from-eax lit/imm32
    30840     0x11/imm32/alloc-id:fake
    30841     _string-subtract/imm32/name
    30842     0x11/imm32/alloc-id:fake
    30843     Single-lit-var/imm32/inouts
    30844     0x11/imm32/alloc-id:fake
    30845     Single-int-var-in-eax/imm32/outputs
    30846     0x11/imm32/alloc-id:fake
    30847     _string_2d_subtract_from_eax/imm32/subx-name
    30848     0/imm32/no-rm32
    30849     0/imm32/no-r32
    30850     1/imm32/imm32-is-first-inout
    30851     0/imm32/no-imm8
    30852     0/imm32/no-disp32
    30853     0/imm32/no-xm32
    30854     0/imm32/no-x32
    30855     0x11/imm32/alloc-id:fake
    30856     _Primitive-subtract-reg-from-reg/imm32/next
    30857 _Primitive-subtract-reg-from-reg:  # (payload primitive)
    30858     0x11/imm32/alloc-id:fake:payload
    30859     # var1/reg <- subtract var2/reg => 29/subtract-from var1/rm32 var2/r32
    30860     0x11/imm32/alloc-id:fake
    30861     _string-subtract/imm32/name
    30862     0x11/imm32/alloc-id:fake
    30863     Single-int-var-in-some-register/imm32/inouts
    30864     0x11/imm32/alloc-id:fake
    30865     Single-int-var-in-some-register/imm32/outputs
    30866     0x11/imm32/alloc-id:fake
    30867     _string_29_subtract_from/imm32/subx-name
    30868     3/imm32/rm32-is-first-output
    30869     1/imm32/r32-is-first-inout
    30870     0/imm32/no-imm32
    30871     0/imm32/no-imm8
    30872     0/imm32/no-disp32
    30873     0/imm32/no-xm32
    30874     0/imm32/no-x32
    30875     0x11/imm32/alloc-id:fake
    30876     _Primitive-subtract-reg-from-mem/imm32/next
    30877 _Primitive-subtract-reg-from-mem:  # (payload primitive)
    30878     0x11/imm32/alloc-id:fake:payload
    30879     # subtract-from var1 var2/reg => 29/subtract-from var1 var2/r32
    30880     0x11/imm32/alloc-id:fake
    30881     _string-subtract-from/imm32/name
    30882     0x11/imm32/alloc-id:fake
    30883     Two-args-int-stack-int-reg/imm32/inouts
    30884     0/imm32/no-outputs
    30885     0/imm32/no-outputs
    30886     0x11/imm32/alloc-id:fake
    30887     _string_29_subtract_from/imm32/subx-name
    30888     1/imm32/rm32-is-first-inout
    30889     2/imm32/r32-is-second-inout
    30890     0/imm32/no-imm32
    30891     0/imm32/no-imm8
    30892     0/imm32/no-disp32
    30893     0/imm32/no-xm32
    30894     0/imm32/no-x32
    30895     0x11/imm32/alloc-id:fake
    30896     _Primitive-subtract-mem-from-reg/imm32/next
    30897 _Primitive-subtract-mem-from-reg:  # (payload primitive)
    30898     0x11/imm32/alloc-id:fake:payload
    30899     # var1/reg <- subtract var2 => 2b/subtract var2/rm32 var1/r32
    30900     0x11/imm32/alloc-id:fake
    30901     _string-subtract/imm32/name
    30902     0x11/imm32/alloc-id:fake
    30903     Single-int-var-in-mem/imm32/inouts
    30904     0x11/imm32/alloc-id:fake
    30905     Single-int-var-in-some-register/imm32/outputs
    30906     0x11/imm32/alloc-id:fake
    30907     _string_2b_subtract/imm32/subx-name
    30908     1/imm32/rm32-is-first-inout
    30909     3/imm32/r32-is-first-output
    30910     0/imm32/no-imm32
    30911     0/imm32/no-imm8
    30912     0/imm32/no-disp32
    30913     0/imm32/no-xm32
    30914     0/imm32/no-x32
    30915     0x11/imm32/alloc-id:fake
    30916     _Primitive-subtract-lit-from-reg/imm32/next
    30917 _Primitive-subtract-lit-from-reg:  # (payload primitive)
    30918     0x11/imm32/alloc-id:fake:payload
    30919     # var1/reg <- subtract lit => 81 5/subop/subtract var1/rm32 lit/imm32
    30920     0x11/imm32/alloc-id:fake
    30921     _string-subtract/imm32/name
    30922     0x11/imm32/alloc-id:fake
    30923     Single-lit-var/imm32/inouts
    30924     0x11/imm32/alloc-id:fake
    30925     Single-int-var-in-some-register/imm32/outputs
    30926     0x11/imm32/alloc-id:fake
    30927     _string_81_subop_subtract/imm32/subx-name
    30928     3/imm32/rm32-is-first-output
    30929     0/imm32/no-r32
    30930     1/imm32/imm32-is-first-inout
    30931     0/imm32/no-imm8
    30932     0/imm32/no-disp32
    30933     0/imm32/no-xm32
    30934     0/imm32/no-x32
    30935     0x11/imm32/alloc-id:fake
    30936     _Primitive-subtract-lit-from-mem/imm32/next
    30937 _Primitive-subtract-lit-from-mem:  # (payload primitive)
    30938     0x11/imm32/alloc-id:fake:payload
    30939     # subtract-from var1, lit => 81 5/subop/subtract var1/rm32 lit/imm32
    30940     0x11/imm32/alloc-id:fake
    30941     _string-subtract-from/imm32/name
    30942     0x11/imm32/alloc-id:fake
    30943     Int-var-and-literal/imm32/inouts
    30944     0/imm32/no-outputs
    30945     0/imm32/no-outputs
    30946     0x11/imm32/alloc-id:fake
    30947     _string_81_subop_subtract/imm32/subx-name
    30948     1/imm32/rm32-is-first-inout
    30949     0/imm32/no-r32
    30950     2/imm32/imm32-is-second-inout
    30951     0/imm32/no-imm8
    30952     0/imm32/no-disp32
    30953     0/imm32/no-xm32
    30954     0/imm32/no-x32
    30955     0x11/imm32/alloc-id:fake
    30956     _Primitive-and-with-eax/imm32/next
    30957 # - and
    30958 _Primitive-and-with-eax:  # (payload primitive)
    30959     0x11/imm32/alloc-id:fake:payload
    30960     # var/eax <- and lit => 25/and-with-eax lit/imm32
    30961     0x11/imm32/alloc-id:fake
    30962     _string-and/imm32/name
    30963     0x11/imm32/alloc-id:fake
    30964     Single-lit-var/imm32/inouts
    30965     0x11/imm32/alloc-id:fake
    30966     Single-int-var-in-eax/imm32/outputs
    30967     0x11/imm32/alloc-id:fake
    30968     _string_25_and_with_eax/imm32/subx-name
    30969     0/imm32/no-rm32
    30970     0/imm32/no-r32
    30971     1/imm32/imm32-is-first-inout
    30972     0/imm32/no-imm8
    30973     0/imm32/no-disp32
    30974     0/imm32/no-xm32
    30975     0/imm32/no-x32
    30976     0x11/imm32/alloc-id:fake
    30977     _Primitive-and-reg-with-reg/imm32/next
    30978 _Primitive-and-reg-with-reg:  # (payload primitive)
    30979     0x11/imm32/alloc-id:fake:payload
    30980     # var1/reg <- and var2/reg => 21/and-with var1/rm32 var2/r32
    30981     0x11/imm32/alloc-id:fake
    30982     _string-and/imm32/name
    30983     0x11/imm32/alloc-id:fake
    30984     Single-int-var-in-some-register/imm32/inouts
    30985     0x11/imm32/alloc-id:fake
    30986     Single-int-var-in-some-register/imm32/outputs
    30987     0x11/imm32/alloc-id:fake
    30988     _string_21_and_with/imm32/subx-name
    30989     3/imm32/rm32-is-first-output
    30990     1/imm32/r32-is-first-inout
    30991     0/imm32/no-imm32
    30992     0/imm32/no-imm8
    30993     0/imm32/no-disp32
    30994     0/imm32/no-xm32
    30995     0/imm32/no-x32
    30996     0x11/imm32/alloc-id:fake
    30997     _Primitive-and-reg-with-mem/imm32/next
    30998 _Primitive-and-reg-with-mem:  # (payload primitive)
    30999     0x11/imm32/alloc-id:fake:payload
    31000     # and-with var1 var2/reg => 21/and-with var1 var2/r32
    31001     0x11/imm32/alloc-id:fake
    31002     _string-and-with/imm32/name
    31003     0x11/imm32/alloc-id:fake
    31004     Two-args-int-stack-int-reg/imm32/inouts
    31005     0/imm32/no-outputs
    31006     0/imm32/no-outputs
    31007     0x11/imm32/alloc-id:fake
    31008     _string_21_and_with/imm32/subx-name
    31009     1/imm32/rm32-is-first-inout
    31010     2/imm32/r32-is-second-inout
    31011     0/imm32/no-imm32
    31012     0/imm32/no-imm8
    31013     0/imm32/no-disp32
    31014     0/imm32/no-xm32
    31015     0/imm32/no-x32
    31016     0x11/imm32/alloc-id:fake
    31017     _Primitive-and-mem-with-reg/imm32/next
    31018 _Primitive-and-mem-with-reg:  # (payload primitive)
    31019     0x11/imm32/alloc-id:fake:payload
    31020     # var1/reg <- and var2 => 23/and var2/rm32 var1/r32
    31021     0x11/imm32/alloc-id:fake
    31022     _string-and/imm32/name
    31023     0x11/imm32/alloc-id:fake
    31024     Single-int-var-in-mem/imm32/inouts
    31025     0x11/imm32/alloc-id:fake
    31026     Single-int-var-in-some-register/imm32/outputs
    31027     0x11/imm32/alloc-id:fake
    31028     _string_23_and/imm32/subx-name
    31029     1/imm32/rm32-is-first-inout
    31030     3/imm32/r32-is-first-output
    31031     0/imm32/no-imm32
    31032     0/imm32/no-imm8
    31033     0/imm32/no-disp32
    31034     0/imm32/no-xm32
    31035     0/imm32/no-x32
    31036     0x11/imm32/alloc-id:fake
    31037     _Primitive-and-lit-with-reg/imm32/next
    31038 _Primitive-and-lit-with-reg:  # (payload primitive)
    31039     0x11/imm32/alloc-id:fake:payload
    31040     # var1/reg <- and lit => 81 4/subop/and var1/rm32 lit/imm32
    31041     0x11/imm32/alloc-id:fake
    31042     _string-and/imm32/name
    31043     0x11/imm32/alloc-id:fake
    31044     Single-lit-var/imm32/inouts
    31045     0x11/imm32/alloc-id:fake
    31046     Single-int-var-in-some-register/imm32/outputs
    31047     0x11/imm32/alloc-id:fake
    31048     _string_81_subop_and/imm32/subx-name
    31049     3/imm32/rm32-is-first-output
    31050     0/imm32/no-r32
    31051     1/imm32/imm32-is-first-inout
    31052     0/imm32/no-imm8
    31053     0/imm32/no-disp32
    31054     0/imm32/no-xm32
    31055     0/imm32/no-x32
    31056     0x11/imm32/alloc-id:fake
    31057     _Primitive-and-lit-with-mem/imm32/next
    31058 _Primitive-and-lit-with-mem:  # (payload primitive)
    31059     0x11/imm32/alloc-id:fake:payload
    31060     # and-with var1, lit => 81 4/subop/and var1/rm32 lit/imm32
    31061     0x11/imm32/alloc-id:fake
    31062     _string-and-with/imm32/name
    31063     0x11/imm32/alloc-id:fake
    31064     Int-var-and-literal/imm32/inouts
    31065     0/imm32/no-outputs
    31066     0/imm32/no-outputs
    31067     0x11/imm32/alloc-id:fake
    31068     _string_81_subop_and/imm32/subx-name
    31069     1/imm32/rm32-is-first-inout
    31070     0/imm32/no-r32
    31071     2/imm32/imm32-is-second-inout
    31072     0/imm32/no-imm8
    31073     0/imm32/no-disp32
    31074     0/imm32/no-xm32
    31075     0/imm32/no-x32
    31076     0x11/imm32/alloc-id:fake
    31077     _Primitive-or-with-eax/imm32/next
    31078 # - or
    31079 _Primitive-or-with-eax:  # (payload primitive)
    31080     0x11/imm32/alloc-id:fake:payload
    31081     # var/eax <- or lit => 0d/or-with-eax lit/imm32
    31082     0x11/imm32/alloc-id:fake
    31083     _string-or/imm32/name
    31084     0x11/imm32/alloc-id:fake
    31085     Single-lit-var/imm32/inouts
    31086     0x11/imm32/alloc-id:fake
    31087     Single-int-var-in-eax/imm32/outputs
    31088     0x11/imm32/alloc-id:fake
    31089     _string_0d_or_with_eax/imm32/subx-name
    31090     0/imm32/no-rm32
    31091     0/imm32/no-r32
    31092     1/imm32/imm32-is-first-inout
    31093     0/imm32/no-imm8
    31094     0/imm32/no-disp32
    31095     0/imm32/no-xm32
    31096     0/imm32/no-x32
    31097     0x11/imm32/alloc-id:fake
    31098     _Primitive-or-reg-with-reg/imm32/next
    31099 _Primitive-or-reg-with-reg:  # (payload primitive)
    31100     0x11/imm32/alloc-id:fake:payload
    31101     # var1/reg <- or var2/reg => 09/or-with var1/rm32 var2/r32
    31102     0x11/imm32/alloc-id:fake
    31103     _string-or/imm32/name
    31104     0x11/imm32/alloc-id:fake
    31105     Single-int-var-in-some-register/imm32/inouts
    31106     0x11/imm32/alloc-id:fake
    31107     Single-int-var-in-some-register/imm32/outputs
    31108     0x11/imm32/alloc-id:fake
    31109     _string_09_or_with/imm32/subx-name
    31110     3/imm32/rm32-is-first-output
    31111     1/imm32/r32-is-first-inout
    31112     0/imm32/no-imm32
    31113     0/imm32/no-imm8
    31114     0/imm32/no-disp32
    31115     0/imm32/no-xm32
    31116     0/imm32/no-x32
    31117     0x11/imm32/alloc-id:fake
    31118     _Primitive-or-reg-with-mem/imm32/next
    31119 _Primitive-or-reg-with-mem:  # (payload primitive)
    31120     0x11/imm32/alloc-id:fake:payload
    31121     # or-with var1 var2/reg => 09/or-with var1 var2/r32
    31122     0x11/imm32/alloc-id:fake
    31123     _string-or-with/imm32/name
    31124     0x11/imm32/alloc-id:fake
    31125     Two-args-int-stack-int-reg/imm32/inouts
    31126     0/imm32/no-outputs
    31127     0/imm32/no-outputs
    31128     0x11/imm32/alloc-id:fake
    31129     _string_09_or_with/imm32/subx-name
    31130     1/imm32/rm32-is-first-inout
    31131     2/imm32/r32-is-second-inout
    31132     0/imm32/no-imm32
    31133     0/imm32/no-imm8
    31134     0/imm32/no-disp32
    31135     0/imm32/no-xm32
    31136     0/imm32/no-x32
    31137     0x11/imm32/alloc-id:fake
    31138     _Primitive-or-mem-with-reg/imm32/next
    31139 _Primitive-or-mem-with-reg:  # (payload primitive)
    31140     0x11/imm32/alloc-id:fake:payload
    31141     # var1/reg <- or var2 => 0b/or var2/rm32 var1/r32
    31142     0x11/imm32/alloc-id:fake
    31143     _string-or/imm32/name
    31144     0x11/imm32/alloc-id:fake
    31145     Single-int-var-in-mem/imm32/inouts
    31146     0x11/imm32/alloc-id:fake
    31147     Single-int-var-in-some-register/imm32/outputs
    31148     0x11/imm32/alloc-id:fake
    31149     _string_0b_or/imm32/subx-name
    31150     1/imm32/rm32-is-first-inout
    31151     3/imm32/r32-is-first-output
    31152     0/imm32/no-imm32
    31153     0/imm32/no-imm8
    31154     0/imm32/no-disp32
    31155     0/imm32/no-xm32
    31156     0/imm32/no-x32
    31157     0x11/imm32/alloc-id:fake
    31158     _Primitive-or-lit-with-reg/imm32/next
    31159 _Primitive-or-lit-with-reg:  # (payload primitive)
    31160     0x11/imm32/alloc-id:fake:payload
    31161     # var1/reg <- or lit => 81 1/subop/or var1/rm32 lit/imm32
    31162     0x11/imm32/alloc-id:fake
    31163     _string-or/imm32/name
    31164     0x11/imm32/alloc-id:fake
    31165     Single-lit-var/imm32/inouts
    31166     0x11/imm32/alloc-id:fake
    31167     Single-int-var-in-some-register/imm32/outputs
    31168     0x11/imm32/alloc-id:fake
    31169     _string_81_subop_or/imm32/subx-name
    31170     3/imm32/rm32-is-first-output
    31171     0/imm32/no-r32
    31172     1/imm32/imm32-is-first-inout
    31173     0/imm32/no-imm8
    31174     0/imm32/no-disp32
    31175     0/imm32/no-xm32
    31176     0/imm32/no-x32
    31177     0x11/imm32/alloc-id:fake
    31178     _Primitive-or-lit-with-mem/imm32/next
    31179 _Primitive-or-lit-with-mem:  # (payload primitive)
    31180     0x11/imm32/alloc-id:fake:payload
    31181     # or-with var1, lit => 81 1/subop/or var1/rm32 lit/imm32
    31182     0x11/imm32/alloc-id:fake
    31183     _string-or-with/imm32/name
    31184     0x11/imm32/alloc-id:fake
    31185     Int-var-and-literal/imm32/inouts
    31186     0/imm32/no-outputs
    31187     0/imm32/no-outputs
    31188     0x11/imm32/alloc-id:fake
    31189     _string_81_subop_or/imm32/subx-name
    31190     1/imm32/rm32-is-first-inout
    31191     0/imm32/no-r32
    31192     2/imm32/imm32-is-second-inout
    31193     0/imm32/no-imm8
    31194     0/imm32/no-disp32
    31195     0/imm32/no-xm32
    31196     0/imm32/no-x32
    31197     0x11/imm32/alloc-id:fake
    31198     _Primitive-xor-with-eax/imm32/next
    31199 # - xor
    31200 _Primitive-xor-with-eax:  # (payload primitive)
    31201     0x11/imm32/alloc-id:fake:payload
    31202     # var/eax <- xor lit => 35/xor-with-eax lit/imm32
    31203     0x11/imm32/alloc-id:fake
    31204     _string-xor/imm32/name
    31205     0x11/imm32/alloc-id:fake
    31206     Single-lit-var/imm32/inouts
    31207     0x11/imm32/alloc-id:fake
    31208     Single-int-var-in-eax/imm32/outputs
    31209     0x11/imm32/alloc-id:fake
    31210     _string_35_xor_with_eax/imm32/subx-name
    31211     0/imm32/no-rm32
    31212     0/imm32/no-r32
    31213     1/imm32/imm32-is-first-inout
    31214     0/imm32/no-imm8
    31215     0/imm32/no-disp32
    31216     0/imm32/no-xm32
    31217     0/imm32/no-x32
    31218     0x11/imm32/alloc-id:fake
    31219     _Primitive-xor-reg-with-reg/imm32/next
    31220 _Primitive-xor-reg-with-reg:  # (payload primitive)
    31221     0x11/imm32/alloc-id:fake:payload
    31222     # var1/reg <- xor var2/reg => 31/xor-with var1/rm32 var2/r32
    31223     0x11/imm32/alloc-id:fake
    31224     _string-xor/imm32/name
    31225     0x11/imm32/alloc-id:fake
    31226     Single-int-var-in-some-register/imm32/inouts
    31227     0x11/imm32/alloc-id:fake
    31228     Single-int-var-in-some-register/imm32/outputs
    31229     0x11/imm32/alloc-id:fake
    31230     _string_31_xor_with/imm32/subx-name
    31231     3/imm32/rm32-is-first-output
    31232     1/imm32/r32-is-first-inout
    31233     0/imm32/no-imm32
    31234     0/imm32/no-imm8
    31235     0/imm32/no-disp32
    31236     0/imm32/no-xm32
    31237     0/imm32/no-x32
    31238     0x11/imm32/alloc-id:fake
    31239     _Primitive-xor-reg-with-mem/imm32/next
    31240 _Primitive-xor-reg-with-mem:  # (payload primitive)
    31241     0x11/imm32/alloc-id:fake:payload
    31242     # xor-with var1 var2/reg => 31/xor-with var1 var2/r32
    31243     0x11/imm32/alloc-id:fake
    31244     _string-xor-with/imm32/name
    31245     0x11/imm32/alloc-id:fake
    31246     Two-args-int-stack-int-reg/imm32/inouts
    31247     0/imm32/no-outputs
    31248     0/imm32/no-outputs
    31249     0x11/imm32/alloc-id:fake
    31250     _string_31_xor_with/imm32/subx-name
    31251     1/imm32/rm32-is-first-inout
    31252     2/imm32/r32-is-second-inout
    31253     0/imm32/no-imm32
    31254     0/imm32/no-imm8
    31255     0/imm32/no-disp32
    31256     0/imm32/no-xm32
    31257     0/imm32/no-x32
    31258     0x11/imm32/alloc-id:fake
    31259     _Primitive-xor-mem-with-reg/imm32/next
    31260 _Primitive-xor-mem-with-reg:  # (payload primitive)
    31261     0x11/imm32/alloc-id:fake:payload
    31262     # var1/reg <- xor var2 => 33/xor var2/rm32 var1/r32
    31263     0x11/imm32/alloc-id:fake
    31264     _string-xor/imm32/name
    31265     0x11/imm32/alloc-id:fake
    31266     Single-int-var-in-mem/imm32/inouts
    31267     0x11/imm32/alloc-id:fake
    31268     Single-int-var-in-some-register/imm32/outputs
    31269     0x11/imm32/alloc-id:fake
    31270     _string_33_xor/imm32/subx-name
    31271     1/imm32/rm32-is-first-inout
    31272     3/imm32/r32-is-first-output
    31273     0/imm32/no-imm32
    31274     0/imm32/no-imm8
    31275     0/imm32/no-disp32
    31276     0/imm32/no-xm32
    31277     0/imm32/no-x32
    31278     0x11/imm32/alloc-id:fake
    31279     _Primitive-xor-lit-with-reg/imm32/next
    31280 _Primitive-xor-lit-with-reg:  # (payload primitive)
    31281     0x11/imm32/alloc-id:fake:payload
    31282     # var1/reg <- xor lit => 81 6/subop/xor var1/rm32 lit/imm32
    31283     0x11/imm32/alloc-id:fake
    31284     _string-xor/imm32/name
    31285     0x11/imm32/alloc-id:fake
    31286     Single-lit-var/imm32/inouts
    31287     0x11/imm32/alloc-id:fake
    31288     Single-int-var-in-some-register/imm32/outputs
    31289     0x11/imm32/alloc-id:fake
    31290     _string_81_subop_xor/imm32/subx-name
    31291     3/imm32/rm32-is-first-output
    31292     0/imm32/no-r32
    31293     1/imm32/imm32-is-first-inout
    31294     0/imm32/no-imm8
    31295     0/imm32/no-disp32
    31296     0/imm32/no-xm32
    31297     0/imm32/no-x32
    31298     0x11/imm32/alloc-id:fake
    31299     _Primitive-xor-lit-with-mem/imm32/next
    31300 _Primitive-xor-lit-with-mem:  # (payload primitive)
    31301     0x11/imm32/alloc-id:fake:payload
    31302     # xor-with var1, lit => 81 6/subop/xor var1/rm32 lit/imm32
    31303     0x11/imm32/alloc-id:fake
    31304     _string-xor-with/imm32/name
    31305     0x11/imm32/alloc-id:fake
    31306     Int-var-and-literal/imm32/inouts
    31307     0/imm32/no-outputs
    31308     0/imm32/no-outputs
    31309     0x11/imm32/alloc-id:fake
    31310     _string_81_subop_xor/imm32/subx-name
    31311     1/imm32/rm32-is-first-inout
    31312     0/imm32/no-r32
    31313     2/imm32/imm32-is-second-inout
    31314     0/imm32/no-imm8
    31315     0/imm32/no-disp32
    31316     0/imm32/no-xm32
    31317     0/imm32/no-x32
    31318     0x11/imm32/alloc-id:fake
    31319     _Primitive-shift-reg-left-by-lit/imm32/next
    31320 _Primitive-shift-reg-left-by-lit:  # (payload primitive)
    31321     0x11/imm32/alloc-id:fake:payload
    31322     # var1/reg <- shift-left lit => c1/shift 4/subop/left var1/rm32 lit/imm32
    31323     0x11/imm32/alloc-id:fake
    31324     _string-shift-left/imm32/name
    31325     0x11/imm32/alloc-id:fake
    31326     Single-lit-var/imm32/inouts
    31327     0x11/imm32/alloc-id:fake
    31328     Single-int-var-in-some-register/imm32/outputs
    31329     0x11/imm32/alloc-id:fake
    31330     _string_c1_subop_shift_left/imm32/subx-name
    31331     3/imm32/rm32-is-first-output
    31332     0/imm32/no-r32
    31333     0/imm32/no-imm32
    31334     1/imm32/imm8-is-first-inout
    31335     0/imm32/no-disp32
    31336     0/imm32/no-xm32
    31337     0/imm32/no-x32
    31338     0x11/imm32/alloc-id:fake
    31339     _Primitive-shift-reg-right-by-lit/imm32/next
    31340 _Primitive-shift-reg-right-by-lit:  # (payload primitive)
    31341     0x11/imm32/alloc-id:fake:payload
    31342     # var1/reg <- shift-right lit => c1/shift 5/subop/right var1/rm32 lit/imm32
    31343     0x11/imm32/alloc-id:fake
    31344     _string-shift-right/imm32/name
    31345     0x11/imm32/alloc-id:fake
    31346     Single-lit-var/imm32/inouts
    31347     0x11/imm32/alloc-id:fake
    31348     Single-int-var-in-some-register/imm32/outputs
    31349     0x11/imm32/alloc-id:fake
    31350     _string_c1_subop_shift_right_padding_zeroes/imm32/subx-name
    31351     3/imm32/rm32-is-first-output
    31352     0/imm32/no-r32
    31353     0/imm32/no-imm32
    31354     1/imm32/imm8-is-first-inout
    31355     0/imm32/no-disp32
    31356     0/imm32/no-xm32
    31357     0/imm32/no-x32
    31358     0x11/imm32/alloc-id:fake
    31359     _Primitive-shift-reg-right-signed-by-lit/imm32/next
    31360 _Primitive-shift-reg-right-signed-by-lit:  # (payload primitive)
    31361     0x11/imm32/alloc-id:fake:payload
    31362     # var1/reg <- shift-right-signed lit => c1/shift 7/subop/right-preserving-sign var1/rm32 lit/imm32
    31363     0x11/imm32/alloc-id:fake
    31364     _string-shift-right-signed/imm32/name
    31365     0x11/imm32/alloc-id:fake
    31366     Single-lit-var/imm32/inouts
    31367     0x11/imm32/alloc-id:fake
    31368     Single-int-var-in-some-register/imm32/outputs
    31369     0x11/imm32/alloc-id:fake
    31370     _string_c1_subop_shift_right_preserving_sign/imm32/subx-name
    31371     3/imm32/rm32-is-first-output
    31372     0/imm32/no-r32
    31373     0/imm32/no-imm32
    31374     1/imm32/imm8-is-first-inout
    31375     0/imm32/no-disp32
    31376     0/imm32/no-xm32
    31377     0/imm32/no-x32
    31378     0x11/imm32/alloc-id:fake
    31379     _Primitive-shift-mem-left-by-lit/imm32/next
    31380 _Primitive-shift-mem-left-by-lit:  # (payload primitive)
    31381     0x11/imm32/alloc-id:fake:payload
    31382     # shift-left var1, lit => c1/shift 4/subop/left var1/rm32 lit/imm32
    31383     0x11/imm32/alloc-id:fake
    31384     _string-shift-left/imm32/name
    31385     0x11/imm32/alloc-id:fake
    31386     Int-var-and-literal/imm32/inouts
    31387     0/imm32/no-outputs
    31388     0/imm32/no-outputs
    31389     0x11/imm32/alloc-id:fake
    31390     _string_c1_subop_shift_left/imm32/subx-name
    31391     1/imm32/rm32-is-first-inout
    31392     0/imm32/no-r32
    31393     0/imm32/no-imm32
    31394     2/imm32/imm8-is-second-inout
    31395     0/imm32/no-disp32
    31396     0/imm32/no-xm32
    31397     0/imm32/no-x32
    31398     0x11/imm32/alloc-id:fake
    31399     _Primitive-shift-mem-right-by-lit/imm32/next
    31400 _Primitive-shift-mem-right-by-lit:  # (payload primitive)
    31401     0x11/imm32/alloc-id:fake:payload
    31402     # shift-right var1, lit => c1/shift 5/subop/right var1/rm32 lit/imm32
    31403     0x11/imm32/alloc-id:fake
    31404     _string-shift-right/imm32/name
    31405     0x11/imm32/alloc-id:fake
    31406     Int-var-and-literal/imm32/inouts
    31407     0/imm32/no-outputs
    31408     0/imm32/no-outputs
    31409     0x11/imm32/alloc-id:fake
    31410     _string_c1_subop_shift_right_padding_zeroes/imm32/subx-name
    31411     1/imm32/rm32-is-first-inout
    31412     0/imm32/no-r32
    31413     0/imm32/no-imm32
    31414     2/imm32/imm8-is-second-inout
    31415     0/imm32/no-disp32
    31416     0/imm32/no-xm32
    31417     0/imm32/no-x32
    31418     0x11/imm32/alloc-id:fake
    31419     _Primitive-shift-mem-right-signed-by-lit/imm32/next
    31420 _Primitive-shift-mem-right-signed-by-lit:  # (payload primitive)
    31421     0x11/imm32/alloc-id:fake:payload
    31422     # shift-right-signed var1, lit => c1/shift 7/subop/right-preserving-sign var1/rm32 lit/imm32
    31423     0x11/imm32/alloc-id:fake
    31424     _string-shift-right-signed/imm32/name
    31425     0x11/imm32/alloc-id:fake
    31426     Int-var-and-literal/imm32/inouts
    31427     0/imm32/no-outputs
    31428     0/imm32/no-outputs
    31429     0x11/imm32/alloc-id:fake
    31430     _string_c1_subop_shift_right_preserving_sign/imm32/subx-name
    31431     1/imm32/rm32-is-first-inout
    31432     0/imm32/no-r32
    31433     0/imm32/no-imm32
    31434     2/imm32/imm8-is-second-inout
    31435     0/imm32/no-disp32
    31436     0/imm32/no-xm32
    31437     0/imm32/no-x32
    31438     0x11/imm32/alloc-id:fake
    31439     _Primitive-copy-to-eax/imm32/next
    31440 # - copy
    31441 _Primitive-copy-to-eax:  # (payload primitive)
    31442     0x11/imm32/alloc-id:fake:payload
    31443     # var/eax <- copy lit => b8/copy-to-eax lit/imm32
    31444     0x11/imm32/alloc-id:fake
    31445     _string-copy/imm32/name
    31446     0x11/imm32/alloc-id:fake
    31447     Single-lit-var/imm32/inouts
    31448     0x11/imm32/alloc-id:fake
    31449     Single-int-var-in-eax/imm32/outputs
    31450     0x11/imm32/alloc-id:fake
    31451     _string_b8_copy_to_eax/imm32/subx-name
    31452     0/imm32/no-rm32
    31453     0/imm32/no-r32
    31454     1/imm32/imm32-is-first-inout
    31455     0/imm32/no-imm8
    31456     0/imm32/no-disp32
    31457     0/imm32/no-xm32
    31458     0/imm32/no-x32
    31459     0x11/imm32/alloc-id:fake
    31460     _Primitive-copy-to-ecx/imm32/next
    31461 _Primitive-copy-to-ecx:  # (payload primitive)
    31462     0x11/imm32/alloc-id:fake:payload
    31463     # var/ecx <- copy lit => b9/copy-to-ecx lit/imm32
    31464     0x11/imm32/alloc-id:fake
    31465     _string-copy/imm32/name
    31466     0x11/imm32/alloc-id:fake
    31467     Single-lit-var/imm32/inouts
    31468     0x11/imm32/alloc-id:fake
    31469     Single-int-var-in-ecx/imm32/outputs
    31470     0x11/imm32/alloc-id:fake
    31471     _string_b9_copy_to_ecx/imm32/subx-name
    31472     0/imm32/no-rm32
    31473     0/imm32/no-r32
    31474     1/imm32/imm32-is-first-inout
    31475     0/imm32/no-imm8
    31476     0/imm32/no-disp32
    31477     0/imm32/no-xm32
    31478     0/imm32/no-x32
    31479     0x11/imm32/alloc-id:fake
    31480     _Primitive-copy-to-edx/imm32/next
    31481 _Primitive-copy-to-edx:  # (payload primitive)
    31482     0x11/imm32/alloc-id:fake:payload
    31483     # var/edx <- copy lit => ba/copy-to-edx lit/imm32
    31484     0x11/imm32/alloc-id:fake
    31485     _string-copy/imm32/name
    31486     0x11/imm32/alloc-id:fake
    31487     Single-lit-var/imm32/inouts
    31488     0x11/imm32/alloc-id:fake
    31489     Single-int-var-in-edx/imm32/outputs
    31490     0x11/imm32/alloc-id:fake
    31491     _string_ba_copy_to_edx/imm32/subx-name
    31492     0/imm32/no-rm32
    31493     0/imm32/no-r32
    31494     1/imm32/imm32-is-first-inout
    31495     0/imm32/no-imm8
    31496     0/imm32/no-disp32
    31497     0/imm32/no-xm32
    31498     0/imm32/no-x32
    31499     0x11/imm32/alloc-id:fake
    31500     _Primitive-copy-to-ebx/imm32/next
    31501 _Primitive-copy-to-ebx:  # (payload primitive)
    31502     0x11/imm32/alloc-id:fake:payload
    31503     # var/ebx <- copy lit => bb/copy-to-ebx lit/imm32
    31504     0x11/imm32/alloc-id:fake
    31505     _string-copy/imm32/name
    31506     0x11/imm32/alloc-id:fake
    31507     Single-lit-var/imm32/inouts
    31508     0x11/imm32/alloc-id:fake
    31509     Single-int-var-in-ebx/imm32/outputs
    31510     0x11/imm32/alloc-id:fake
    31511     _string_bb_copy_to_ebx/imm32/subx-name
    31512     0/imm32/no-rm32
    31513     0/imm32/no-r32
    31514     1/imm32/imm32-is-first-inout
    31515     0/imm32/no-imm8
    31516     0/imm32/no-disp32
    31517     0/imm32/no-xm32
    31518     0/imm32/no-x32
    31519     0x11/imm32/alloc-id:fake
    31520     _Primitive-copy-to-esi/imm32/next
    31521 _Primitive-copy-to-esi:  # (payload primitive)
    31522     0x11/imm32/alloc-id:fake:payload
    31523     # var/esi <- copy lit => be/copy-to-esi lit/imm32
    31524     0x11/imm32/alloc-id:fake
    31525     _string-copy/imm32/name
    31526     0x11/imm32/alloc-id:fake
    31527     Single-lit-var/imm32/inouts
    31528     0x11/imm32/alloc-id:fake
    31529     Single-int-var-in-esi/imm32/outputs
    31530     0x11/imm32/alloc-id:fake
    31531     _string_be_copy_to_esi/imm32/subx-name
    31532     0/imm32/no-rm32
    31533     0/imm32/no-r32
    31534     1/imm32/imm32-is-first-inout
    31535     0/imm32/no-imm8
    31536     0/imm32/no-disp32
    31537     0/imm32/no-xm32
    31538     0/imm32/no-x32
    31539     0x11/imm32/alloc-id:fake
    31540     _Primitive-copy-to-edi/imm32/next
    31541 _Primitive-copy-to-edi:  # (payload primitive)
    31542     0x11/imm32/alloc-id:fake:payload
    31543     # var/edi <- copy lit => bf/copy-to-edi lit/imm32
    31544     0x11/imm32/alloc-id:fake
    31545     _string-copy/imm32/name
    31546     0x11/imm32/alloc-id:fake
    31547     Single-lit-var/imm32/inouts
    31548     0x11/imm32/alloc-id:fake
    31549     Single-int-var-in-edi/imm32/outputs
    31550     0x11/imm32/alloc-id:fake
    31551     _string_bf_copy_to_edi/imm32/subx-name
    31552     0/imm32/no-rm32
    31553     0/imm32/no-r32
    31554     1/imm32/imm32-is-first-inout
    31555     0/imm32/no-imm8
    31556     0/imm32/no-disp32
    31557     0/imm32/no-xm32
    31558     0/imm32/no-x32
    31559     0x11/imm32/alloc-id:fake
    31560     _Primitive-copy-reg-to-reg/imm32/next
    31561 _Primitive-copy-reg-to-reg:  # (payload primitive)
    31562     0x11/imm32/alloc-id:fake:payload
    31563     # var1/reg <- copy var2/reg => 89/<- var1/rm32 var2/r32
    31564     0x11/imm32/alloc-id:fake
    31565     _string-copy/imm32/name
    31566     0x11/imm32/alloc-id:fake
    31567     Single-int-var-in-some-register/imm32/inouts
    31568     0x11/imm32/alloc-id:fake
    31569     Single-int-var-in-some-register/imm32/outputs
    31570     0x11/imm32/alloc-id:fake
    31571     _string_89_<-/imm32/subx-name
    31572     3/imm32/rm32-is-first-output
    31573     1/imm32/r32-is-first-inout
    31574     0/imm32/no-imm32
    31575     0/imm32/no-imm8
    31576     0/imm32/no-disp32
    31577     0/imm32/no-xm32
    31578     0/imm32/no-x32
    31579     0x11/imm32/alloc-id:fake
    31580     _Primitive-copy-reg-to-mem/imm32/next
    31581 _Primitive-copy-reg-to-mem:  # (payload primitive)
    31582     0x11/imm32/alloc-id:fake:payload
    31583     # copy-to var1 var2/reg => 89/<- var1 var2/r32
    31584     0x11/imm32/alloc-id:fake
    31585     _string-copy-to/imm32/name
    31586     0x11/imm32/alloc-id:fake
    31587     Two-args-int-stack-int-reg/imm32/inouts
    31588     0/imm32/no-outputs
    31589     0/imm32/no-outputs
    31590     0x11/imm32/alloc-id:fake
    31591     _string_89_<-/imm32/subx-name
    31592     1/imm32/rm32-is-first-inout
    31593     2/imm32/r32-is-second-inout
    31594     0/imm32/no-imm32
    31595     0/imm32/no-imm8
    31596     0/imm32/no-disp32
    31597     0/imm32/no-xm32
    31598     0/imm32/no-x32
    31599     0x11/imm32/alloc-id:fake
    31600     _Primitive-copy-mem-to-reg/imm32/next
    31601 _Primitive-copy-mem-to-reg:  # (payload primitive)
    31602     0x11/imm32/alloc-id:fake:payload
    31603     # var1/reg <- copy var2 => 8b/-> var2/rm32 var1/r32
    31604     0x11/imm32/alloc-id:fake
    31605     _string-copy/imm32/name
    31606     0x11/imm32/alloc-id:fake
    31607     Single-int-var-in-mem/imm32/inouts
    31608     0x11/imm32/alloc-id:fake
    31609     Single-int-var-in-some-register/imm32/outputs
    31610     0x11/imm32/alloc-id:fake
    31611     _string_8b_->/imm32/subx-name
    31612     1/imm32/rm32-is-first-inout
    31613     3/imm32/r32-is-first-output
    31614     0/imm32/no-imm32
    31615     0/imm32/no-imm8
    31616     0/imm32/no-disp32
    31617     0/imm32/no-xm32
    31618     0/imm32/no-x32
    31619     0x11/imm32/alloc-id:fake
    31620     _Primitive-copy-lit-to-reg/imm32/next
    31621 _Primitive-copy-lit-to-reg:  # (payload primitive)
    31622     0x11/imm32/alloc-id:fake:payload
    31623     # var1/reg <- copy lit => c7 0/subop/copy var1/rm32 lit/imm32
    31624     0x11/imm32/alloc-id:fake
    31625     _string-copy/imm32/name
    31626     0x11/imm32/alloc-id:fake
    31627     Single-lit-var/imm32/inouts
    31628     0x11/imm32/alloc-id:fake
    31629     Single-int-var-in-some-register/imm32/outputs
    31630     0x11/imm32/alloc-id:fake
    31631     _string_c7_subop_copy/imm32/subx-name
    31632     3/imm32/rm32-is-first-output
    31633     0/imm32/no-r32
    31634     1/imm32/imm32-is-first-inout
    31635     0/imm32/no-imm8
    31636     0/imm32/no-disp32
    31637     0/imm32/no-xm32
    31638     0/imm32/no-x32
    31639     0x11/imm32/alloc-id:fake
    31640     _Primitive-copy-lit-to-mem/imm32/next
    31641 _Primitive-copy-lit-to-mem:  # (payload primitive)
    31642     0x11/imm32/alloc-id:fake:payload
    31643     # copy-to var1, lit => c7 0/subop/copy var1/rm32 lit/imm32
    31644     0x11/imm32/alloc-id:fake
    31645     _string-copy-to/imm32/name
    31646     0x11/imm32/alloc-id:fake
    31647     Int-var-and-literal/imm32/inouts
    31648     0/imm32/no-outputs
    31649     0/imm32/no-outputs
    31650     0x11/imm32/alloc-id:fake
    31651     _string_c7_subop_copy/imm32/subx-name
    31652     1/imm32/rm32-is-first-inout
    31653     0/imm32/no-r32
    31654     2/imm32/imm32-is-second-inout
    31655     0/imm32/no-imm8
    31656     0/imm32/no-disp32
    31657     0/imm32/no-xm32
    31658     0/imm32/no-x32
    31659     0x11/imm32/alloc-id:fake
    31660     _Primitive-copy-byte-from-reg/imm32/next
    31661 # - copy byte
    31662 _Primitive-copy-byte-from-reg:
    31663     0x11/imm32/alloc-id:fake:payload
    31664     # var/reg <- copy-byte var2/reg2 => 8a/byte-> %var2 var/r32
    31665     0x11/imm32/alloc-id:fake
    31666     _string-copy-byte/imm32/name
    31667     0x11/imm32/alloc-id:fake
    31668     Single-byte-var-in-some-register/imm32/inouts
    31669     0x11/imm32/alloc-id:fake
    31670     Single-byte-var-in-some-register/imm32/outputs
    31671     0x11/imm32/alloc-id:fake
    31672     _string_8a_copy_byte/imm32/subx-name
    31673     1/imm32/rm32-is-first-inout
    31674     3/imm32/r32-is-first-output
    31675     0/imm32/no-imm32
    31676     0/imm32/no-imm8
    31677     0/imm32/no-disp32
    31678     0/imm32/no-xm32
    31679     0/imm32/no-x32
    31680     0x11/imm32/alloc-id:fake
    31681     _Primitive-copy-byte-from-mem/imm32/next
    31682 _Primitive-copy-byte-from-mem:
    31683     0x11/imm32/alloc-id:fake:payload
    31684     # var/reg <- copy-byte *var2/reg2 => 8a/byte-> *var2 var/r32
    31685     0x11/imm32/alloc-id:fake
    31686     _string-copy-byte/imm32/name
    31687     0x11/imm32/alloc-id:fake
    31688     Single-byte-var-in-mem/imm32/inouts
    31689     0x11/imm32/alloc-id:fake
    31690     Single-byte-var-in-some-register/imm32/outputs
    31691     0x11/imm32/alloc-id:fake
    31692     _string_8a_copy_byte/imm32/subx-name
    31693     1/imm32/rm32-is-first-inout
    31694     3/imm32/r32-is-first-output
    31695     0/imm32/no-imm32
    31696     0/imm32/no-imm8
    31697     0/imm32/no-disp32
    31698     0/imm32/no-xm32
    31699     0/imm32/no-x32
    31700     0x11/imm32/alloc-id:fake
    31701     _Primitive-copy-byte-to-mem/imm32/next
    31702 _Primitive-copy-byte-to-mem:
    31703     0x11/imm32/alloc-id:fake:payload
    31704     # copy-byte-to *var1/reg1, var2/reg2 => 88/byte<- *reg1 reg2/r32
    31705     0x11/imm32/alloc-id:fake
    31706     _string-copy-byte-to/imm32/name
    31707     0x11/imm32/alloc-id:fake
    31708     Two-args-byte-stack-byte-reg/imm32/inouts
    31709     0/imm32/no-outputs
    31710     0/imm32/no-outputs
    31711     0x11/imm32/alloc-id:fake
    31712     _string_88_copy_byte/imm32/subx-name
    31713     1/imm32/rm32-is-first-inout
    31714     2/imm32/r32-is-second-inout
    31715     0/imm32/no-imm32
    31716     0/imm32/no-imm8
    31717     0/imm32/no-disp32
    31718     0/imm32/no-xm32
    31719     0/imm32/no-x32
    31720     0x11/imm32/alloc-id:fake
    31721     _Primitive-address/imm32/next
    31722 # - address
    31723 _Primitive-address:  # (payload primitive)
    31724     0x11/imm32/alloc-id:fake:payload
    31725     # var1/reg <- address var2 => 8d/copy-address var2/rm32 var1/r32
    31726     0x11/imm32/alloc-id:fake
    31727     _string-address/imm32/name
    31728     0x11/imm32/alloc-id:fake
    31729     Single-int-var-in-mem/imm32/inouts
    31730     0x11/imm32/alloc-id:fake
    31731     Single-addr-var-in-some-register/imm32/outputs
    31732     0x11/imm32/alloc-id:fake
    31733     _string_8d_copy_address/imm32/subx-name
    31734     1/imm32/rm32-is-first-inout
    31735     3/imm32/r32-is-first-output
    31736     0/imm32/no-imm32
    31737     0/imm32/no-imm8
    31738     0/imm32/no-disp32
    31739     0/imm32/no-xm32
    31740     0/imm32/no-x32
    31741     0x11/imm32/alloc-id:fake
    31742     _Primitive-compare-reg-with-reg/imm32/next
    31743 # - compare
    31744 _Primitive-compare-reg-with-reg:  # (payload primitive)
    31745     0x11/imm32/alloc-id:fake:payload
    31746     # compare var1/reg1 var2/reg2 => 39/compare var1/rm32 var2/r32
    31747     0x11/imm32/alloc-id:fake
    31748     _string-compare/imm32/name
    31749     0x11/imm32/alloc-id:fake
    31750     Two-int-args-in-regs/imm32/inouts
    31751     0/imm32/no-outputs
    31752     0/imm32/no-outputs
    31753     0x11/imm32/alloc-id:fake
    31754     _string_39_compare->/imm32/subx-name
    31755     1/imm32/rm32-is-first-inout
    31756     2/imm32/r32-is-second-inout
    31757     0/imm32/no-imm32
    31758     0/imm32/no-imm8
    31759     0/imm32/no-disp32
    31760     0/imm32/no-xm32
    31761     0/imm32/no-x32
    31762     0x11/imm32/alloc-id:fake
    31763     _Primitive-compare-mem-with-reg/imm32/next
    31764 _Primitive-compare-mem-with-reg:  # (payload primitive)
    31765     0x11/imm32/alloc-id:fake:payload
    31766     # compare var1 var2/reg => 39/compare var1/rm32 var2/r32
    31767     0x11/imm32/alloc-id:fake
    31768     _string-compare/imm32/name
    31769     0x11/imm32/alloc-id:fake
    31770     Two-args-int-stack-int-reg/imm32/inouts
    31771     0/imm32/no-outputs
    31772     0/imm32/no-outputs
    31773     0x11/imm32/alloc-id:fake
    31774     _string_39_compare->/imm32/subx-name
    31775     1/imm32/rm32-is-first-inout
    31776     2/imm32/r32-is-second-inout
    31777     0/imm32/no-imm32
    31778     0/imm32/no-imm8
    31779     0/imm32/no-disp32
    31780     0/imm32/no-xm32
    31781     0/imm32/no-x32
    31782     0x11/imm32/alloc-id:fake
    31783     _Primitive-compare-reg-with-mem/imm32/next
    31784 _Primitive-compare-reg-with-mem:  # (payload primitive)
    31785     0x11/imm32/alloc-id:fake:payload
    31786     # compare var1/reg var2 => 3b/compare<- var2/rm32 var1/r32
    31787     0x11/imm32/alloc-id:fake
    31788     _string-compare/imm32/name
    31789     0x11/imm32/alloc-id:fake
    31790     Two-args-int-reg-int-stack/imm32/inouts
    31791     0/imm32/no-outputs
    31792     0/imm32/no-outputs
    31793     0x11/imm32/alloc-id:fake
    31794     _string_3b_compare<-/imm32/subx-name
    31795     2/imm32/rm32-is-second-inout
    31796     1/imm32/r32-is-first-inout
    31797     0/imm32/no-imm32
    31798     0/imm32/no-imm8
    31799     0/imm32/no-disp32
    31800     0/imm32/no-xm32
    31801     0/imm32/no-x32
    31802     0x11/imm32/alloc-id:fake
    31803     _Primitive-compare-eax-with-literal/imm32/next
    31804 _Primitive-compare-eax-with-literal:  # (payload primitive)
    31805     0x11/imm32/alloc-id:fake:payload
    31806     # compare var1/eax n => 3d/compare-eax-with n/imm32
    31807     0x11/imm32/alloc-id:fake
    31808     _string-compare/imm32/name
    31809     0x11/imm32/alloc-id:fake
    31810     Two-args-int-eax-int-literal/imm32/inouts
    31811     0/imm32/no-outputs
    31812     0/imm32/no-outputs
    31813     0x11/imm32/alloc-id:fake
    31814     _string_3d_compare_eax_with/imm32/subx-name
    31815     0/imm32/no-rm32
    31816     0/imm32/no-r32
    31817     2/imm32/imm32-is-second-inout
    31818     0/imm32/no-imm8
    31819     0/imm32/no-disp32
    31820     0/imm32/no-xm32
    31821     0/imm32/no-x32
    31822     0x11/imm32/alloc-id:fake
    31823     _Primitive-compare-reg-with-literal/imm32/next
    31824 _Primitive-compare-reg-with-literal:  # (payload primitive)
    31825     0x11/imm32/alloc-id:fake:payload
    31826     # compare var1/reg n => 81 7/subop/compare %reg n/imm32
    31827     0x11/imm32/alloc-id:fake
    31828     _string-compare/imm32/name
    31829     0x11/imm32/alloc-id:fake
    31830     Int-var-in-register-and-literal/imm32/inouts
    31831     0/imm32/no-outputs
    31832     0/imm32/no-outputs
    31833     0x11/imm32/alloc-id:fake
    31834     _string_81_subop_compare/imm32/subx-name
    31835     1/imm32/rm32-is-first-inout
    31836     0/imm32/no-r32
    31837     2/imm32/imm32-is-second-inout
    31838     0/imm32/no-imm8
    31839     0/imm32/no-disp32
    31840     0/imm32/no-xm32
    31841     0/imm32/no-x32
    31842     0x11/imm32/alloc-id:fake
    31843     _Primitive-compare-mem-with-literal/imm32/next
    31844 _Primitive-compare-mem-with-literal:  # (payload primitive)
    31845     0x11/imm32/alloc-id:fake:payload
    31846     # compare var1 n => 81 7/subop/compare *(ebp+___) n/imm32
    31847     0x11/imm32/alloc-id:fake
    31848     _string-compare/imm32/name
    31849     0x11/imm32/alloc-id:fake
    31850     Int-var-and-literal/imm32/inouts
    31851     0/imm32/no-outputs
    31852     0/imm32/no-outputs
    31853     0x11/imm32/alloc-id:fake
    31854     _string_81_subop_compare/imm32/subx-name
    31855     1/imm32/rm32-is-first-inout
    31856     0/imm32/no-r32
    31857     2/imm32/imm32-is-second-inout
    31858     0/imm32/no-imm8
    31859     0/imm32/no-disp32
    31860     0/imm32/no-xm32
    31861     0/imm32/no-x32
    31862     0x11/imm32/alloc-id:fake
    31863     _Primitive-negate-reg/imm32/next
    31864 # - negate
    31865 _Primitive-negate-reg:  # (payload primitive)
    31866     0x11/imm32/alloc-id:fake:payload
    31867     # var1/reg <- negate => f7 3/subop/negate var1/rm32
    31868     0x11/imm32/alloc-id:fake
    31869     _string-negate/imm32/name
    31870     0/imm32/no-inouts
    31871     0/imm32/no-inouts
    31872     0x11/imm32/alloc-id:fake
    31873     Single-int-var-in-some-register/imm32/outputs
    31874     0x11/imm32/alloc-id:fake
    31875     _string_f7_subop_negate/imm32/subx-name
    31876     3/imm32/rm32-is-first-output
    31877     0/imm32/no-r32
    31878     0/imm32/no-imm32
    31879     0/imm32/no-imm8
    31880     0/imm32/no-disp32
    31881     0/imm32/no-xm32
    31882     0/imm32/no-x32
    31883     0x11/imm32/alloc-id:fake
    31884     _Primitive-negate-mem/imm32/next
    31885 _Primitive-negate-mem:  # (payload primitive)
    31886     0x11/imm32/alloc-id:fake:payload
    31887     # negate var1 => f7 3/subop/negate var1/rm32
    31888     0x11/imm32/alloc-id:fake
    31889     _string-negate/imm32/name
    31890     0x11/imm32/alloc-id:fake
    31891     Single-int-var-in-mem/imm32/inouts
    31892     0/imm32/no-outputs
    31893     0/imm32/no-outputs
    31894     0x11/imm32/alloc-id:fake
    31895     _string_f7_subop_negate/imm32/subx-name
    31896     1/imm32/rm32-is-first-inout
    31897     0/imm32/no-r32
    31898     0/imm32/no-imm32
    31899     0/imm32/no-imm8
    31900     0/imm32/no-disp32
    31901     0/imm32/no-xm32
    31902     0/imm32/no-x32
    31903     0x11/imm32/alloc-id:fake
    31904     _Primitive-multiply-reg-by-reg/imm32/next
    31905 # - multiply
    31906 _Primitive-multiply-reg-by-reg:  # (payload primitive)
    31907     0x11/imm32/alloc-id:fake:payload
    31908     # var1/reg <- multiply var2 => 0f af/multiply var2/rm32 var1/r32
    31909     0x11/imm32/alloc-id:fake
    31910     _string-multiply/imm32/name
    31911     0x11/imm32/alloc-id:fake
    31912     Single-int-var-in-some-register/imm32/inouts
    31913     0x11/imm32/alloc-id:fake
    31914     Single-int-var-in-some-register/imm32/outputs
    31915     0x11/imm32/alloc-id:fake
    31916     _string_0f_af_multiply/imm32/subx-name
    31917     1/imm32/rm32-is-first-inout
    31918     3/imm32/r32-is-first-output
    31919     0/imm32/no-imm32
    31920     0/imm32/no-imm8
    31921     0/imm32/no-disp32
    31922     0/imm32/no-xm32
    31923     0/imm32/no-x32
    31924     0x11/imm32/alloc-id:fake
    31925     _Primitive-multiply-reg-by-mem/imm32/next
    31926 _Primitive-multiply-reg-by-mem:  # (payload primitive)
    31927     0x11/imm32/alloc-id:fake:payload
    31928     # var1/reg <- multiply var2 => 0f af/multiply var2/rm32 var1/r32
    31929     0x11/imm32/alloc-id:fake
    31930     _string-multiply/imm32/name
    31931     0x11/imm32/alloc-id:fake
    31932     Single-int-var-in-mem/imm32/inouts
    31933     0x11/imm32/alloc-id:fake
    31934     Single-int-var-in-some-register/imm32/outputs
    31935     0x11/imm32/alloc-id:fake
    31936     _string_0f_af_multiply/imm32/subx-name
    31937     1/imm32/rm32-is-first-inout
    31938     3/imm32/r32-is-first-output
    31939     0/imm32/no-imm32
    31940     0/imm32/no-imm8
    31941     0/imm32/no-disp32
    31942     0/imm32/no-xm32
    31943     0/imm32/no-x32
    31944     0x11/imm32/alloc-id:fake
    31945     _Primitive-convert-mem-to-xreg/imm32/next
    31946 # - convert int to floating point
    31947 _Primitive-convert-mem-to-xreg:  # (payload primitive)
    31948     0x11/imm32/alloc-id:fake:payload
    31949     # var1/xreg <- convert var2 => f3 0f 2a/convert-to-float var2/rm32 var1/x32
    31950     0x11/imm32/alloc-id:fake
    31951     _string-convert/imm32/name
    31952     0x11/imm32/alloc-id:fake
    31953     Single-int-var-in-mem/imm32/inouts
    31954     0x11/imm32/alloc-id:fake
    31955     Single-float-var-in-some-register/imm32/outputs
    31956     0x11/imm32/alloc-id:fake
    31957     _string_f3_0f_2a_convert_to_float/imm32/subx-name
    31958     1/imm32/rm32-is-first-inout
    31959     0/imm32/no-r32
    31960     0/imm32/no-imm32
    31961     0/imm32/no-imm8
    31962     0/imm32/no-disp32
    31963     0/imm32/no-xm32
    31964     3/imm32/x32-is-first-output
    31965     0x11/imm32/alloc-id:fake
    31966     _Primitive-convert-reg-to-xreg/imm32/next
    31967 _Primitive-convert-reg-to-xreg:  # (payload primitive)
    31968     0x11/imm32/alloc-id:fake:payload
    31969     # var1/xreg <- convert var2/reg => f3 0f 2a/convert-to-float var2/rm32 var1/x32
    31970     0x11/imm32/alloc-id:fake
    31971     _string-convert/imm32/name
    31972     0x11/imm32/alloc-id:fake
    31973     Single-int-var-in-some-register/imm32/inouts
    31974     0x11/imm32/alloc-id:fake
    31975     Single-float-var-in-some-register/imm32/outputs
    31976     0x11/imm32/alloc-id:fake
    31977     _string_f3_0f_2a_convert_to_float/imm32/subx-name
    31978     1/imm32/rm32-is-first-inout
    31979     0/imm32/no-r32
    31980     0/imm32/no-imm32
    31981     0/imm32/no-imm8
    31982     0/imm32/no-disp32
    31983     0/imm32/no-xm32
    31984     3/imm32/x32-is-first-output
    31985     0x11/imm32/alloc-id:fake
    31986     _Primitive-convert-xmem-to-reg/imm32/next
    31987 # - convert floating point to int
    31988 _Primitive-convert-xmem-to-reg:  # (payload primitive)
    31989     0x11/imm32/alloc-id:fake:payload
    31990     # var1/reg <- convert var2 => f3 0f 2d/convert-to-int var2/xm32 var1/r32
    31991     0x11/imm32/alloc-id:fake
    31992     _string-convert/imm32/name
    31993     0x11/imm32/alloc-id:fake
    31994     Single-float-var-in-mem/imm32/inouts
    31995     0x11/imm32/alloc-id:fake
    31996     Single-int-var-in-some-register/imm32/outputs
    31997     0x11/imm32/alloc-id:fake
    31998     _string_f3_0f_2d_convert_to_int/imm32/subx-name
    31999     0/imm32/no-rm32
    32000     3/imm32/r32-is-first-output
    32001     0/imm32/no-imm32
    32002     0/imm32/no-imm8
    32003     0/imm32/no-disp32
    32004     1/imm32/xm32-is-first-inout
    32005     0/imm32/no-x32
    32006     0x11/imm32/alloc-id:fake
    32007     _Primitive-convert-xreg-to-reg/imm32/next
    32008 _Primitive-convert-xreg-to-reg:  # (payload primitive)
    32009     0x11/imm32/alloc-id:fake:payload
    32010     # var1/reg <- convert var2/xreg => f3 0f 2d/convert-to-int var2/xm32 var1/r32
    32011     0x11/imm32/alloc-id:fake
    32012     _string-convert/imm32/name
    32013     0x11/imm32/alloc-id:fake
    32014     Single-float-var-in-some-register/imm32/inouts
    32015     0x11/imm32/alloc-id:fake
    32016     Single-int-var-in-some-register/imm32/outputs
    32017     0x11/imm32/alloc-id:fake
    32018     _string_f3_0f_2d_convert_to_int/imm32/subx-name
    32019     0/imm32/no-rm32
    32020     3/imm32/r32-is-first-output
    32021     0/imm32/no-imm32
    32022     0/imm32/no-imm8
    32023     0/imm32/no-disp32
    32024     1/imm32/xm32-is-first-inout
    32025     0/imm32/no-x32
    32026     0x11/imm32/alloc-id:fake
    32027     _Primitive-truncate-xmem-to-reg/imm32/next
    32028 _Primitive-truncate-xmem-to-reg:  # (payload primitive)
    32029     0x11/imm32/alloc-id:fake:payload
    32030     # var1/reg <- truncate var2 => f3 0f 2c/truncate-to-int var2/xm32 var1/r32
    32031     0x11/imm32/alloc-id:fake
    32032     _string-truncate/imm32/name
    32033     0x11/imm32/alloc-id:fake
    32034     Single-float-var-in-mem/imm32/inouts
    32035     0x11/imm32/alloc-id:fake
    32036     Single-int-var-in-some-register/imm32/outputs
    32037     0x11/imm32/alloc-id:fake
    32038     _string_f3_0f_2c_truncate_to_int/imm32/subx-name
    32039     0/imm32/no-rm32
    32040     3/imm32/r32-is-first-output
    32041     0/imm32/no-imm32
    32042     0/imm32/no-imm8
    32043     0/imm32/no-disp32
    32044     1/imm32/xm32-is-first-inout
    32045     0/imm32/no-x32
    32046     0x11/imm32/alloc-id:fake
    32047     _Primitive-truncate-xreg-to-reg/imm32/next
    32048 _Primitive-truncate-xreg-to-reg:  # (payload primitive)
    32049     0x11/imm32/alloc-id:fake:payload
    32050     # var1/reg <- truncate var2/xreg => f3 0f 2c/truncate-to-int var2/xm32 var1/r32
    32051     0x11/imm32/alloc-id:fake
    32052     _string-truncate/imm32/name
    32053     0x11/imm32/alloc-id:fake
    32054     Single-float-var-in-some-register/imm32/inouts
    32055     0x11/imm32/alloc-id:fake
    32056     Single-int-var-in-some-register/imm32/outputs
    32057     0x11/imm32/alloc-id:fake
    32058     _string_f3_0f_2c_truncate_to_int/imm32/subx-name
    32059     0/imm32/no-rm32
    32060     3/imm32/r32-is-first-output
    32061     0/imm32/no-imm32
    32062     0/imm32/no-imm8
    32063     0/imm32/no-disp32
    32064     1/imm32/xm32-is-first-inout
    32065     0/imm32/no-x32
    32066     0x11/imm32/alloc-id:fake
    32067     _Primitive-reinterpret-xmem-as-reg/imm32/next
    32068 # - reinterpret bytes (just for debugging)
    32069 _Primitive-reinterpret-xmem-as-reg:  # (payload primitive)
    32070     0x11/imm32/alloc-id:fake:payload
    32071     # var1/reg <- reinterpret var2 => 8b/-> var2/xm32 var1/r32
    32072     0x11/imm32/alloc-id:fake
    32073     _string-reinterpret/imm32/name
    32074     0x11/imm32/alloc-id:fake
    32075     Single-float-var-in-mem/imm32/inouts
    32076     0x11/imm32/alloc-id:fake
    32077     Single-int-var-in-some-register/imm32/outputs
    32078     0x11/imm32/alloc-id:fake
    32079     _string_8b_->/imm32/subx-name
    32080     0/imm32/no-rm32
    32081     3/imm32/r32-is-first-output
    32082     0/imm32/no-imm32
    32083     0/imm32/no-imm8
    32084     0/imm32/no-disp32
    32085     1/imm32/xm32-is-first-inout
    32086     0/imm32/no-x32
    32087     0x11/imm32/alloc-id:fake
    32088     _Primitive-reinterpret-mem-as-xreg/imm32/next
    32089 _Primitive-reinterpret-mem-as-xreg:  # (payload primitive)
    32090     0x11/imm32/alloc-id:fake:payload
    32091     # var1/xreg <- reinterpret var2 => f3 0f 10/-> var2/rm32 var1/x32
    32092     0x11/imm32/alloc-id:fake
    32093     _string-reinterpret/imm32/name
    32094     0x11/imm32/alloc-id:fake
    32095     Single-int-var-in-mem/imm32/inouts
    32096     0x11/imm32/alloc-id:fake
    32097     Single-float-var-in-some-register/imm32/outputs
    32098     0x11/imm32/alloc-id:fake
    32099     _string_f3_0f_10_copy/imm32/subx-name
    32100     1/imm32/rm32-is-first-inout
    32101     0/imm32/no-r32
    32102     0/imm32/no-imm32
    32103     0/imm32/no-imm8
    32104     0/imm32/no-disp32
    32105     0/imm32/no-xm32
    32106     3/imm32/x32-is-first-output
    32107     0x11/imm32/alloc-id:fake
    32108     _Primitive-copy-xreg-to-xreg/imm32/next
    32109 # - floating-point copy
    32110 _Primitive-copy-xreg-to-xreg:  # (payload primitive)
    32111     0x11/imm32/alloc-id:fake:payload
    32112     # var1/xreg <- copy var2/xreg => f3 0f 11/<- var1/xm32 var2/x32
    32113     0x11/imm32/alloc-id:fake
    32114     _string-copy/imm32/name
    32115     0x11/imm32/alloc-id:fake
    32116     Single-float-var-in-some-register/imm32/inouts
    32117     0x11/imm32/alloc-id:fake
    32118     Single-float-var-in-some-register/imm32/outputs
    32119     0x11/imm32/alloc-id:fake
    32120     _string_f3_0f_11_copy/imm32/subx-name
    32121     0/imm32/no-rm32
    32122     0/imm32/no-r32
    32123     0/imm32/no-imm32
    32124     0/imm32/no-imm8
    32125     0/imm32/no-disp32
    32126     3/imm32/xm32-is-first-output
    32127     1/imm32/x32-is-first-inout
    32128     0x11/imm32/alloc-id:fake
    32129     _Primitive-copy-xreg-to-mem/imm32/next
    32130 _Primitive-copy-xreg-to-mem:  # (payload primitive)
    32131     0x11/imm32/alloc-id:fake:payload
    32132     # copy-to var1 var2/xreg => f3 0f 11/<- var1 var2/x32
    32133     0x11/imm32/alloc-id:fake
    32134     _string-copy-to/imm32/name
    32135     0x11/imm32/alloc-id:fake
    32136     Two-args-float-stack-float-reg/imm32/inouts
    32137     0/imm32/no-outputs
    32138     0/imm32/no-outputs
    32139     0x11/imm32/alloc-id:fake
    32140     _string_f3_0f_11_copy/imm32/subx-name
    32141     0/imm32/no-rm32
    32142     0/imm32/no-r32
    32143     0/imm32/no-imm32
    32144     0/imm32/no-imm8
    32145     0/imm32/no-disp32
    32146     1/imm32/xm32-is-first-inout
    32147     2/imm32/x32-is-second-inout
    32148     0x11/imm32/alloc-id:fake
    32149     _Primitive-copy-mem-to-xreg/imm32/next
    32150 _Primitive-copy-mem-to-xreg:  # (payload primitive)
    32151     0x11/imm32/alloc-id:fake:payload
    32152     # var1/xreg <- copy var2 => f3 0f 10/-> var2/rm32 var1/x32
    32153     0x11/imm32/alloc-id:fake
    32154     _string-copy/imm32/name
    32155     0x11/imm32/alloc-id:fake
    32156     Single-float-var-in-mem/imm32/inouts
    32157     0x11/imm32/alloc-id:fake
    32158     Single-float-var-in-some-register/imm32/outputs
    32159     0x11/imm32/alloc-id:fake
    32160     _string_f3_0f_10_copy/imm32/subx-name
    32161     0/imm32/no-rm32
    32162     0/imm32/no-r32
    32163     0/imm32/no-imm32
    32164     0/imm32/no-imm8
    32165     0/imm32/no-disp32
    32166     1/imm32/xm32-is-first-inout
    32167     3/imm32/x32-is-first-output
    32168     0x11/imm32/alloc-id:fake
    32169     _Primitive-address-of-xmem/imm32/next
    32170 # - floating-point-address
    32171 _Primitive-address-of-xmem:  # (payload primitive)
    32172     0x11/imm32/alloc-id:fake:payload
    32173     # var1/reg <- address var2 => 8d/copy-address var2/rm32 var1/r32
    32174     0x11/imm32/alloc-id:fake
    32175     _string-address/imm32/name
    32176     0x11/imm32/alloc-id:fake
    32177     Single-float-var-in-mem/imm32/inouts
    32178     0x11/imm32/alloc-id:fake
    32179     Single-addr-var-in-some-register/imm32/outputs
    32180     0x11/imm32/alloc-id:fake
    32181     _string_8d_copy_address/imm32/subx-name
    32182     1/imm32/rm32-is-first-inout
    32183     3/imm32/r32-is-first-output
    32184     0/imm32/no-imm32
    32185     0/imm32/no-imm8
    32186     0/imm32/no-disp32
    32187     0/imm32/no-xm32
    32188     0/imm32/no-x32
    32189     0x11/imm32/alloc-id:fake
    32190     _Primitive-add-xreg-to-xreg/imm32/next
    32191 # - floating-point add
    32192 _Primitive-add-xreg-to-xreg:  # (payload primitive)
    32193     0x11/imm32/alloc-id:fake:payload
    32194     # var1/xreg <- add var2/xreg => f3 0f 58/add var1/xm32 var2/x32
    32195     0x11/imm32/alloc-id:fake
    32196     _string-add/imm32/name
    32197     0x11/imm32/alloc-id:fake
    32198     Single-float-var-in-some-register/imm32/inouts
    32199     0x11/imm32/alloc-id:fake
    32200     Single-float-var-in-some-register/imm32/outputs
    32201     0x11/imm32/alloc-id:fake
    32202     _string_f3_0f_58_add/imm32/subx-name
    32203     0/imm32/no-rm32
    32204     0/imm32/no-r32
    32205     0/imm32/no-imm32
    32206     0/imm32/no-imm8
    32207     0/imm32/no-disp32
    32208     1/imm32/xm32-is-first-inout
    32209     3/imm32/x32-is-first-output
    32210     0x11/imm32/alloc-id:fake
    32211     _Primitive-add-mem-to-xreg/imm32/next
    32212 _Primitive-add-mem-to-xreg:  # (payload primitive)
    32213     0x11/imm32/alloc-id:fake:payload
    32214     # var1/xreg <- add var2 => f3 0f 58/add var2/xm32 var1/x32
    32215     0x11/imm32/alloc-id:fake
    32216     _string-add/imm32/name
    32217     0x11/imm32/alloc-id:fake
    32218     Single-float-var-in-mem/imm32/inouts
    32219     0x11/imm32/alloc-id:fake
    32220     Single-float-var-in-some-register/imm32/outputs
    32221     0x11/imm32/alloc-id:fake
    32222     _string_f3_0f_58_add/imm32/subx-name
    32223     0/imm32/no-rm32
    32224     0/imm32/no-r32
    32225     0/imm32/no-imm32
    32226     0/imm32/no-imm8
    32227     0/imm32/no-disp32
    32228     1/imm32/xm32-is-first-inout
    32229     3/imm32/x32-is-first-output
    32230     0x11/imm32/alloc-id:fake
    32231     _Primitive-subtract-xreg-from-xreg/imm32/next
    32232 # - floating-point subtract
    32233 _Primitive-subtract-xreg-from-xreg:  # (payload primitive)
    32234     0x11/imm32/alloc-id:fake:payload
    32235     # var1/xreg <- subtract var2/xreg => f3 0f 5c/subtract var1/xm32 var2/x32
    32236     0x11/imm32/alloc-id:fake
    32237     _string-subtract/imm32/name
    32238     0x11/imm32/alloc-id:fake
    32239     Single-float-var-in-some-register/imm32/inouts
    32240     0x11/imm32/alloc-id:fake
    32241     Single-float-var-in-some-register/imm32/outputs
    32242     0x11/imm32/alloc-id:fake
    32243     _string_f3_0f_5c_subtract/imm32/subx-name
    32244     0/imm32/no-rm32
    32245     0/imm32/no-r32
    32246     0/imm32/no-imm32
    32247     0/imm32/no-imm8
    32248     0/imm32/no-disp32
    32249     1/imm32/xm32-is-first-inout
    32250     3/imm32/x32-is-first-output
    32251     0x11/imm32/alloc-id:fake
    32252     _Primitive-subtract-mem-from-xreg/imm32/next
    32253 _Primitive-subtract-mem-from-xreg:  # (payload primitive)
    32254     0x11/imm32/alloc-id:fake:payload
    32255     # var1/xreg <- subtract var2 => f3 0f 5c/subtract var2/xm32 var1/x32
    32256     0x11/imm32/alloc-id:fake
    32257     _string-subtract/imm32/name
    32258     0x11/imm32/alloc-id:fake
    32259     Single-float-var-in-mem/imm32/inouts
    32260     0x11/imm32/alloc-id:fake
    32261     Single-float-var-in-some-register/imm32/outputs
    32262     0x11/imm32/alloc-id:fake
    32263     _string_f3_0f_5c_subtract/imm32/subx-name
    32264     0/imm32/no-rm32
    32265     0/imm32/no-r32
    32266     0/imm32/no-imm32
    32267     0/imm32/no-imm8
    32268     0/imm32/no-disp32
    32269     1/imm32/xm32-is-first-inout
    32270     3/imm32/x32-is-first-output
    32271     0x11/imm32/alloc-id:fake
    32272     _Primitive-multiply-xreg-by-xreg/imm32/next
    32273 # - floating-point multiply
    32274 _Primitive-multiply-xreg-by-xreg:  # (payload primitive)
    32275     0x11/imm32/alloc-id:fake:payload
    32276     # var1/xreg <- multiply var2 => f3 0f 59/multiply var2/xm32 var1/x32
    32277     0x11/imm32/alloc-id:fake
    32278     _string-multiply/imm32/name
    32279     0x11/imm32/alloc-id:fake
    32280     Single-float-var-in-some-register/imm32/inouts
    32281     0x11/imm32/alloc-id:fake
    32282     Single-float-var-in-some-register/imm32/outputs
    32283     0x11/imm32/alloc-id:fake
    32284     _string_f3_0f_59_multiply/imm32/subx-name
    32285     0/imm32/no-rm32
    32286     0/imm32/no-r32
    32287     0/imm32/no-imm32
    32288     0/imm32/no-imm8
    32289     0/imm32/no-disp32
    32290     1/imm32/xm32-is-first-inout
    32291     3/imm32/x32-is-first-output
    32292     0x11/imm32/alloc-id:fake
    32293     _Primitive-multiply-xreg-by-mem/imm32/next
    32294 _Primitive-multiply-xreg-by-mem:  # (payload primitive)
    32295     0x11/imm32/alloc-id:fake:payload
    32296     # var1/xreg <- multiply var2 => 53 0f 59/multiply var2/xm32 var1/x32
    32297     0x11/imm32/alloc-id:fake
    32298     _string-multiply/imm32/name
    32299     0x11/imm32/alloc-id:fake
    32300     Single-float-var-in-mem/imm32/inouts
    32301     0x11/imm32/alloc-id:fake
    32302     Single-float-var-in-some-register/imm32/outputs
    32303     0x11/imm32/alloc-id:fake
    32304     _string_f3_0f_59_multiply/imm32/subx-name
    32305     0/imm32/no-rm32
    32306     0/imm32/no-r32
    32307     0/imm32/no-imm32
    32308     0/imm32/no-imm8
    32309     0/imm32/no-disp32
    32310     1/imm32/xm32-is-first-inout
    32311     3/imm32/x32-is-first-output
    32312     0x11/imm32/alloc-id:fake
    32313     _Primitive-divide-xreg-by-xreg/imm32/next
    32314 # - floating-point divide
    32315 _Primitive-divide-xreg-by-xreg:  # (payload primitive)
    32316     0x11/imm32/alloc-id:fake:payload
    32317     # var1/xreg <- divide var2 => f3 0f 5e/divide var2/xm32 var1/x32
    32318     0x11/imm32/alloc-id:fake
    32319     _string-divide/imm32/name
    32320     0x11/imm32/alloc-id:fake
    32321     Single-float-var-in-some-register/imm32/inouts
    32322     0x11/imm32/alloc-id:fake
    32323     Single-float-var-in-some-register/imm32/outputs
    32324     0x11/imm32/alloc-id:fake
    32325     _string_f3_0f_5e_divide/imm32/subx-name
    32326     0/imm32/no-rm32
    32327     0/imm32/no-r32
    32328     0/imm32/no-imm32
    32329     0/imm32/no-imm8
    32330     0/imm32/no-disp32
    32331     1/imm32/xm32-is-first-inout
    32332     3/imm32/x32-is-first-output
    32333     0x11/imm32/alloc-id:fake
    32334     _Primitive-divide-xreg-by-mem/imm32/next
    32335 _Primitive-divide-xreg-by-mem:  # (payload primitive)
    32336     0x11/imm32/alloc-id:fake:payload
    32337     # var1/xreg <- divide var2 => f3 0f 5e/divide var2/xm32 var1/x32
    32338     0x11/imm32/alloc-id:fake
    32339     _string-divide/imm32/name
    32340     0x11/imm32/alloc-id:fake
    32341     Single-float-var-in-mem/imm32/inouts
    32342     0x11/imm32/alloc-id:fake
    32343     Single-float-var-in-some-register/imm32/outputs
    32344     0x11/imm32/alloc-id:fake
    32345     _string_f3_0f_5e_divide/imm32/subx-name
    32346     0/imm32/no-rm32
    32347     0/imm32/no-r32
    32348     0/imm32/no-imm32
    32349     0/imm32/no-imm8
    32350     0/imm32/no-disp32
    32351     1/imm32/xm32-is-first-inout
    32352     3/imm32/x32-is-first-output
    32353     0x11/imm32/alloc-id:fake
    32354     _Primitive-max-xreg-with-xreg/imm32/next
    32355 # - floating-point maximum
    32356 _Primitive-max-xreg-with-xreg:  # (payload primitive)
    32357     0x11/imm32/alloc-id:fake:payload
    32358     # var1/xreg <- max var2 => f3 0f 5f/max var2/xm32 var1/x32
    32359     0x11/imm32/alloc-id:fake
    32360     _string-max/imm32/name
    32361     0x11/imm32/alloc-id:fake
    32362     Single-float-var-in-some-register/imm32/inouts
    32363     0x11/imm32/alloc-id:fake
    32364     Single-float-var-in-some-register/imm32/outputs
    32365     0x11/imm32/alloc-id:fake
    32366     _string_f3_0f_5f_max/imm32/subx-name
    32367     0/imm32/no-rm32
    32368     0/imm32/no-r32
    32369     0/imm32/no-imm32
    32370     0/imm32/no-imm8
    32371     0/imm32/no-disp32
    32372     1/imm32/xm32-is-first-inout
    32373     3/imm32/x32-is-first-output
    32374     0x11/imm32/alloc-id:fake
    32375     _Primitive-max-xreg-with-mem/imm32/next
    32376 _Primitive-max-xreg-with-mem:  # (payload primitive)
    32377     0x11/imm32/alloc-id:fake:payload
    32378     # var1/xreg <- divide var2 => f3 0f 5f/max var2/xm32 var1/x32
    32379     0x11/imm32/alloc-id:fake
    32380     _string-max/imm32/name
    32381     0x11/imm32/alloc-id:fake
    32382     Single-float-var-in-mem/imm32/inouts
    32383     0x11/imm32/alloc-id:fake
    32384     Single-float-var-in-some-register/imm32/outputs
    32385     0x11/imm32/alloc-id:fake
    32386     _string_f3_0f_5f_max/imm32/subx-name
    32387     0/imm32/no-rm32
    32388     0/imm32/no-r32
    32389     0/imm32/no-imm32
    32390     0/imm32/no-imm8
    32391     0/imm32/no-disp32
    32392     1/imm32/xm32-is-first-inout
    32393     3/imm32/x32-is-first-output
    32394     0x11/imm32/alloc-id:fake
    32395     _Primitive-min-xreg-with-xreg/imm32/next
    32396 # - floating-point minimum
    32397 _Primitive-min-xreg-with-xreg:  # (payload primitive)
    32398     0x11/imm32/alloc-id:fake:payload
    32399     # var1/xreg <- divide var2 => f3 0f 5d/min var2/xm32 var1/x32
    32400     0x11/imm32/alloc-id:fake
    32401     _string-min/imm32/name
    32402     0x11/imm32/alloc-id:fake
    32403     Single-float-var-in-some-register/imm32/inouts
    32404     0x11/imm32/alloc-id:fake
    32405     Single-float-var-in-some-register/imm32/outputs
    32406     0x11/imm32/alloc-id:fake
    32407     _string_f3_0f_5d_min/imm32/subx-name
    32408     0/imm32/no-rm32
    32409     0/imm32/no-r32
    32410     0/imm32/no-imm32
    32411     0/imm32/no-imm8
    32412     0/imm32/no-disp32
    32413     1/imm32/xm32-is-first-inout
    32414     3/imm32/x32-is-first-output
    32415     0x11/imm32/alloc-id:fake
    32416     _Primitive-min-xreg-with-mem/imm32/next
    32417 _Primitive-min-xreg-with-mem:  # (payload primitive)
    32418     0x11/imm32/alloc-id:fake:payload
    32419     # var1/xreg <- divide var2 => f3 0f 5d/min var2/xm32 var1/x32
    32420     0x11/imm32/alloc-id:fake
    32421     _string-min/imm32/name
    32422     0x11/imm32/alloc-id:fake
    32423     Single-float-var-in-mem/imm32/inouts
    32424     0x11/imm32/alloc-id:fake
    32425     Single-float-var-in-some-register/imm32/outputs
    32426     0x11/imm32/alloc-id:fake
    32427     _string_f3_0f_5d_min/imm32/subx-name
    32428     0/imm32/no-rm32
    32429     0/imm32/no-r32
    32430     0/imm32/no-imm32
    32431     0/imm32/no-imm8
    32432     0/imm32/no-disp32
    32433     1/imm32/xm32-is-first-inout
    32434     3/imm32/x32-is-first-output
    32435     0x11/imm32/alloc-id:fake
    32436     _Primitive-reciprocal-xreg-to-xreg/imm32/next
    32437 # - floating-point reciprocal
    32438 _Primitive-reciprocal-xreg-to-xreg:  # (payload primitive)
    32439     0x11/imm32/alloc-id:fake:payload
    32440     # var1/xreg <- reciprocal var2 => f3 0f 53/reciprocal var2/xm32 var1/x32
    32441     0x11/imm32/alloc-id:fake
    32442     _string-reciprocal/imm32/name
    32443     0x11/imm32/alloc-id:fake
    32444     Single-float-var-in-some-register/imm32/inouts
    32445     0x11/imm32/alloc-id:fake
    32446     Single-float-var-in-some-register/imm32/outputs
    32447     0x11/imm32/alloc-id:fake
    32448     _string_f3_0f_53_reciprocal/imm32/subx-name
    32449     0/imm32/no-rm32
    32450     0/imm32/no-r32
    32451     0/imm32/no-imm32
    32452     0/imm32/no-imm8
    32453     0/imm32/no-disp32
    32454     1/imm32/xm32-is-first-inout
    32455     3/imm32/x32-is-first-output
    32456     0x11/imm32/alloc-id:fake
    32457     _Primitive-reciprocal-mem-to-xreg/imm32/next
    32458 _Primitive-reciprocal-mem-to-xreg:  # (payload primitive)
    32459     0x11/imm32/alloc-id:fake:payload
    32460     # var1/xreg <- divide var2 => f3 0f 53/reciprocal var2/xm32 var1/x32
    32461     0x11/imm32/alloc-id:fake
    32462     _string-reciprocal/imm32/name
    32463     0x11/imm32/alloc-id:fake
    32464     Single-float-var-in-mem/imm32/inouts
    32465     0x11/imm32/alloc-id:fake
    32466     Single-float-var-in-some-register/imm32/outputs
    32467     0x11/imm32/alloc-id:fake
    32468     _string_f3_0f_53_reciprocal/imm32/subx-name
    32469     0/imm32/no-rm32
    32470     0/imm32/no-r32
    32471     0/imm32/no-imm32
    32472     0/imm32/no-imm8
    32473     0/imm32/no-disp32
    32474     1/imm32/xm32-is-first-inout
    32475     3/imm32/x32-is-first-output
    32476     0x11/imm32/alloc-id:fake
    32477     _Primitive-square-root-xreg-to-xreg/imm32/next
    32478 # - floating-point square root
    32479 _Primitive-square-root-xreg-to-xreg:  # (payload primitive)
    32480     0x11/imm32/alloc-id:fake:payload
    32481     # var1/xreg <- square-root var2 => f3 0f 51/square-root var2/xm32 var1/x32
    32482     0x11/imm32/alloc-id:fake
    32483     _string-square-root/imm32/name
    32484     0x11/imm32/alloc-id:fake
    32485     Single-float-var-in-some-register/imm32/inouts
    32486     0x11/imm32/alloc-id:fake
    32487     Single-float-var-in-some-register/imm32/outputs
    32488     0x11/imm32/alloc-id:fake
    32489     _string_f3_0f_51_square_root/imm32/subx-name
    32490     0/imm32/no-rm32
    32491     0/imm32/no-r32
    32492     0/imm32/no-imm32
    32493     0/imm32/no-imm8
    32494     0/imm32/no-disp32
    32495     1/imm32/xm32-is-first-inout
    32496     3/imm32/x32-is-first-output
    32497     0x11/imm32/alloc-id:fake
    32498     _Primitive-square-root-mem-to-xreg/imm32/next
    32499 _Primitive-square-root-mem-to-xreg:  # (payload primitive)
    32500     0x11/imm32/alloc-id:fake:payload
    32501     # var1/xreg <- divide var2 => f3 0f 51/square-root var2/xm32 var1/x32
    32502     0x11/imm32/alloc-id:fake
    32503     _string-square-root/imm32/name
    32504     0x11/imm32/alloc-id:fake
    32505     Single-float-var-in-mem/imm32/inouts
    32506     0x11/imm32/alloc-id:fake
    32507     Single-float-var-in-some-register/imm32/outputs
    32508     0x11/imm32/alloc-id:fake
    32509     _string_f3_0f_51_square_root/imm32/subx-name
    32510     0/imm32/no-rm32
    32511     0/imm32/no-r32
    32512     0/imm32/no-imm32
    32513     0/imm32/no-imm8
    32514     0/imm32/no-disp32
    32515     1/imm32/xm32-is-first-inout
    32516     3/imm32/x32-is-first-output
    32517     0x11/imm32/alloc-id:fake
    32518     _Primitive-inverse-square-root-xreg-to-xreg/imm32/next
    32519 # - floating-point inverse square root 1/sqrt(x)
    32520 _Primitive-inverse-square-root-xreg-to-xreg:  # (payload primitive)
    32521     0x11/imm32/alloc-id:fake:payload
    32522     # var1/xreg <- reciprocal var2 => f3 0f 52/inverse-square-root var2/xm32 var1/x32
    32523     0x11/imm32/alloc-id:fake
    32524     _string-inverse-square-root/imm32/name
    32525     0x11/imm32/alloc-id:fake
    32526     Single-float-var-in-some-register/imm32/inouts
    32527     0x11/imm32/alloc-id:fake
    32528     Single-float-var-in-some-register/imm32/outputs
    32529     0x11/imm32/alloc-id:fake
    32530     _string_f3_0f_52_inverse_square_root/imm32/subx-name
    32531     0/imm32/no-rm32
    32532     0/imm32/no-r32
    32533     0/imm32/no-imm32
    32534     0/imm32/no-imm8
    32535     0/imm32/no-disp32
    32536     1/imm32/xm32-is-first-inout
    32537     3/imm32/x32-is-first-output
    32538     0x11/imm32/alloc-id:fake
    32539     _Primitive-inverse-square-root-mem-to-xreg/imm32/next
    32540 _Primitive-inverse-square-root-mem-to-xreg:  # (payload primitive)
    32541     0x11/imm32/alloc-id:fake:payload
    32542     # var1/xreg <- divide var2 => f3 0f 52/inverse-square-root var2/xm32 var1/x32
    32543     0x11/imm32/alloc-id:fake
    32544     _string-inverse-square-root/imm32/name
    32545     0x11/imm32/alloc-id:fake
    32546     Single-float-var-in-mem/imm32/inouts
    32547     0x11/imm32/alloc-id:fake
    32548     Single-float-var-in-some-register/imm32/outputs
    32549     0x11/imm32/alloc-id:fake
    32550     _string_f3_0f_52_inverse_square_root/imm32/subx-name
    32551     0/imm32/no-rm32
    32552     0/imm32/no-r32
    32553     0/imm32/no-imm32
    32554     0/imm32/no-imm8
    32555     0/imm32/no-disp32
    32556     1/imm32/xm32-is-first-inout
    32557     3/imm32/x32-is-first-output
    32558     0x11/imm32/alloc-id:fake
    32559     _Primitive-compare-xreg-with-xreg/imm32/next
    32560 # - floating-point compare
    32561 _Primitive-compare-xreg-with-xreg:  # (payload primitive)
    32562     0x11/imm32/alloc-id:fake:payload
    32563     # compare var1/reg1 var2/reg2 => 0f 2f/compare var2/x32 var1/xm32
    32564     0x11/imm32/alloc-id:fake
    32565     _string-compare/imm32/name
    32566     0x11/imm32/alloc-id:fake
    32567     Two-float-args-in-regs/imm32/inouts
    32568     0/imm32/no-outputs
    32569     0/imm32/no-outputs
    32570     0x11/imm32/alloc-id:fake
    32571     _string_0f_2f_compare/imm32/subx-name
    32572     0/imm32/no-rm32
    32573     0/imm32/no-r32
    32574     0/imm32/no-imm32
    32575     0/imm32/no-imm8
    32576     0/imm32/no-disp32
    32577     2/imm32/xm32-is-second-inout
    32578     1/imm32/x32-is-first-inout
    32579     0x11/imm32/alloc-id:fake
    32580     _Primitive-compare-xreg-with-mem/imm32/next
    32581 _Primitive-compare-xreg-with-mem:  # (payload primitive)
    32582     0x11/imm32/alloc-id:fake:payload
    32583     # compare var1/xreg var2 => 0f 2f/compare var1/x32 var2/xm32
    32584     0x11/imm32/alloc-id:fake
    32585     _string-compare/imm32/name
    32586     0x11/imm32/alloc-id:fake
    32587     Two-args-float-reg-float-stack/imm32/inouts
    32588     0/imm32/no-outputs
    32589     0/imm32/no-outputs
    32590     0x11/imm32/alloc-id:fake
    32591     _string_0f_2f_compare/imm32/subx-name
    32592     0/imm32/no-rm32
    32593     0/imm32/no-r32
    32594     0/imm32/no-imm32
    32595     0/imm32/no-imm8
    32596     0/imm32/no-disp32
    32597     2/imm32/xm32-is-second-inout
    32598     1/imm32/x32-is-first-inout
    32599     0x11/imm32/alloc-id:fake
    32600     _Primitive-break-if-addr</imm32/next
    32601 # - branches
    32602 _Primitive-break-if-addr<:  # (payload primitive)
    32603     0x11/imm32/alloc-id:fake:payload
    32604     0x11/imm32/alloc-id:fake
    32605     _string-break-if-addr</imm32/name
    32606     0/imm32/no-inouts
    32607     0/imm32/no-inouts
    32608     0/imm32/no-outputs
    32609     0/imm32/no-outputs
    32610     0x11/imm32/alloc-id:fake
    32611     _string_0f_82_jump_break/imm32/subx-name
    32612     0/imm32/no-rm32
    32613     0/imm32/no-r32
    32614     0/imm32/no-imm32
    32615     0/imm32/no-imm8
    32616     0/imm32/no-disp32
    32617     0/imm32/no-xm32
    32618     0/imm32/no-x32
    32619     0x11/imm32/alloc-id:fake
    32620     _Primitive-break-if-addr>=/imm32/next
    32621 _Primitive-break-if-addr>=:  # (payload primitive)
    32622     0x11/imm32/alloc-id:fake:payload
    32623     0x11/imm32/alloc-id:fake
    32624     _string-break-if-addr>=/imm32/name
    32625     0/imm32/no-inouts
    32626     0/imm32/no-inouts
    32627     0/imm32/no-outputs
    32628     0/imm32/no-outputs
    32629     0x11/imm32/alloc-id:fake
    32630     _string_0f_83_jump_break/imm32/subx-name
    32631     0/imm32/no-rm32
    32632     0/imm32/no-r32
    32633     0/imm32/no-imm32
    32634     0/imm32/no-imm8
    32635     0/imm32/no-disp32
    32636     0/imm32/no-xm32
    32637     0/imm32/no-x32
    32638     0x11/imm32/alloc-id:fake
    32639     _Primitive-break-if-=/imm32/next
    32640 _Primitive-break-if-=:  # (payload primitive)
    32641     0x11/imm32/alloc-id:fake:payload
    32642     0x11/imm32/alloc-id:fake
    32643     _string-break-if-=/imm32/name
    32644     0/imm32/no-inouts
    32645     0/imm32/no-inouts
    32646     0/imm32/no-outputs
    32647     0/imm32/no-outputs
    32648     0x11/imm32/alloc-id:fake
    32649     _string_0f_84_jump_break/imm32/subx-name
    32650     0/imm32/no-rm32
    32651     0/imm32/no-r32
    32652     0/imm32/no-imm32
    32653     0/imm32/no-imm8
    32654     0/imm32/no-disp32
    32655     0/imm32/no-xm32
    32656     0/imm32/no-x32
    32657     0x11/imm32/alloc-id:fake
    32658     _Primitive-break-if-!=/imm32/next
    32659 _Primitive-break-if-!=:  # (payload primitive)
    32660     0x11/imm32/alloc-id:fake:payload
    32661     0x11/imm32/alloc-id:fake
    32662     _string-break-if-!=/imm32/name
    32663     0/imm32/no-inouts
    32664     0/imm32/no-inouts
    32665     0/imm32/no-outputs
    32666     0/imm32/no-outputs
    32667     0x11/imm32/alloc-id:fake
    32668     _string_0f_85_jump_break/imm32/subx-name
    32669     0/imm32/no-rm32
    32670     0/imm32/no-r32
    32671     0/imm32/no-imm32
    32672     0/imm32/no-imm8
    32673     0/imm32/no-disp32
    32674     0/imm32/no-xm32
    32675     0/imm32/no-x32
    32676     0x11/imm32/alloc-id:fake
    32677     _Primitive-break-if-addr<=/imm32/next
    32678 _Primitive-break-if-addr<=:  # (payload primitive)
    32679     0x11/imm32/alloc-id:fake:payload
    32680     0x11/imm32/alloc-id:fake
    32681     _string-break-if-addr<=/imm32/name
    32682     0/imm32/no-inouts
    32683     0/imm32/no-inouts
    32684     0/imm32/no-outputs
    32685     0/imm32/no-outputs
    32686     0x11/imm32/alloc-id:fake
    32687     _string_0f_86_jump_break/imm32/subx-name
    32688     0/imm32/no-rm32
    32689     0/imm32/no-r32
    32690     0/imm32/no-imm32
    32691     0/imm32/no-imm8
    32692     0/imm32/no-disp32
    32693     0/imm32/no-xm32
    32694     0/imm32/no-x32
    32695     0x11/imm32/alloc-id:fake
    32696     _Primitive-break-if-addr>/imm32/next
    32697 _Primitive-break-if-addr>:  # (payload primitive)
    32698     0x11/imm32/alloc-id:fake:payload
    32699     0x11/imm32/alloc-id:fake
    32700     _string-break-if-addr>/imm32/name
    32701     0/imm32/no-inouts
    32702     0/imm32/no-inouts
    32703     0/imm32/no-outputs
    32704     0/imm32/no-outputs
    32705     0x11/imm32/alloc-id:fake
    32706     _string_0f_87_jump_break/imm32/subx-name
    32707     0/imm32/no-rm32
    32708     0/imm32/no-r32
    32709     0/imm32/no-imm32
    32710     0/imm32/no-imm8
    32711     0/imm32/no-disp32
    32712     0/imm32/no-xm32
    32713     0/imm32/no-x32
    32714     0x11/imm32/alloc-id:fake
    32715     _Primitive-break-if-</imm32/next
    32716 _Primitive-break-if-<:  # (payload primitive)
    32717     0x11/imm32/alloc-id:fake:payload
    32718     0x11/imm32/alloc-id:fake
    32719     _string-break-if-</imm32/name
    32720     0/imm32/no-inouts
    32721     0/imm32/no-inouts
    32722     0/imm32/no-outputs
    32723     0/imm32/no-outputs
    32724     0x11/imm32/alloc-id:fake
    32725     _string_0f_8c_jump_break/imm32/subx-name
    32726     0/imm32/no-rm32
    32727     0/imm32/no-r32
    32728     0/imm32/no-imm32
    32729     0/imm32/no-imm8
    32730     0/imm32/no-disp32
    32731     0/imm32/no-xm32
    32732     0/imm32/no-x32
    32733     0x11/imm32/alloc-id:fake
    32734     _Primitive-break-if->=/imm32/next
    32735 _Primitive-break-if->=:  # (payload primitive)
    32736     0x11/imm32/alloc-id:fake:payload
    32737     0x11/imm32/alloc-id:fake
    32738     _string-break-if->=/imm32/name
    32739     0/imm32/no-inouts
    32740     0/imm32/no-inouts
    32741     0/imm32/no-outputs
    32742     0/imm32/no-outputs
    32743     0x11/imm32/alloc-id:fake
    32744     _string_0f_8d_jump_break/imm32/subx-name
    32745     0/imm32/no-rm32
    32746     0/imm32/no-r32
    32747     0/imm32/no-imm32
    32748     0/imm32/no-imm8
    32749     0/imm32/no-disp32
    32750     0/imm32/no-xm32
    32751     0/imm32/no-x32
    32752     0x11/imm32/alloc-id:fake
    32753     _Primitive-break-if-<=/imm32/next
    32754 _Primitive-break-if-<=:  # (payload primitive)
    32755     0x11/imm32/alloc-id:fake:payload
    32756     0x11/imm32/alloc-id:fake
    32757     _string-break-if-<=/imm32/name
    32758     0/imm32/no-inouts
    32759     0/imm32/no-inouts
    32760     0/imm32/no-outputs
    32761     0/imm32/no-outputs
    32762     0x11/imm32/alloc-id:fake
    32763     _string_0f_8e_jump_break/imm32/subx-name
    32764     0/imm32/no-rm32
    32765     0/imm32/no-r32
    32766     0/imm32/no-imm32
    32767     0/imm32/no-imm8
    32768     0/imm32/no-disp32
    32769     0/imm32/no-xm32
    32770     0/imm32/no-x32
    32771     0x11/imm32/alloc-id:fake
    32772     _Primitive-break-if->/imm32/next
    32773 _Primitive-break-if->:  # (payload primitive)
    32774     0x11/imm32/alloc-id:fake:payload
    32775     0x11/imm32/alloc-id:fake
    32776     _string-break-if->/imm32/name
    32777     0/imm32/no-inouts
    32778     0/imm32/no-inouts
    32779     0/imm32/no-outputs
    32780     0/imm32/no-outputs
    32781     0x11/imm32/alloc-id:fake
    32782     _string_0f_8f_jump_break/imm32/subx-name
    32783     0/imm32/no-rm32
    32784     0/imm32/no-r32
    32785     0/imm32/no-imm32
    32786     0/imm32/no-imm8
    32787     0/imm32/no-disp32
    32788     0/imm32/no-xm32
    32789     0/imm32/no-x32
    32790     0x11/imm32/alloc-id:fake
    32791     _Primitive-break/imm32/next
    32792 _Primitive-break:  # (payload primitive)
    32793     0x11/imm32/alloc-id:fake:payload
    32794     0x11/imm32/alloc-id:fake
    32795     _string-break/imm32/name
    32796     0/imm32/no-inouts
    32797     0/imm32/no-inouts
    32798     0/imm32/no-outputs
    32799     0/imm32/no-outputs
    32800     0x11/imm32/alloc-id:fake
    32801     _string_e9_jump_break/imm32/subx-name
    32802     0/imm32/no-rm32
    32803     0/imm32/no-r32
    32804     0/imm32/no-imm32
    32805     0/imm32/no-imm8
    32806     0/imm32/no-disp32
    32807     0/imm32/no-xm32
    32808     0/imm32/no-x32
    32809     0x11/imm32/alloc-id:fake
    32810     _Primitive-loop-if-addr</imm32/next
    32811 _Primitive-loop-if-addr<:  # (payload primitive)
    32812     0x11/imm32/alloc-id:fake:payload
    32813     0x11/imm32/alloc-id:fake
    32814     _string-loop-if-addr</imm32/name
    32815     0/imm32/no-inouts
    32816     0/imm32/no-inouts
    32817     0/imm32/no-outputs
    32818     0/imm32/no-outputs
    32819     0x11/imm32/alloc-id:fake
    32820     _string_0f_82_jump_loop/imm32/subx-name
    32821     0/imm32/no-rm32
    32822     0/imm32/no-r32
    32823     0/imm32/no-imm32
    32824     0/imm32/no-imm8
    32825     0/imm32/no-disp32
    32826     0/imm32/no-xm32
    32827     0/imm32/no-x32
    32828     0x11/imm32/alloc-id:fake
    32829     _Primitive-loop-if-addr>=/imm32/next
    32830 _Primitive-loop-if-addr>=:  # (payload primitive)
    32831     0x11/imm32/alloc-id:fake:payload
    32832     0x11/imm32/alloc-id:fake
    32833     _string-loop-if-addr>=/imm32/name
    32834     0/imm32/no-inouts
    32835     0/imm32/no-inouts
    32836     0/imm32/no-outputs
    32837     0/imm32/no-outputs
    32838     0x11/imm32/alloc-id:fake
    32839     _string_0f_83_jump_loop/imm32/subx-name
    32840     0/imm32/no-rm32
    32841     0/imm32/no-r32
    32842     0/imm32/no-imm32
    32843     0/imm32/no-imm8
    32844     0/imm32/no-disp32
    32845     0/imm32/no-xm32
    32846     0/imm32/no-x32
    32847     0x11/imm32/alloc-id:fake
    32848     _Primitive-loop-if-=/imm32/next
    32849 _Primitive-loop-if-=:  # (payload primitive)
    32850     0x11/imm32/alloc-id:fake:payload
    32851     0x11/imm32/alloc-id:fake
    32852     _string-loop-if-=/imm32/name
    32853     0/imm32/no-inouts
    32854     0/imm32/no-inouts
    32855     0/imm32/no-outputs
    32856     0/imm32/no-outputs
    32857     0x11/imm32/alloc-id:fake
    32858     _string_0f_84_jump_loop/imm32/subx-name
    32859     0/imm32/no-rm32
    32860     0/imm32/no-r32
    32861     0/imm32/no-imm32
    32862     0/imm32/no-imm8
    32863     0/imm32/no-disp32
    32864     0/imm32/no-xm32
    32865     0/imm32/no-x32
    32866     0x11/imm32/alloc-id:fake
    32867     _Primitive-loop-if-!=/imm32/next
    32868 _Primitive-loop-if-!=:  # (payload primitive)
    32869     0x11/imm32/alloc-id:fake:payload
    32870     0x11/imm32/alloc-id:fake
    32871     _string-loop-if-!=/imm32/name
    32872     0/imm32/no-inouts
    32873     0/imm32/no-inouts
    32874     0/imm32/no-outputs
    32875     0/imm32/no-outputs
    32876     0x11/imm32/alloc-id:fake
    32877     _string_0f_85_jump_loop/imm32/subx-name
    32878     0/imm32/no-rm32
    32879     0/imm32/no-r32
    32880     0/imm32/no-imm32
    32881     0/imm32/no-imm8
    32882     0/imm32/no-disp32
    32883     0/imm32/no-xm32
    32884     0/imm32/no-x32
    32885     0x11/imm32/alloc-id:fake
    32886     _Primitive-loop-if-addr<=/imm32/next
    32887 _Primitive-loop-if-addr<=:  # (payload primitive)
    32888     0x11/imm32/alloc-id:fake:payload
    32889     0x11/imm32/alloc-id:fake
    32890     _string-loop-if-addr<=/imm32/name
    32891     0/imm32/no-inouts
    32892     0/imm32/no-inouts
    32893     0/imm32/no-outputs
    32894     0/imm32/no-outputs
    32895     0x11/imm32/alloc-id:fake
    32896     _string_0f_86_jump_loop/imm32/subx-name
    32897     0/imm32/no-rm32
    32898     0/imm32/no-r32
    32899     0/imm32/no-imm32
    32900     0/imm32/no-imm8
    32901     0/imm32/no-disp32
    32902     0/imm32/no-xm32
    32903     0/imm32/no-x32
    32904     0x11/imm32/alloc-id:fake
    32905     _Primitive-loop-if-addr>/imm32/next
    32906 _Primitive-loop-if-addr>:  # (payload primitive)
    32907     0x11/imm32/alloc-id:fake:payload
    32908     0x11/imm32/alloc-id:fake
    32909     _string-loop-if-addr>/imm32/name
    32910     0/imm32/no-inouts
    32911     0/imm32/no-inouts
    32912     0/imm32/no-outputs
    32913     0/imm32/no-outputs
    32914     0x11/imm32/alloc-id:fake
    32915     _string_0f_87_jump_loop/imm32/subx-name
    32916     0/imm32/no-rm32
    32917     0/imm32/no-r32
    32918     0/imm32/no-imm32
    32919     0/imm32/no-imm8
    32920     0/imm32/no-disp32
    32921     0/imm32/no-xm32
    32922     0/imm32/no-x32
    32923     0x11/imm32/alloc-id:fake
    32924     _Primitive-loop-if-</imm32/next
    32925 _Primitive-loop-if-<:  # (payload primitive)
    32926     0x11/imm32/alloc-id:fake:payload
    32927     0x11/imm32/alloc-id:fake
    32928     _string-loop-if-</imm32/name
    32929     0/imm32/no-inouts
    32930     0/imm32/no-inouts
    32931     0/imm32/no-outputs
    32932     0/imm32/no-outputs
    32933     0x11/imm32/alloc-id:fake
    32934     _string_0f_8c_jump_loop/imm32/subx-name
    32935     0/imm32/no-rm32
    32936     0/imm32/no-r32
    32937     0/imm32/no-imm32
    32938     0/imm32/no-imm8
    32939     0/imm32/no-disp32
    32940     0/imm32/no-xm32
    32941     0/imm32/no-x32
    32942     0x11/imm32/alloc-id:fake
    32943     _Primitive-loop-if->=/imm32/next
    32944 _Primitive-loop-if->=:  # (payload primitive)
    32945     0x11/imm32/alloc-id:fake:payload
    32946     0x11/imm32/alloc-id:fake
    32947     _string-loop-if->=/imm32/name
    32948     0/imm32/no-inouts
    32949     0/imm32/no-inouts
    32950     0/imm32/no-outputs
    32951     0/imm32/no-outputs
    32952     0x11/imm32/alloc-id:fake
    32953     _string_0f_8d_jump_loop/imm32/subx-name
    32954     0/imm32/no-rm32
    32955     0/imm32/no-r32
    32956     0/imm32/no-imm32
    32957     0/imm32/no-imm8
    32958     0/imm32/no-disp32
    32959     0/imm32/no-xm32
    32960     0/imm32/no-x32
    32961     0x11/imm32/alloc-id:fake
    32962     _Primitive-loop-if-<=/imm32/next
    32963 _Primitive-loop-if-<=:  # (payload primitive)
    32964     0x11/imm32/alloc-id:fake:payload
    32965     0x11/imm32/alloc-id:fake
    32966     _string-loop-if-<=/imm32/name
    32967     0/imm32/no-inouts
    32968     0/imm32/no-inouts
    32969     0/imm32/no-outputs
    32970     0/imm32/no-outputs
    32971     0x11/imm32/alloc-id:fake
    32972     _string_0f_8e_jump_loop/imm32/subx-name
    32973     0/imm32/no-rm32
    32974     0/imm32/no-r32
    32975     0/imm32/no-imm32
    32976     0/imm32/no-imm8
    32977     0/imm32/no-disp32
    32978     0/imm32/no-xm32
    32979     0/imm32/no-x32
    32980     0x11/imm32/alloc-id:fake
    32981     _Primitive-loop-if->/imm32/next
    32982 _Primitive-loop-if->:  # (payload primitive)
    32983     0x11/imm32/alloc-id:fake:payload
    32984     0x11/imm32/alloc-id:fake
    32985     _string-loop-if->/imm32/name
    32986     0/imm32/no-inouts
    32987     0/imm32/no-inouts
    32988     0/imm32/no-outputs
    32989     0/imm32/no-outputs
    32990     0x11/imm32/alloc-id:fake
    32991     _string_0f_8f_jump_loop/imm32/subx-name
    32992     0/imm32/no-rm32
    32993     0/imm32/no-r32
    32994     0/imm32/no-imm32
    32995     0/imm32/no-imm8
    32996     0/imm32/no-disp32
    32997     0/imm32/no-xm32
    32998     0/imm32/no-x32
    32999     0x11/imm32/alloc-id:fake
    33000     _Primitive-loop/imm32/next  # we probably don't need an unconditional break
    33001 _Primitive-loop:  # (payload primitive)
    33002     0x11/imm32/alloc-id:fake:payload
    33003     0x11/imm32/alloc-id:fake
    33004     _string-loop/imm32/name
    33005     0/imm32/no-inouts
    33006     0/imm32/no-inouts
    33007     0/imm32/no-outputs
    33008     0/imm32/no-outputs
    33009     0x11/imm32/alloc-id:fake
    33010     _string_e9_jump_loop/imm32/subx-name
    33011     0/imm32/no-rm32
    33012     0/imm32/no-r32
    33013     0/imm32/no-imm32
    33014     0/imm32/no-imm8
    33015     0/imm32/no-disp32
    33016     0/imm32/no-xm32
    33017     0/imm32/no-x32
    33018     0x11/imm32/alloc-id:fake
    33019     _Primitive-break-if-addr<-named/imm32/next
    33020 # - branches to named blocks
    33021 _Primitive-break-if-addr<-named:  # (payload primitive)
    33022     0x11/imm32/alloc-id:fake:payload
    33023     0x11/imm32/alloc-id:fake
    33024     _string-break-if-addr</imm32/name
    33025     0x11/imm32/alloc-id:fake
    33026     Single-lit-var/imm32/inouts
    33027     0/imm32/no-outputs
    33028     0/imm32/no-outputs
    33029     0x11/imm32/alloc-id:fake
    33030     _string_0f_82_jump_label/imm32/subx-name
    33031     0/imm32/no-rm32
    33032     0/imm32/no-r32
    33033     0/imm32/no-imm32
    33034     0/imm32/no-imm8
    33035     1/imm32/disp32-is-first-inout
    33036     0/imm32/no-xm32
    33037     0/imm32/no-x32
    33038     0x11/imm32/alloc-id:fake
    33039     _Primitive-break-if-addr>=-named/imm32/next
    33040 _Primitive-break-if-addr>=-named:  # (payload primitive)
    33041     0x11/imm32/alloc-id:fake:payload
    33042     0x11/imm32/alloc-id:fake
    33043     _string-break-if-addr>=/imm32/name
    33044     0x11/imm32/alloc-id:fake
    33045     Single-lit-var/imm32/inouts
    33046     0/imm32/no-outputs
    33047     0/imm32/no-outputs
    33048     0x11/imm32/alloc-id:fake
    33049     _string_0f_83_jump_label/imm32/subx-name
    33050     0/imm32/no-rm32
    33051     0/imm32/no-r32
    33052     0/imm32/no-imm32
    33053     0/imm32/no-imm8
    33054     1/imm32/disp32-is-first-inout
    33055     0/imm32/no-xm32
    33056     0/imm32/no-x32
    33057     0x11/imm32/alloc-id:fake
    33058     _Primitive-break-if-=-named/imm32/next
    33059 _Primitive-break-if-=-named:  # (payload primitive)
    33060     0x11/imm32/alloc-id:fake:payload
    33061     0x11/imm32/alloc-id:fake
    33062     _string-break-if-=/imm32/name
    33063     0x11/imm32/alloc-id:fake
    33064     Single-lit-var/imm32/inouts
    33065     0/imm32/no-outputs
    33066     0/imm32/no-outputs
    33067     0x11/imm32/alloc-id:fake
    33068     _string_0f_84_jump_label/imm32/subx-name
    33069     0/imm32/no-rm32
    33070     0/imm32/no-r32
    33071     0/imm32/no-imm32
    33072     0/imm32/no-imm8
    33073     1/imm32/disp32-is-first-inout
    33074     0/imm32/no-xm32
    33075     0/imm32/no-x32
    33076     0x11/imm32/alloc-id:fake
    33077     _Primitive-break-if-!=-named/imm32/next
    33078 _Primitive-break-if-!=-named:  # (payload primitive)
    33079     0x11/imm32/alloc-id:fake:payload
    33080     0x11/imm32/alloc-id:fake
    33081     _string-break-if-!=/imm32/name
    33082     0x11/imm32/alloc-id:fake
    33083     Single-lit-var/imm32/inouts
    33084     0/imm32/no-outputs
    33085     0/imm32/no-outputs
    33086     0x11/imm32/alloc-id:fake
    33087     _string_0f_85_jump_label/imm32/subx-name
    33088     0/imm32/no-rm32
    33089     0/imm32/no-r32
    33090     0/imm32/no-imm32
    33091     0/imm32/no-imm8
    33092     1/imm32/disp32-is-first-inout
    33093     0/imm32/no-xm32
    33094     0/imm32/no-x32
    33095     0x11/imm32/alloc-id:fake
    33096     _Primitive-break-if-addr<=-named/imm32/next
    33097 _Primitive-break-if-addr<=-named:  # (payload primitive)
    33098     0x11/imm32/alloc-id:fake:payload
    33099     0x11/imm32/alloc-id:fake
    33100     _string-break-if-addr<=/imm32/name
    33101     0x11/imm32/alloc-id:fake
    33102     Single-lit-var/imm32/inouts
    33103     0/imm32/no-outputs
    33104     0/imm32/no-outputs
    33105     0x11/imm32/alloc-id:fake
    33106     _string_0f_86_jump_label/imm32/subx-name
    33107     0/imm32/no-rm32
    33108     0/imm32/no-r32
    33109     0/imm32/no-imm32
    33110     0/imm32/no-imm8
    33111     1/imm32/disp32-is-first-inout
    33112     0/imm32/no-xm32
    33113     0/imm32/no-x32
    33114     0x11/imm32/alloc-id:fake
    33115     _Primitive-break-if-addr>-named/imm32/next
    33116 _Primitive-break-if-addr>-named:  # (payload primitive)
    33117     0x11/imm32/alloc-id:fake:payload
    33118     0x11/imm32/alloc-id:fake
    33119     _string-break-if-addr>/imm32/name
    33120     0x11/imm32/alloc-id:fake
    33121     Single-lit-var/imm32/inouts
    33122     0/imm32/no-outputs
    33123     0/imm32/no-outputs
    33124     0x11/imm32/alloc-id:fake
    33125     _string_0f_87_jump_label/imm32/subx-name
    33126     0/imm32/no-rm32
    33127     0/imm32/no-r32
    33128     0/imm32/no-imm32
    33129     0/imm32/no-imm8
    33130     1/imm32/disp32-is-first-inout
    33131     0/imm32/no-xm32
    33132     0/imm32/no-x32
    33133     0x11/imm32/alloc-id:fake
    33134     _Primitive-break-if-<-named/imm32/next
    33135 _Primitive-break-if-<-named:  # (payload primitive)
    33136     0x11/imm32/alloc-id:fake:payload
    33137     0x11/imm32/alloc-id:fake
    33138     _string-break-if-</imm32/name
    33139     0x11/imm32/alloc-id:fake
    33140     Single-lit-var/imm32/inouts
    33141     0/imm32/no-outputs
    33142     0/imm32/no-outputs
    33143     0x11/imm32/alloc-id:fake
    33144     _string_0f_8c_jump_label/imm32/subx-name
    33145     0/imm32/no-rm32
    33146     0/imm32/no-r32
    33147     0/imm32/no-imm32
    33148     0/imm32/no-imm8
    33149     1/imm32/disp32-is-first-inout
    33150     0/imm32/no-xm32
    33151     0/imm32/no-x32
    33152     0x11/imm32/alloc-id:fake
    33153     _Primitive-break-if->=-named/imm32/next
    33154 _Primitive-break-if->=-named:  # (payload primitive)
    33155     0x11/imm32/alloc-id:fake:payload
    33156     0x11/imm32/alloc-id:fake
    33157     _string-break-if->=/imm32/name
    33158     0x11/imm32/alloc-id:fake
    33159     Single-lit-var/imm32/inouts
    33160     0/imm32/no-outputs
    33161     0/imm32/no-outputs
    33162     0x11/imm32/alloc-id:fake
    33163     _string_0f_8d_jump_label/imm32/subx-name
    33164     0/imm32/no-rm32
    33165     0/imm32/no-r32
    33166     0/imm32/no-imm32
    33167     0/imm32/no-imm8
    33168     1/imm32/disp32-is-first-inout
    33169     0/imm32/no-xm32
    33170     0/imm32/no-x32
    33171     0x11/imm32/alloc-id:fake
    33172     _Primitive-break-if-<=-named/imm32/next
    33173 _Primitive-break-if-<=-named:  # (payload primitive)
    33174     0x11/imm32/alloc-id:fake:payload
    33175     0x11/imm32/alloc-id:fake
    33176     _string-break-if-<=/imm32/name
    33177     0x11/imm32/alloc-id:fake
    33178     Single-lit-var/imm32/inouts
    33179     0/imm32/no-outputs
    33180     0/imm32/no-outputs
    33181     0x11/imm32/alloc-id:fake
    33182     _string_0f_8e_jump_label/imm32/subx-name
    33183     0/imm32/no-rm32
    33184     0/imm32/no-r32
    33185     0/imm32/no-imm32
    33186     0/imm32/no-imm8
    33187     1/imm32/disp32-is-first-inout
    33188     0/imm32/no-xm32
    33189     0/imm32/no-x32
    33190     0x11/imm32/alloc-id:fake
    33191     _Primitive-break-if->-named/imm32/next
    33192 _Primitive-break-if->-named:  # (payload primitive)
    33193     0x11/imm32/alloc-id:fake:payload
    33194     0x11/imm32/alloc-id:fake
    33195     _string-break-if->/imm32/name
    33196     0x11/imm32/alloc-id:fake
    33197     Single-lit-var/imm32/inouts
    33198     0/imm32/no-outputs
    33199     0/imm32/no-outputs
    33200     0x11/imm32/alloc-id:fake
    33201     _string_0f_8f_jump_label/imm32/subx-name
    33202     0/imm32/no-rm32
    33203     0/imm32/no-r32
    33204     0/imm32/no-imm32
    33205     0/imm32/no-imm8
    33206     1/imm32/disp32-is-first-inout
    33207     0/imm32/no-xm32
    33208     0/imm32/no-x32
    33209     0x11/imm32/alloc-id:fake
    33210     _Primitive-break-named/imm32/next
    33211 _Primitive-break-named:  # (payload primitive)
    33212     0x11/imm32/alloc-id:fake:payload
    33213     0x11/imm32/alloc-id:fake
    33214     _string-break/imm32/name
    33215     0x11/imm32/alloc-id:fake
    33216     Single-lit-var/imm32/inouts
    33217     0/imm32/no-outputs
    33218     0/imm32/no-outputs
    33219     0x11/imm32/alloc-id:fake
    33220     _string_e9_jump_label/imm32/subx-name
    33221     0/imm32/no-rm32
    33222     0/imm32/no-r32
    33223     0/imm32/no-imm32
    33224     0/imm32/no-imm8
    33225     1/imm32/disp32-is-first-inout
    33226     0/imm32/no-xm32
    33227     0/imm32/no-x32
    33228     0x11/imm32/alloc-id:fake
    33229     _Primitive-loop-if-addr<-named/imm32/next
    33230 _Primitive-loop-if-addr<-named:  # (payload primitive)
    33231     0x11/imm32/alloc-id:fake:payload
    33232     0x11/imm32/alloc-id:fake
    33233     _string-loop-if-addr</imm32/name
    33234     0x11/imm32/alloc-id:fake
    33235     Single-lit-var/imm32/inouts
    33236     0/imm32/no-outputs
    33237     0/imm32/no-outputs
    33238     0x11/imm32/alloc-id:fake
    33239     _string_0f_82_jump_label/imm32/subx-name
    33240     0/imm32/no-rm32
    33241     0/imm32/no-r32
    33242     0/imm32/no-imm32
    33243     0/imm32/no-imm8
    33244     1/imm32/disp32-is-first-inout
    33245     0/imm32/no-xm32
    33246     0/imm32/no-x32
    33247     0x11/imm32/alloc-id:fake
    33248     _Primitive-loop-if-addr>=-named/imm32/next
    33249 _Primitive-loop-if-addr>=-named:  # (payload primitive)
    33250     0x11/imm32/alloc-id:fake:payload
    33251     0x11/imm32/alloc-id:fake
    33252     _string-loop-if-addr>=/imm32/name
    33253     0x11/imm32/alloc-id:fake
    33254     Single-lit-var/imm32/inouts
    33255     0/imm32/no-outputs
    33256     0/imm32/no-outputs
    33257     0x11/imm32/alloc-id:fake
    33258     _string_0f_83_jump_label/imm32/subx-name
    33259     0/imm32/no-rm32
    33260     0/imm32/no-r32
    33261     0/imm32/no-imm32
    33262     0/imm32/no-imm8
    33263     1/imm32/disp32-is-first-inout
    33264     0/imm32/no-xm32
    33265     0/imm32/no-x32
    33266     0x11/imm32/alloc-id:fake
    33267     _Primitive-loop-if-=-named/imm32/next
    33268 _Primitive-loop-if-=-named:  # (payload primitive)
    33269     0x11/imm32/alloc-id:fake:payload
    33270     0x11/imm32/alloc-id:fake
    33271     _string-loop-if-=/imm32/name
    33272     0x11/imm32/alloc-id:fake
    33273     Single-lit-var/imm32/inouts
    33274     0/imm32/no-outputs
    33275     0/imm32/no-outputs
    33276     0x11/imm32/alloc-id:fake
    33277     _string_0f_84_jump_label/imm32/subx-name
    33278     0/imm32/no-rm32
    33279     0/imm32/no-r32
    33280     0/imm32/no-imm32
    33281     0/imm32/no-imm8
    33282     1/imm32/disp32-is-first-inout
    33283     0/imm32/no-xm32
    33284     0/imm32/no-x32
    33285     0x11/imm32/alloc-id:fake
    33286     _Primitive-loop-if-!=-named/imm32/next
    33287 _Primitive-loop-if-!=-named:  # (payload primitive)
    33288     0x11/imm32/alloc-id:fake:payload
    33289     0x11/imm32/alloc-id:fake
    33290     _string-loop-if-!=/imm32/name
    33291     0x11/imm32/alloc-id:fake
    33292     Single-lit-var/imm32/inouts
    33293     0/imm32/no-outputs
    33294     0/imm32/no-outputs
    33295     0x11/imm32/alloc-id:fake
    33296     _string_0f_85_jump_label/imm32/subx-name
    33297     0/imm32/no-rm32
    33298     0/imm32/no-r32
    33299     0/imm32/no-imm32
    33300     0/imm32/no-imm8
    33301     1/imm32/disp32-is-first-inout
    33302     0/imm32/no-xm32
    33303     0/imm32/no-x32
    33304     0x11/imm32/alloc-id:fake
    33305     _Primitive-loop-if-addr<=-named/imm32/next
    33306 _Primitive-loop-if-addr<=-named:  # (payload primitive)
    33307     0x11/imm32/alloc-id:fake:payload
    33308     0x11/imm32/alloc-id:fake
    33309     _string-loop-if-addr<=/imm32/name
    33310     0x11/imm32/alloc-id:fake
    33311     Single-lit-var/imm32/inouts
    33312     0/imm32/no-outputs
    33313     0/imm32/no-outputs
    33314     0x11/imm32/alloc-id:fake
    33315     _string_0f_86_jump_label/imm32/subx-name
    33316     0/imm32/no-rm32
    33317     0/imm32/no-r32
    33318     0/imm32/no-imm32
    33319     0/imm32/no-imm8
    33320     1/imm32/disp32-is-first-inout
    33321     0/imm32/no-xm32
    33322     0/imm32/no-x32
    33323     0x11/imm32/alloc-id:fake
    33324     _Primitive-loop-if-addr>-named/imm32/next
    33325 _Primitive-loop-if-addr>-named:  # (payload primitive)
    33326     0x11/imm32/alloc-id:fake:payload
    33327     0x11/imm32/alloc-id:fake
    33328     _string-loop-if-addr>/imm32/name
    33329     0x11/imm32/alloc-id:fake
    33330     Single-lit-var/imm32/inouts
    33331     0/imm32/no-outputs
    33332     0/imm32/no-outputs
    33333     0x11/imm32/alloc-id:fake
    33334     _string_0f_87_jump_label/imm32/subx-name
    33335     0/imm32/no-rm32
    33336     0/imm32/no-r32
    33337     0/imm32/no-imm32
    33338     0/imm32/no-imm8
    33339     1/imm32/disp32-is-first-inout
    33340     0/imm32/no-xm32
    33341     0/imm32/no-x32
    33342     0x11/imm32/alloc-id:fake
    33343     _Primitive-loop-if-<-named/imm32/next
    33344 _Primitive-loop-if-<-named:  # (payload primitive)
    33345     0x11/imm32/alloc-id:fake:payload
    33346     0x11/imm32/alloc-id:fake
    33347     _string-loop-if-</imm32/name
    33348     0x11/imm32/alloc-id:fake
    33349     Single-lit-var/imm32/inouts
    33350     0/imm32/no-outputs
    33351     0/imm32/no-outputs
    33352     0x11/imm32/alloc-id:fake
    33353     _string_0f_8c_jump_label/imm32/subx-name
    33354     0/imm32/no-rm32
    33355     0/imm32/no-r32
    33356     0/imm32/no-imm32
    33357     0/imm32/no-imm8
    33358     1/imm32/disp32-is-first-inout
    33359     0/imm32/no-xm32
    33360     0/imm32/no-x32
    33361     0x11/imm32/alloc-id:fake
    33362     _Primitive-loop-if->=-named/imm32/next
    33363 _Primitive-loop-if->=-named:  # (payload primitive)
    33364     0x11/imm32/alloc-id:fake:payload
    33365     0x11/imm32/alloc-id:fake
    33366     _string-loop-if->=/imm32/name
    33367     0x11/imm32/alloc-id:fake
    33368     Single-lit-var/imm32/inouts
    33369     0/imm32/no-outputs
    33370     0/imm32/no-outputs
    33371     0x11/imm32/alloc-id:fake
    33372     _string_0f_8d_jump_label/imm32/subx-name
    33373     0/imm32/no-rm32
    33374     0/imm32/no-r32
    33375     0/imm32/no-imm32
    33376     0/imm32/no-imm8
    33377     1/imm32/disp32-is-first-inout
    33378     0/imm32/no-xm32
    33379     0/imm32/no-x32
    33380     0x11/imm32/alloc-id:fake
    33381     _Primitive-loop-if-<=-named/imm32/next
    33382 _Primitive-loop-if-<=-named:  # (payload primitive)
    33383     0x11/imm32/alloc-id:fake:payload
    33384     0x11/imm32/alloc-id:fake
    33385     _string-loop-if-<=/imm32/name
    33386     0x11/imm32/alloc-id:fake
    33387     Single-lit-var/imm32/inouts
    33388     0/imm32/no-outputs
    33389     0/imm32/no-outputs
    33390     0x11/imm32/alloc-id:fake
    33391     _string_0f_8e_jump_label/imm32/subx-name
    33392     0/imm32/no-rm32
    33393     0/imm32/no-r32
    33394     0/imm32/no-imm32
    33395     0/imm32/no-imm8
    33396     1/imm32/disp32-is-first-inout
    33397     0/imm32/no-xm32
    33398     0/imm32/no-x32
    33399     0x11/imm32/alloc-id:fake
    33400     _Primitive-loop-if->-named/imm32/next
    33401 _Primitive-loop-if->-named:  # (payload primitive)
    33402     0x11/imm32/alloc-id:fake:payload
    33403     0x11/imm32/alloc-id:fake
    33404     _string-loop-if->/imm32/name
    33405     0x11/imm32/alloc-id:fake
    33406     Single-lit-var/imm32/inouts
    33407     0/imm32/no-outputs
    33408     0/imm32/no-outputs
    33409     0x11/imm32/alloc-id:fake
    33410     _string_0f_8f_jump_label/imm32/subx-name
    33411     0/imm32/no-rm32
    33412     0/imm32/no-r32
    33413     0/imm32/no-imm32
    33414     0/imm32/no-imm8
    33415     1/imm32/disp32-is-first-inout
    33416     0/imm32/no-xm32
    33417     0/imm32/no-x32
    33418     0x11/imm32/alloc-id:fake
    33419     _Primitive-loop-named/imm32/next  # we probably don't need an unconditional break
    33420 _Primitive-loop-named:  # (payload primitive)
    33421     0x11/imm32/alloc-id:fake:payload
    33422     0x11/imm32/alloc-id:fake
    33423     _string-loop/imm32/name
    33424     0x11/imm32/alloc-id:fake
    33425     Single-lit-var/imm32/inouts
    33426     0/imm32/no-outputs
    33427     0/imm32/no-outputs
    33428     0x11/imm32/alloc-id:fake
    33429     _string_e9_jump_label/imm32/subx-name
    33430     0/imm32/no-rm32
    33431     0/imm32/no-r32
    33432     0/imm32/no-imm32
    33433     0/imm32/no-imm8
    33434     1/imm32/disp32-is-first-inout
    33435     0/imm32/no-xm32
    33436     0/imm32/no-x32
    33437     0x11/imm32/alloc-id:fake
    33438     _Primitive-break-if-float</imm32/next
    33439 # - branches based on floating-point comparisons
    33440 _Primitive-break-if-float<:  # (payload primitive)
    33441     0x11/imm32/alloc-id:fake:payload
    33442     0x11/imm32/alloc-id:fake
    33443     _string-break-if-float</imm32/name
    33444     0/imm32/no-inouts
    33445     0/imm32/no-inouts
    33446     0/imm32/no-outputs
    33447     0/imm32/no-outputs
    33448     0x11/imm32/alloc-id:fake
    33449     _string_0f_82_jump_break/imm32/subx-name
    33450     0/imm32/no-rm32
    33451     0/imm32/no-r32
    33452     0/imm32/no-imm32
    33453     0/imm32/no-imm8
    33454     0/imm32/no-disp32
    33455     0/imm32/no-xm32
    33456     0/imm32/no-x32
    33457     0x11/imm32/alloc-id:fake
    33458     _Primitive-break-if-float>=/imm32/next
    33459 _Primitive-break-if-float>=:  # (payload primitive)
    33460     0x11/imm32/alloc-id:fake:payload
    33461     0x11/imm32/alloc-id:fake
    33462     _string-break-if-float>=/imm32/name
    33463     0/imm32/no-inouts
    33464     0/imm32/no-inouts
    33465     0/imm32/no-outputs
    33466     0/imm32/no-outputs
    33467     0x11/imm32/alloc-id:fake
    33468     _string_0f_83_jump_break/imm32/subx-name
    33469     0/imm32/no-rm32
    33470     0/imm32/no-r32
    33471     0/imm32/no-imm32
    33472     0/imm32/no-imm8
    33473     0/imm32/no-disp32
    33474     0/imm32/no-xm32
    33475     0/imm32/no-x32
    33476     0x11/imm32/alloc-id:fake
    33477     _Primitive-break-if-float<=/imm32/next
    33478 _Primitive-break-if-float<=:  # (payload primitive)
    33479     0x11/imm32/alloc-id:fake:payload
    33480     0x11/imm32/alloc-id:fake
    33481     _string-break-if-float<=/imm32/name
    33482     0/imm32/no-inouts
    33483     0/imm32/no-inouts
    33484     0/imm32/no-outputs
    33485     0/imm32/no-outputs
    33486     0x11/imm32/alloc-id:fake
    33487     _string_0f_86_jump_break/imm32/subx-name
    33488     0/imm32/no-rm32
    33489     0/imm32/no-r32
    33490     0/imm32/no-imm32
    33491     0/imm32/no-imm8
    33492     0/imm32/no-disp32
    33493     0/imm32/no-xm32
    33494     0/imm32/no-x32
    33495     0x11/imm32/alloc-id:fake
    33496     _Primitive-break-if-float>/imm32/next
    33497 _Primitive-break-if-float>:  # (payload primitive)
    33498     0x11/imm32/alloc-id:fake:payload
    33499     0x11/imm32/alloc-id:fake
    33500     _string-break-if-float>/imm32/name
    33501     0/imm32/no-inouts
    33502     0/imm32/no-inouts
    33503     0/imm32/no-outputs
    33504     0/imm32/no-outputs
    33505     0x11/imm32/alloc-id:fake
    33506     _string_0f_87_jump_break/imm32/subx-name
    33507     0/imm32/no-rm32
    33508     0/imm32/no-r32
    33509     0/imm32/no-imm32
    33510     0/imm32/no-imm8
    33511     0/imm32/no-disp32
    33512     0/imm32/no-xm32
    33513     0/imm32/no-x32
    33514     0x11/imm32/alloc-id:fake
    33515     _Primitive-loop-if-float</imm32/next
    33516 _Primitive-loop-if-float<:  # (payload primitive)
    33517     0x11/imm32/alloc-id:fake:payload
    33518     0x11/imm32/alloc-id:fake
    33519     _string-loop-if-float</imm32/name
    33520     0/imm32/no-inouts
    33521     0/imm32/no-inouts
    33522     0/imm32/no-outputs
    33523     0/imm32/no-outputs
    33524     0x11/imm32/alloc-id:fake
    33525     _string_0f_82_jump_loop/imm32/subx-name
    33526     0/imm32/no-rm32
    33527     0/imm32/no-r32
    33528     0/imm32/no-imm32
    33529     0/imm32/no-imm8
    33530     0/imm32/no-disp32
    33531     0/imm32/no-xm32
    33532     0/imm32/no-x32
    33533     0x11/imm32/alloc-id:fake
    33534     _Primitive-loop-if-float>=/imm32/next
    33535 _Primitive-loop-if-float>=:  # (payload primitive)
    33536     0x11/imm32/alloc-id:fake:payload
    33537     0x11/imm32/alloc-id:fake
    33538     _string-loop-if-float>=/imm32/name
    33539     0/imm32/no-inouts
    33540     0/imm32/no-inouts
    33541     0/imm32/no-outputs
    33542     0/imm32/no-outputs
    33543     0x11/imm32/alloc-id:fake
    33544     _string_0f_83_jump_loop/imm32/subx-name
    33545     0/imm32/no-rm32
    33546     0/imm32/no-r32
    33547     0/imm32/no-imm32
    33548     0/imm32/no-imm8
    33549     0/imm32/no-disp32
    33550     0/imm32/no-xm32
    33551     0/imm32/no-x32
    33552     0x11/imm32/alloc-id:fake
    33553     _Primitive-loop-if-float<=/imm32/next
    33554 _Primitive-loop-if-float<=:  # (payload primitive)
    33555     0x11/imm32/alloc-id:fake:payload
    33556     0x11/imm32/alloc-id:fake
    33557     _string-loop-if-float<=/imm32/name
    33558     0/imm32/no-inouts
    33559     0/imm32/no-inouts
    33560     0/imm32/no-outputs
    33561     0/imm32/no-outputs
    33562     0x11/imm32/alloc-id:fake
    33563     _string_0f_86_jump_loop/imm32/subx-name
    33564     0/imm32/no-rm32
    33565     0/imm32/no-r32
    33566     0/imm32/no-imm32
    33567     0/imm32/no-imm8
    33568     0/imm32/no-disp32
    33569     0/imm32/no-xm32
    33570     0/imm32/no-x32
    33571     0x11/imm32/alloc-id:fake
    33572     _Primitive-loop-if-float>/imm32/next
    33573 _Primitive-loop-if-float>:  # (payload primitive)
    33574     0x11/imm32/alloc-id:fake:payload
    33575     0x11/imm32/alloc-id:fake
    33576     _string-loop-if-float>/imm32/name
    33577     0/imm32/no-inouts
    33578     0/imm32/no-inouts
    33579     0/imm32/no-outputs
    33580     0/imm32/no-outputs
    33581     0x11/imm32/alloc-id:fake
    33582     _string_0f_87_jump_loop/imm32/subx-name
    33583     0/imm32/no-rm32
    33584     0/imm32/no-r32
    33585     0/imm32/no-imm32
    33586     0/imm32/no-imm8
    33587     0/imm32/no-disp32
    33588     0/imm32/no-xm32
    33589     0/imm32/no-x32
    33590     0x11/imm32/alloc-id:fake
    33591     _Primitive-break-if-float<-named/imm32/next
    33592 _Primitive-break-if-float<-named:  # (payload primitive)
    33593     0x11/imm32/alloc-id:fake:payload
    33594     0x11/imm32/alloc-id:fake
    33595     _string-break-if-float</imm32/name
    33596     0x11/imm32/alloc-id:fake
    33597     Single-lit-var/imm32/inouts
    33598     0/imm32/no-outputs
    33599     0/imm32/no-outputs
    33600     0x11/imm32/alloc-id:fake
    33601     _string_0f_82_jump_label/imm32/subx-name
    33602     0/imm32/no-rm32
    33603     0/imm32/no-r32
    33604     0/imm32/no-imm32
    33605     0/imm32/no-imm8
    33606     1/imm32/disp32-is-first-inout
    33607     0/imm32/no-xm32
    33608     0/imm32/no-x32
    33609     0x11/imm32/alloc-id:fake
    33610     _Primitive-break-if-float>=-named/imm32/next
    33611 _Primitive-break-if-float>=-named:  # (payload primitive)
    33612     0x11/imm32/alloc-id:fake:payload
    33613     0x11/imm32/alloc-id:fake
    33614     _string-break-if-float>=/imm32/name
    33615     0x11/imm32/alloc-id:fake
    33616     Single-lit-var/imm32/inouts
    33617     0/imm32/no-outputs
    33618     0/imm32/no-outputs
    33619     0x11/imm32/alloc-id:fake
    33620     _string_0f_83_jump_label/imm32/subx-name
    33621     0/imm32/no-rm32
    33622     0/imm32/no-r32
    33623     0/imm32/no-imm32
    33624     0/imm32/no-imm8
    33625     1/imm32/disp32-is-first-inout
    33626     0/imm32/no-xm32
    33627     0/imm32/no-x32
    33628     0x11/imm32/alloc-id:fake
    33629     _Primitive-break-if-float<=-named/imm32/next
    33630 _Primitive-break-if-float<=-named:  # (payload primitive)
    33631     0x11/imm32/alloc-id:fake:payload
    33632     0x11/imm32/alloc-id:fake
    33633     _string-break-if-float<=/imm32/name
    33634     0x11/imm32/alloc-id:fake
    33635     Single-lit-var/imm32/inouts
    33636     0/imm32/no-outputs
    33637     0/imm32/no-outputs
    33638     0x11/imm32/alloc-id:fake
    33639     _string_0f_86_jump_label/imm32/subx-name
    33640     0/imm32/no-rm32
    33641     0/imm32/no-r32
    33642     0/imm32/no-imm32
    33643     0/imm32/no-imm8
    33644     1/imm32/disp32-is-first-inout
    33645     0/imm32/no-xm32
    33646     0/imm32/no-x32
    33647     0x11/imm32/alloc-id:fake
    33648     _Primitive-break-if-float>-named/imm32/next
    33649 _Primitive-break-if-float>-named:  # (payload primitive)
    33650     0x11/imm32/alloc-id:fake:payload
    33651     0x11/imm32/alloc-id:fake
    33652     _string-break-if-float>/imm32/name
    33653     0x11/imm32/alloc-id:fake
    33654     Single-lit-var/imm32/inouts
    33655     0/imm32/no-outputs
    33656     0/imm32/no-outputs
    33657     0x11/imm32/alloc-id:fake
    33658     _string_0f_87_jump_label/imm32/subx-name
    33659     0/imm32/no-rm32
    33660     0/imm32/no-r32
    33661     0/imm32/no-imm32
    33662     0/imm32/no-imm8
    33663     1/imm32/disp32-is-first-inout
    33664     0/imm32/no-xm32
    33665     0/imm32/no-x32
    33666     0x11/imm32/alloc-id:fake
    33667     _Primitive-loop-if-float<-named/imm32/next
    33668 _Primitive-loop-if-float<-named:  # (payload primitive)
    33669     0x11/imm32/alloc-id:fake:payload
    33670     0x11/imm32/alloc-id:fake
    33671     _string-loop-if-float</imm32/name
    33672     0x11/imm32/alloc-id:fake
    33673     Single-lit-var/imm32/inouts
    33674     0/imm32/no-outputs
    33675     0/imm32/no-outputs
    33676     0x11/imm32/alloc-id:fake
    33677     _string_0f_82_jump_label/imm32/subx-name
    33678     0/imm32/no-rm32
    33679     0/imm32/no-r32
    33680     0/imm32/no-imm32
    33681     0/imm32/no-imm8
    33682     1/imm32/disp32-is-first-inout
    33683     0/imm32/no-xm32
    33684     0/imm32/no-x32
    33685     0x11/imm32/alloc-id:fake
    33686     _Primitive-loop-if-float>=-named/imm32/next
    33687 _Primitive-loop-if-float>=-named:  # (payload primitive)
    33688     0x11/imm32/alloc-id:fake:payload
    33689     0x11/imm32/alloc-id:fake
    33690     _string-loop-if-float>=/imm32/name
    33691     0x11/imm32/alloc-id:fake
    33692     Single-lit-var/imm32/inouts
    33693     0/imm32/no-outputs
    33694     0/imm32/no-outputs
    33695     0x11/imm32/alloc-id:fake
    33696     _string_0f_83_jump_label/imm32/subx-name
    33697     0/imm32/no-rm32
    33698     0/imm32/no-r32
    33699     0/imm32/no-imm32
    33700     0/imm32/no-imm8
    33701     1/imm32/disp32-is-first-inout
    33702     0/imm32/no-xm32
    33703     0/imm32/no-x32
    33704     0x11/imm32/alloc-id:fake
    33705     _Primitive-loop-if-float<=-named/imm32/next
    33706 _Primitive-loop-if-float<=-named:  # (payload primitive)
    33707     0x11/imm32/alloc-id:fake:payload
    33708     0x11/imm32/alloc-id:fake
    33709     _string-loop-if-float<=/imm32/name
    33710     0x11/imm32/alloc-id:fake
    33711     Single-lit-var/imm32/inouts
    33712     0/imm32/no-outputs
    33713     0/imm32/no-outputs
    33714     0x11/imm32/alloc-id:fake
    33715     _string_0f_86_jump_label/imm32/subx-name
    33716     0/imm32/no-rm32
    33717     0/imm32/no-r32
    33718     0/imm32/no-imm32
    33719     0/imm32/no-imm8
    33720     1/imm32/disp32-is-first-inout
    33721     0/imm32/no-xm32
    33722     0/imm32/no-x32
    33723     0x11/imm32/alloc-id:fake
    33724     _Primitive-loop-if-float>-named/imm32/next
    33725 _Primitive-loop-if-float>-named:  # (payload primitive)
    33726     0x11/imm32/alloc-id:fake:payload
    33727     0x11/imm32/alloc-id:fake
    33728     _string-loop-if-float>/imm32/name
    33729     0x11/imm32/alloc-id:fake
    33730     Single-lit-var/imm32/inouts
    33731     0/imm32/no-outputs
    33732     0/imm32/no-outputs
    33733     0x11/imm32/alloc-id:fake
    33734     _string_0f_87_jump_label/imm32/subx-name
    33735     0/imm32/no-rm32
    33736     0/imm32/no-r32
    33737     0/imm32/no-imm32
    33738     0/imm32/no-imm8
    33739     1/imm32/disp32-is-first-inout
    33740     0/imm32/no-xm32
    33741     0/imm32/no-x32
    33742     0/imm32/next
    33743     0/imm32/next
    33744
    33745 # string literals for Mu instructions
    33746 _string-add:  # (payload array byte)
    33747     0x11/imm32/alloc-id:fake:payload
    33748     # "add"
    33749     0x3/imm32/size
    33750     0x61/a 0x64/d 0x64/d
    33751 _string-address:  # (payload array byte)
    33752     0x11/imm32/alloc-id:fake:payload
    33753     # "address"
    33754     0x7/imm32/size
    33755     0x61/a 0x64/d 0x64/d 0x72/r 0x65/e 0x73/s 0x73/s
    33756 _string-add-to:  # (payload array byte)
    33757     0x11/imm32/alloc-id:fake:payload
    33758     # "add-to"
    33759     0x6/imm32/size
    33760     0x61/a 0x64/d 0x64/d 0x2d/dash 0x74/t 0x6f/o
    33761 _string-and:  # (payload array byte)
    33762     0x11/imm32/alloc-id:fake:payload
    33763     # "and"
    33764     0x3/imm32/size
    33765     0x61/a 0x6e/n 0x64/d
    33766 _string-and-with:  # (payload array byte)
    33767     0x11/imm32/alloc-id:fake:payload
    33768     # "and-with"
    33769     0x8/imm32/size
    33770     0x61/a 0x6e/n 0x64/d 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h
    33771 _string-break:  # (payload array byte)
    33772     0x11/imm32/alloc-id:fake:payload
    33773     # "break"
    33774     0x5/imm32/size
    33775     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k
    33776 _string-break-if-<:  # (payload array byte)
    33777     0x11/imm32/alloc-id:fake:payload
    33778     # "break-if-<"
    33779     0xa/imm32/size
    33780     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3c/<
    33781 _string-break-if-<=:  # (payload array byte)
    33782     0x11/imm32/alloc-id:fake:payload
    33783     # "break-if-<="
    33784     0xb/imm32/size
    33785     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3c/< 0x3d/=
    33786 _string-break-if-=:  # (payload array byte)
    33787     0x11/imm32/alloc-id:fake:payload
    33788     # "break-if-="
    33789     0xa/imm32/size
    33790     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3d/=
    33791 _string-break-if->:  # (payload array byte)
    33792     0x11/imm32/alloc-id:fake:payload
    33793     # "break-if->"
    33794     0xa/imm32/size
    33795     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3e/>
    33796 _string-break-if->=:  # (payload array byte)
    33797     0x11/imm32/alloc-id:fake:payload
    33798     # "break-if->="
    33799     0xb/imm32/size
    33800     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3e/> 0x3d/=
    33801 _string-break-if-!=:  # (payload array byte)
    33802     0x11/imm32/alloc-id:fake:payload
    33803     # "break-if-!="
    33804     0xb/imm32/size
    33805     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x21/! 0x3d/=
    33806 _string-break-if-addr<:  # (payload array byte)
    33807     0x11/imm32/alloc-id:fake:payload
    33808     # "break-if-addr<"
    33809     0xe/imm32/size
    33810     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x61/a 0x64/d 0x64/d 0x72/r 0x3c/<
    33811 _string-break-if-addr<=:  # (payload array byte)
    33812     0x11/imm32/alloc-id:fake:payload
    33813     # "break-if-addr<="
    33814     0xf/imm32/size
    33815     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x61/a 0x64/d 0x64/d 0x72/r 0x3c/< 0x3d/=
    33816 _string-break-if-addr>:  # (payload array byte)
    33817     0x11/imm32/alloc-id:fake:payload
    33818     # "break-if-addr>"
    33819     0xe/imm32/size
    33820     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x61/a 0x64/d 0x64/d 0x72/r 0x3e/>
    33821 _string-break-if-addr>=:  # (payload array byte)
    33822     0x11/imm32/alloc-id:fake:payload
    33823     # "break-if-addr>="
    33824     0xf/imm32/size
    33825     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x61/a 0x64/d 0x64/d 0x72/r 0x3e/> 0x3d/=
    33826 _string-break-if-float<:  # (payload array byte)
    33827     0x11/imm32/alloc-id:fake:payload
    33828     # "break-if-float<"
    33829     0xf/imm32/size
    33830     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x66/f 0x6c/l 0x6f/o 0x61/a 0x74/t 0x3c/<
    33831 _string-break-if-float<=:  # (payload array byte)
    33832     0x11/imm32/alloc-id:fake:payload
    33833     # "break-if-float<="
    33834     0x10/imm32/size
    33835     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x66/f 0x6c/l 0x6f/o 0x61/a 0x74/t 0x3c/< 0x3d/=
    33836 _string-break-if-float>:  # (payload array byte)
    33837     0x11/imm32/alloc-id:fake:payload
    33838     # "break-if-float>"
    33839     0xf/imm32/size
    33840     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x66/f 0x6c/l 0x6f/o 0x61/a 0x74/t 0x3e/>
    33841 _string-break-if-float>=:  # (payload array byte)
    33842     0x11/imm32/alloc-id:fake:payload
    33843     # "break-if-float>="
    33844     0x10/imm32/size
    33845     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x66/f 0x6c/l 0x6f/o 0x61/a 0x74/t 0x3e/> 0x3d/=
    33846 _string-compare:  # (payload array byte)
    33847     0x11/imm32/alloc-id:fake:payload
    33848     # "compare"
    33849     0x7/imm32/size
    33850     0x63/c 0x6f/o 0x6d/m 0x70/p 0x61/a 0x72/r 0x65/e
    33851 _string-copy:  # (payload array byte)
    33852     0x11/imm32/alloc-id:fake:payload
    33853     # "copy"
    33854     0x4/imm32/size
    33855     0x63/c 0x6f/o 0x70/p 0x79/y
    33856 _string-copy-to:  # (payload array byte)
    33857     0x11/imm32/alloc-id:fake:payload
    33858     # "copy-to"
    33859     0x7/imm32/size
    33860     0x63/c 0x6f/o 0x70/p 0x79/y 0x2d/dash 0x74/t 0x6f/o
    33861 _string-copy-byte:
    33862     0x11/imm32/alloc-id:fake:payload
    33863     # "copy-byte"
    33864     0x9/imm32/size
    33865     0x63/c 0x6f/o 0x70/p 0x79/y 0x2d/- 0x62/b 0x79/y 0x74/t 0x65/e
    33866 _string-copy-byte-to:
    33867     0x11/imm32/alloc-id:fake:payload
    33868     # "copy-byte-to"
    33869     0xc/imm32/size
    33870     0x63/c 0x6f/o 0x70/p 0x79/y 0x2d/- 0x62/b 0x79/y 0x74/t 0x65/e 0x2d/- 0x74/t 0x6f/o
    33871 _string-decrement:  # (payload array byte)
    33872     0x11/imm32/alloc-id:fake:payload
    33873     # "decrement"
    33874     0x9/imm32/size
    33875     0x64/d 0x65/e 0x63/c 0x72/r 0x65/e 0x6d/m 0x65/e 0x6e/n 0x74/t
    33876 _string-increment:  # (payload array byte)
    33877     0x11/imm32/alloc-id:fake:payload
    33878     # "increment"
    33879     0x9/imm32/size
    33880     0x69/i 0x6e/n 0x63/c 0x72/r 0x65/e 0x6d/m 0x65/e 0x6e/n 0x74/t
    33881 _string-loop:  # (payload array byte)
    33882     0x11/imm32/alloc-id:fake:payload
    33883     # "loop"
    33884     0x4/imm32/size
    33885     0x6c/l 0x6f/o 0x6f/o 0x70/p
    33886 _string-loop-if-<:  # (payload array byte)
    33887     0x11/imm32/alloc-id:fake:payload
    33888     # "loop-if-<"
    33889     0x9/imm32/size
    33890     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3c/<
    33891 _string-loop-if-<=:  # (payload array byte)
    33892     0x11/imm32/alloc-id:fake:payload
    33893     # "loop-if-<="
    33894     0xa/imm32/size
    33895     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3c/< 0x3d/=
    33896 _string-loop-if-=:  # (payload array byte)
    33897     0x11/imm32/alloc-id:fake:payload
    33898     # "loop-if-="
    33899     0x9/imm32/size
    33900     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3d/=
    33901 _string-loop-if->:  # (payload array byte)
    33902     0x11/imm32/alloc-id:fake:payload
    33903     # "loop-if->"
    33904     0x9/imm32/size
    33905     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3e/>
    33906 _string-loop-if->=:  # (payload array byte)
    33907     0x11/imm32/alloc-id:fake:payload
    33908     # "loop-if->="
    33909     0xa/imm32/size
    33910     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3e/> 0x3d/=
    33911 _string-loop-if-!=:  # (payload array byte)
    33912     0x11/imm32/alloc-id:fake:payload
    33913     # "loop-if-!="
    33914     0xa/imm32/size
    33915     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x21/! 0x3d/=
    33916 _string-loop-if-addr<:  # (payload array byte)
    33917     0x11/imm32/alloc-id:fake:payload
    33918     # "loop-if-addr<"
    33919     0xd/imm32/size
    33920     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x61/a 0x64/d 0x64/d 0x72/r 0x3c/<
    33921 _string-loop-if-addr<=:  # (payload array byte)
    33922     0x11/imm32/alloc-id:fake:payload
    33923     # "loop-if-addr<="
    33924     0xe/imm32/size
    33925     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x61/a 0x64/d 0x64/d 0x72/r 0x3c/< 0x3d/=
    33926 _string-loop-if-addr>:  # (payload array byte)
    33927     0x11/imm32/alloc-id:fake:payload
    33928     # "loop-if-addr>"
    33929     0xd/imm32/size
    33930     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x61/a 0x64/d 0x64/d 0x72/r 0x3e/>
    33931 _string-loop-if-addr>=:  # (payload array byte)
    33932     0x11/imm32/alloc-id:fake:payload
    33933     # "loop-if-addr>="
    33934     0xe/imm32/size
    33935     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x61/a 0x64/d 0x64/d 0x72/r 0x3e/> 0x3d/=
    33936 _string-loop-if-float<:  # (payload array byte)
    33937     0x11/imm32/alloc-id:fake:payload
    33938     # "loop-if-float<"
    33939     0xe/imm32/size
    33940     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x66/f 0x6c/l 0x6f/o 0x61/a 0x74/t 0x3c/<
    33941 _string-loop-if-float<=:  # (payload array byte)
    33942     0x11/imm32/alloc-id:fake:payload
    33943     # "loop-if-float<="
    33944     0xf/imm32/size
    33945     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x66/f 0x6c/l 0x6f/o 0x61/a 0x74/t 0x3c/< 0x3d/=
    33946 _string-loop-if-float>:  # (payload array byte)
    33947     0x11/imm32/alloc-id:fake:payload
    33948     # "loop-if-float>"
    33949     0xe/imm32/size
    33950     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x66/f 0x6c/l 0x6f/o 0x61/a 0x74/t 0x3e/>
    33951 _string-loop-if-float>=:  # (payload array byte)
    33952     0x11/imm32/alloc-id:fake:payload
    33953     # "loop-if-float>="
    33954     0xf/imm32/size
    33955     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x66/f 0x6c/l 0x6f/o 0x61/a 0x74/t 0x3e/> 0x3d/=
    33956 _string-multiply:  # (payload array byte)
    33957     0x11/imm32/alloc-id:fake:payload
    33958     # "multiply"
    33959     0x8/imm32/size
    33960     0x6d/m 0x75/u 0x6c/l 0x74/t 0x69/i 0x70/p 0x6c/l 0x79/y
    33961 _string-convert:  # (payload array byte)
    33962     0x11/imm32/alloc-id:fake:payload
    33963     # "convert"
    33964     0x7/imm32/size
    33965     0x63/c 0x6f/o 0x6e/n 0x76/v 0x65/e 0x72/r 0x74/t
    33966 _string-truncate:  # (payload array byte)
    33967     0x11/imm32/alloc-id:fake:payload
    33968     # "truncate"
    33969     0x8/imm32/size
    33970     0x74/t 0x72/r 0x75/u 0x6e/n 0x63/c 0x61/a 0x74/t 0x65/e
    33971 _string-reinterpret:  # (payload array byte)
    33972     0x11/imm32/alloc-id:fake:payload
    33973     # "reinterpret"
    33974     0xb/imm32/size
    33975     0x72/r 0x65/e 0x69/i 0x6e/n 0x74/t 0x65/e 0x72/r 0x70/p 0x72/r 0x65/e 0x74/t
    33976 _string-divide:
    33977     0x11/imm32/alloc-id:fake:payload
    33978     # "divide"
    33979     0x6/imm32/size
    33980     0x64/d 0x69/i 0x76/v 0x69/i 0x64/d 0x65/e
    33981 _string-max:
    33982     0x11/imm32/alloc-id:fake:payload
    33983     # "max"
    33984     0x3/imm32/size
    33985     0x6d/m 0x61/a 0x78/x
    33986 _string-min:
    33987     0x11/imm32/alloc-id:fake:payload
    33988     # "min"
    33989     0x3/imm32/size
    33990     0x6d/m 0x69/i 0x6e/n
    33991 _string-reciprocal:
    33992     0x11/imm32/alloc-id:fake:payload
    33993     # "reciprocal"
    33994     0xa/imm32/size
    33995     0x72/r 0x65/e 0x63/c 0x69/i 0x70/p 0x72/r 0x6f/o 0x63/c 0x61/a 0x6c/l
    33996 _string-square-root:
    33997     0x11/imm32/alloc-id:fake:payload
    33998     # "square-root"
    33999     0xb/imm32/size
    34000     0x73/s 0x71/q 0x75/u 0x61/a 0x72/r 0x65/e 0x2d/- 0x72/r 0x6f/o 0x6f/o 0x74/t
    34001 _string-inverse-square-root:
    34002     0x11/imm32/alloc-id:fake:payload
    34003     # "inverse-square-root"
    34004     0x13/imm32/size
    34005     0x69/i 0x6e/n 0x76/v 0x65/e 0x72/r 0x73/s 0x65/e 0x2d/- 0x73/s 0x71/q 0x75/u 0x61/a 0x72/r 0x65/e 0x2d/- 0x72/r 0x6f/o 0x6f/o 0x74/t
    34006 _string-negate:  # (payload array byte)
    34007     0x11/imm32/alloc-id:fake:payload
    34008     # "negate"
    34009     0x6/imm32/size
    34010     0x6e/n 0x65/e 0x67/g 0x61/a 0x74/t 0x65/e
    34011 _string-or:  # (payload array byte)
    34012     0x11/imm32/alloc-id:fake:payload
    34013     # "or"
    34014     0x2/imm32/size
    34015     0x6f/o 0x72/r
    34016 _string-or-with:  # (payload array byte)
    34017     0x11/imm32/alloc-id:fake:payload
    34018     # "or-with"
    34019     0x7/imm32/size
    34020     0x6f/o 0x72/r 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h
    34021 _string-subtract:  # (payload array byte)
    34022     0x11/imm32/alloc-id:fake:payload
    34023     # "subtract"
    34024     0x8/imm32/size
    34025     0x73/s 0x75/u 0x62/b 0x74/t 0x72/r 0x61/a 0x63/c 0x74/t
    34026 _string-subtract-from:  # (payload array byte)
    34027     0x11/imm32/alloc-id:fake:payload
    34028     # "subtract-from"
    34029     0xd/imm32/size
    34030     0x73/s 0x75/u 0x62/b 0x74/t 0x72/r 0x61/a 0x63/c 0x74/t 0x2d/dash 0x66/f 0x72/r 0x6f/o 0x6d/m
    34031 _string-xor:  # (payload array byte)
    34032     0x11/imm32/alloc-id:fake:payload
    34033     # "xor"
    34034     0x3/imm32/size
    34035     0x78/x 0x6f/o 0x72/r
    34036 _string-xor-with:  # (payload array byte)
    34037     0x11/imm32/alloc-id:fake:payload
    34038     # "xor-with"
    34039     0x8/imm32/size
    34040     0x78/x 0x6f/o 0x72/r 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h
    34041 _string-shift-left:  # (payload array byte)
    34042     0x11/imm32/alloc-id:fake:payload
    34043     # "shift-left"
    34044     0xa/imm32/size
    34045     0x73/s 0x68/h 0x69/i 0x66/f 0x74/t 0x2d/dash 0x6c/l 0x65/e 0x66/f 0x74/t
    34046 _string-shift-right:  # (payload array byte)
    34047     0x11/imm32/alloc-id:fake:payload
    34048     # "shift-right"
    34049     0xb/imm32/size
    34050     0x73/s 0x68/h 0x69/i 0x66/f 0x74/t 0x2d/dash 0x72/r 0x69/i 0x67/g 0x68/h 0x74/t
    34051 _string-shift-right-signed:  # (payload array byte)
    34052     0x11/imm32/alloc-id:fake:payload
    34053     # "shift-right-signed"
    34054     0x12/imm32/size
    34055     0x73/s 0x68/h 0x69/i 0x66/f 0x74/t 0x2d/dash 0x72/r 0x69/i 0x67/g 0x68/h 0x74/t 0x2d/dash 0x73/s 0x69/i 0x67/g 0x6e/n 0x65/e 0x64/d
    34056
    34057 # string literals for SubX instructions
    34058 _string_01_add_to:  # (payload array byte)
    34059     0x11/imm32/alloc-id:fake:payload
    34060     # "01/add-to"
    34061     0x9/imm32/size
    34062     0x30/0 0x31/1 0x2f/slash 0x61/a 0x64/d 0x64/d 0x2d/dash 0x74/t 0x6f/o
    34063 _string_03_add:  # (payload array byte)
    34064     0x11/imm32/alloc-id:fake:payload
    34065     # "03/add"
    34066     0x6/imm32/size
    34067     0x30/0 0x33/3 0x2f/slash 0x61/a 0x64/d 0x64/d
    34068 _string_05_add_to_eax:  # (payload array byte)
    34069     0x11/imm32/alloc-id:fake:payload
    34070     # "05/add-to-eax"
    34071     0xd/imm32/size
    34072     0x30/0 0x35/5 0x2f/slash 0x61/a 0x64/d 0x64/d 0x2d/dash 0x74/t 0x6f/o 0x2d/dash 0x65/e 0x61/a 0x78/x
    34073 _string_09_or_with:  # (payload array byte)
    34074     0x11/imm32/alloc-id:fake:payload
    34075     # "09/or-with"
    34076     0xa/imm32/size
    34077     0x30/0 0x39/9 0x2f/slash 0x6f/o 0x72/r 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h
    34078 _string_0b_or:  # (payload array byte)
    34079     0x11/imm32/alloc-id:fake:payload
    34080     # "0b/or"
    34081     0x5/imm32/size
    34082     0x30/0 0x62/b 0x2f/slash 0x6f/o 0x72/r
    34083 _string_0d_or_with_eax:  # (payload array byte)
    34084     0x11/imm32/alloc-id:fake:payload
    34085     # "0d/or-with-eax"
    34086     0xe/imm32/size
    34087     0x30/0 0x64/d 0x2f/slash 0x6f/o 0x72/r 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h 0x2d/dash 0x65/e 0x61/a 0x78/x
    34088 _string_0f_82_jump_label:  # (payload array byte)
    34089     0x11/imm32/alloc-id:fake:payload
    34090     # "0f 82/jump-if-addr<"
    34091     0x13/imm32/size
    34092     0x30/0 0x66/f 0x20/space 0x38/8 0x32/2 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x61/a 0x64/d 0x64/d 0x72/r 0x3c/<
    34093 _string_0f_82_jump_break:  # (payload array byte)
    34094     0x11/imm32/alloc-id:fake:payload
    34095     # "0f 82/jump-if-addr< break/disp32"
    34096     0x20/imm32/size
    34097     0x30/0 0x66/f 0x20/space 0x38/8 0x32/2 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x61/a 0x64/d 0x64/d 0x72/r 0x3c/< 0x20/space 0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2
    34098 _string_0f_82_jump_loop:  # (payload array byte)
    34099     0x11/imm32/alloc-id:fake:payload
    34100     # "0f 82/jump-if-addr< loop/disp32"
    34101     0x1f/imm32/size
    34102     0x30/0 0x66/f 0x20/space 0x38/8 0x32/2 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x61/a 0x64/d 0x64/d 0x72/r 0x3c/< 0x20/space 0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2
    34103 _string_0f_83_jump_label:  # (payload array byte)
    34104     0x11/imm32/alloc-id:fake:payload
    34105     # "0f 83/jump-if-addr>="
    34106     0x14/imm32/size
    34107     0x30/0 0x66/f 0x20/space 0x38/8 0x33/3 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x61/a 0x64/d 0x64/d 0x72/r 0x3e/> 0x3d/=
    34108 _string_0f_83_jump_break:  # (payload array byte)
    34109     0x11/imm32/alloc-id:fake:payload
    34110     # "0f 83/jump-if-addr>= break/disp32"
    34111     0x21/imm32/size
    34112     0x30/0 0x66/f 0x20/space 0x38/8 0x33/3 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x61/a 0x64/d 0x64/d 0x72/r 0x3e/> 0x3d/= 0x20/space 0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2
    34113 _string_0f_83_jump_loop:  # (payload array byte)
    34114     0x11/imm32/alloc-id:fake:payload
    34115     # "0f 83/jump-if-addr>= loop/disp32"
    34116     0x20/imm32/size
    34117     0x30/0 0x66/f 0x20/space 0x38/8 0x33/3 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x61/a 0x64/d 0x64/d 0x72/r 0x3e/> 0x3d/= 0x20/space 0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2
    34118 _string_0f_84_jump_label:  # (payload array byte)
    34119     0x11/imm32/alloc-id:fake:payload
    34120     # "0f 84/jump-if-="
    34121     0xf/imm32/size
    34122     0x30/0 0x66/f 0x20/space 0x38/8 0x34/4 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3d/=
    34123 _string_0f_84_jump_break:  # (payload array byte)
    34124     0x11/imm32/alloc-id:fake:payload
    34125     # "0f 84/jump-if-= break/disp32"
    34126     0x1c/imm32/size
    34127     0x30/0 0x66/f 0x20/space 0x38/8 0x34/4 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3d/= 0x20/space 0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2
    34128 _string_0f_84_jump_loop:  # (payload array byte)
    34129     0x11/imm32/alloc-id:fake:payload
    34130     # "0f 84/jump-if-= loop/disp32"
    34131     0x1b/imm32/size
    34132     0x30/0 0x66/f 0x20/space 0x38/8 0x34/4 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3d/= 0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2
    34133 _string_0f_85_jump_label:  # (payload array byte)
    34134     0x11/imm32/alloc-id:fake:payload
    34135     # "0f 85/jump-if-!="
    34136     0x10/imm32/size
    34137     0x30/0 0x66/f 0x20/space 0x38/8 0x35/5 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x21/! 0x3d/=
    34138 _string_0f_85_jump_break:  # (payload array byte)
    34139     0x11/imm32/alloc-id:fake:payload
    34140     # "0f 85/jump-if-!= break/disp32"
    34141     0x1d/imm32/size
    34142     0x30/0 0x66/f 0x20/space 0x38/8 0x35/5 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x21/! 0x3d/= 0x20/space 0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2
    34143 _string_0f_85_jump_loop:  # (payload array byte)
    34144     0x11/imm32/alloc-id:fake:payload
    34145     # "0f 85/jump-if-!= loop/disp32"
    34146     0x1c/imm32/size
    34147     0x30/0 0x66/f 0x20/space 0x38/8 0x35/5 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x21/! 0x3d/= 0x20/space 0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2
    34148 _string_0f_86_jump_label:  # (payload array byte)
    34149     0x11/imm32/alloc-id:fake:payload
    34150     # "0f 86/jump-if-addr<="
    34151     0x14/imm32/size
    34152     0x30/0 0x66/f 0x20/space 0x38/8 0x36/6 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x61/a 0x64/d 0x64/d 0x72/r 0x3c/< 0x3d/=
    34153 _string_0f_86_jump_break:  # (payload array byte)
    34154     0x11/imm32/alloc-id:fake:payload
    34155     # "0f 86/jump-if-addr<= break/disp32"
    34156     0x21/imm32/size
    34157     0x30/0 0x66/f 0x20/space 0x38/8 0x36/6 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x61/a 0x64/d 0x64/d 0x72/r 0x3c/< 0x3d/= 0x20/space 0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2
    34158 _string_0f_86_jump_loop:  # (payload array byte)
    34159     0x11/imm32/alloc-id:fake:payload
    34160     # "0f 86/jump-if-addr<= loop/disp32"
    34161     0x20/imm32/size
    34162     0x30/0 0x66/f 0x20/space 0x38/8 0x36/6 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x61/a 0x64/d 0x64/d 0x72/r 0x3c/< 0x3d/= 0x20/space 0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2
    34163 _string_0f_87_jump_label:  # (payload array byte)
    34164     0x11/imm32/alloc-id:fake:payload
    34165     # "0f 87/jump-if-addr>"
    34166     0x13/imm32/size
    34167     0x30/0 0x66/f 0x20/space 0x38/8 0x37/7 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x61/a 0x64/d 0x64/d 0x72/r 0x3e/>
    34168 _string_0f_87_jump_break:  # (payload array byte)
    34169     0x11/imm32/alloc-id:fake:payload
    34170     # "0f 87/jump-if-addr> break/disp32"
    34171     0x20/imm32/size
    34172     0x30/0 0x66/f 0x20/space 0x38/8 0x37/7 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x61/a 0x64/d 0x64/d 0x72/r 0x3e/> 0x20/space 0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2
    34173 _string_0f_87_jump_loop:  # (payload array byte)
    34174     0x11/imm32/alloc-id:fake:payload
    34175     # "0f 87/jump-if-addr> loop/disp32"
    34176     0x1f/imm32/size
    34177     0x30/0 0x66/f 0x20/space 0x38/8 0x37/7 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x61/a 0x64/d 0x64/d 0x72/r 0x3e/> 0x20/space 0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2
    34178 _string_0f_8c_jump_label:  # (payload array byte)
    34179     0x11/imm32/alloc-id:fake:payload
    34180     # "0f 8c/jump-if-<"
    34181     0xf/imm32/size
    34182     0x30/0 0x66/f 0x20/space 0x38/8 0x63/c 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3c/<
    34183 _string_0f_8c_jump_break:  # (payload array byte)
    34184     0x11/imm32/alloc-id:fake:payload
    34185     # "0f 8c/jump-if-< break/disp32"
    34186     0x1c/imm32/size
    34187     0x30/0 0x66/f 0x20/space 0x38/8 0x63/c 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3c/< 0x20/space 0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2
    34188 _string_0f_8c_jump_loop:  # (payload array byte)
    34189     0x11/imm32/alloc-id:fake:payload
    34190     # "0f 8c/jump-if-< loop/disp32"
    34191     0x1b/imm32/size
    34192     0x30/0 0x66/f 0x20/space 0x38/8 0x63/c 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3c/< 0x20/space 0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2
    34193 _string_0f_8d_jump_label:  # (payload array byte)
    34194     0x11/imm32/alloc-id:fake:payload
    34195     # "0f 8d/jump-if->="
    34196     0x10/imm32/size
    34197     0x30/0 0x66/f 0x20/space 0x38/8 0x64/d 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3e/> 0x3d/=
    34198 _string_0f_8d_jump_break:  # (payload array byte)
    34199     0x11/imm32/alloc-id:fake:payload
    34200     # "0f 8d/jump-if->= break/disp32"
    34201     0x1d/imm32/size
    34202     0x30/0 0x66/f 0x20/space 0x38/8 0x64/d 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3e/> 0x3d/= 0x20/space 0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2
    34203 _string_0f_8d_jump_loop:  # (payload array byte)
    34204     0x11/imm32/alloc-id:fake:payload
    34205     # "0f 8d/jump-if->= loop/disp32"
    34206     0x1c/imm32/size
    34207     0x30/0 0x66/f 0x20/space 0x38/8 0x64/d 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3e/> 0x3d/= 0x20/space 0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2
    34208 _string_0f_8e_jump_label:  # (payload array byte)
    34209     0x11/imm32/alloc-id:fake:payload
    34210     # "0f 8e/jump-if-<="
    34211     0x10/imm32/size
    34212     0x30/0 0x66/f 0x20/space 0x38/8 0x65/e 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3c/< 0x3d/=
    34213 _string_0f_8e_jump_break:  # (payload array byte)
    34214     0x11/imm32/alloc-id:fake:payload
    34215     # "0f 8e/jump-if-<= break/disp32"
    34216     0x1d/imm32/size
    34217     0x30/0 0x66/f 0x20/space 0x38/8 0x65/e 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3c/< 0x3d/= 0x20/space 0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2
    34218 _string_0f_8e_jump_loop:  # (payload array byte)
    34219     0x11/imm32/alloc-id:fake:payload
    34220     # "0f 8e/jump-if-<= loop/disp32"
    34221     0x1c/imm32/size
    34222     0x30/0 0x66/f 0x20/space 0x38/8 0x65/e 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3c/< 0x3d/= 0x20/space 0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2
    34223 _string_0f_8f_jump_label:  # (payload array byte)
    34224     0x11/imm32/alloc-id:fake:payload
    34225     # "0f 8f/jump-if->"
    34226     0xf/imm32/size
    34227     0x30/0 0x66/f 0x20/space 0x38/8 0x66/f 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3e/>
    34228 _string_0f_8f_jump_break:  # (payload array byte)
    34229     0x11/imm32/alloc-id:fake:payload
    34230     # "0f 8f/jump-if-> break/disp32"
    34231     0x1c/imm32/size
    34232     0x30/0 0x66/f 0x20/space 0x38/8 0x66/f 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3e/> 0x20/space 0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2
    34233 _string_0f_8f_jump_loop:  # (payload array byte)
    34234     0x11/imm32/alloc-id:fake:payload
    34235     # "0f 8f/jump-if-> loop/disp32"
    34236     0x1b/imm32/size
    34237     0x30/0 0x66/f 0x20/space 0x38/8 0x66/f 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3e/> 0x20/space 0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2
    34238 _string_0f_af_multiply:  # (payload array byte)
    34239     0x11/imm32/alloc-id:fake:payload
    34240     # "0f af/multiply"
    34241     0xe/imm32/size
    34242     0x30/0 0x66/f 0x20/space 0x61/a 0x66/f 0x2f/slash 0x6d/m 0x75/u 0x6c/l 0x74/t 0x69/i 0x70/p 0x6c/l 0x79/y
    34243 _string_f3_0f_2a_convert_to_float:
    34244     0x11/imm32/alloc-id:fake:payload
    34245     # "f3 0f 2a/convert-to-float"
    34246     0x19/imm32/size
    34247     0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x32/2 0x61/a 0x2f/slash 0x63/c 0x6f/o 0x6e/n 0x76/v 0x65/e 0x72/r 0x74/t 0x2d/dash 0x74/t 0x6f/o 0x2d/dash 0x66/f 0x6c/l 0x6f/o 0x61/a 0x74/t
    34248 _string_f3_0f_2d_convert_to_int:
    34249     0x11/imm32/alloc-id:fake:payload
    34250     # "f3 0f 2d/convert-to-int"
    34251     0x17/imm32/size
    34252     0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x32/2 0x64/d 0x2f/slash 0x63/c 0x6f/o 0x6e/n 0x76/v 0x65/e 0x72/r 0x74/t 0x2d/dash 0x74/t 0x6f/o 0x2d/dash 0x69/i 0x6e/n 0x74/t
    34253 _string_f3_0f_2c_truncate_to_int:
    34254     0x11/imm32/alloc-id:fake:payload
    34255     # "f3 0f 2c/truncate-to-int"
    34256     0x18/imm32/size
    34257     0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x32/2 0x63/c 0x2f/slash 0x74/t 0x72/r 0x75/u 0x6e/n 0x63/c 0x61/a 0x74/t 0x65/e 0x2d/dash 0x74/t 0x6f/o 0x2d/dash 0x69/i 0x6e/n 0x74/t
    34258 _string_f3_0f_58_add:
    34259     0x11/imm32/alloc-id:fake:payload
    34260     # "f3 0f 58/add"
    34261     0xc/imm32/size
    34262     0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x35/5 0x38/8 0x2f/slash 0x61/a 0x64/d 0x64/d
    34263 _string_f3_0f_5c_subtract:
    34264     0x11/imm32/alloc-id:fake:payload
    34265     # "f3 0f 5c/subtract"
    34266     0x11/imm32/size
    34267     0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x35/5 0x63/c 0x2f/slash 0x73/s 0x75/u 0x62/b 0x74/t 0x72/r 0x61/a 0x63/c 0x74/t
    34268 _string_f3_0f_59_multiply:
    34269     0x11/imm32/alloc-id:fake:payload
    34270     # "f3 0f 59/multiply"
    34271     0x11/imm32/size
    34272     0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x35/5 0x39/9 0x2f/slash 0x6d/m 0x75/u 0x6c/l 0x74/t 0x69/i 0x70/p 0x6c/l 0x79/y
    34273 _string_f3_0f_5e_divide:
    34274     0x11/imm32/alloc-id:fake:payload
    34275     # "f3 0f 5e/divide"
    34276     0xf/imm32/size
    34277     0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x35/5 0x65/e 0x2f/slash 0x64/d 0x69/i 0x76/v 0x69/i 0x64/d 0x65/e
    34278 _string_f3_0f_53_reciprocal:
    34279     0x11/imm32/alloc-id:fake:payload
    34280     # "f3 0f 53/reciprocal"
    34281     0x13/imm32/size
    34282     0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x35/5 0x33/3 0x2f/slash 0x72/r 0x65/e 0x63/c 0x69/i 0x70/p 0x72/r 0x6f/o 0x63/c 0x61/a 0x6c/l
    34283 _string_f3_0f_51_square_root:
    34284     0x11/imm32/alloc-id:fake:payload
    34285     # "f3 0f 51/square-root"
    34286     0x14/imm32/size
    34287     0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x35/5 0x31/1 0x2f/slash 0x73/s 0x71/q 0x75/u 0x61/a 0x72/r 0x65/e 0x2d/dash 0x72/r 0x6f/o 0x6f/o 0x74/t
    34288 _string_f3_0f_52_inverse_square_root:
    34289     0x11/imm32/alloc-id:fake:payload
    34290     # "f3 0f 52/inverse-square-root"
    34291     0x1c/imm32/size
    34292     0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x35/5 0x32/2 0x2f/slash 0x69/i 0x6e/n 0x76/v 0x65/e 0x72/r 0x73/s 0x65/e 0x2d/dash 0x73/s 0x71/q 0x75/u 0x61/a 0x72/r 0x65/e 0x2d/dash 0x72/r 0x6f/o 0x6f/o 0x74/t
    34293 _string_f3_0f_5d_min:
    34294     0x11/imm32/alloc-id:fake:payload
    34295     # "f3 0f 5d/min"
    34296     0xc/imm32/size
    34297     0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x35/5 0x64/d 0x2f/slash 0x6d/m 0x69/i 0x6e/n
    34298 _string_f3_0f_5f_max:
    34299     0x11/imm32/alloc-id:fake:payload
    34300     # "f3 0f 5f/max"
    34301     0xc/imm32/size
    34302     0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x35/5 0x66/f 0x2f/slash 0x6d/m 0x61/a 0x78/x
    34303 _string_f3_0f_10_copy:
    34304     0x11/imm32/alloc-id:fake:payload
    34305     # "f3 0f 10/copy"
    34306     0xd/imm32/size
    34307     0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x31/1 0x30/0 0x2f/slash 0x63/c 0x6f/o 0x70/p 0x79/y
    34308 _string_f3_0f_11_copy:
    34309     0x11/imm32/alloc-id:fake:payload
    34310     # "f3 0f 11/copy"
    34311     0xd/imm32/size
    34312     0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x31/1 0x31/1 0x2f/slash 0x63/c 0x6f/o 0x70/p 0x79/y
    34313 _string_0f_2f_compare:
    34314     0x11/imm32/alloc-id:fake:payload
    34315     # "0f 2f/compare"
    34316     0xd/imm32/size
    34317     0x30/0 0x66/f 0x20/space 0x32/2 0x66/f 0x2f/slash 0x63/c 0x6f/o 0x6d/m 0x70/p 0x61/a 0x72/r 0x65/e
    34318 _string_21_and_with:  # (payload array byte)
    34319     0x11/imm32/alloc-id:fake:payload
    34320     # "21/and-with"
    34321     0xb/imm32/size
    34322     0x32/2 0x31/1 0x2f/slash 0x61/a 0x6e/n 0x64/d 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h
    34323 _string_23_and:  # (payload array byte)
    34324     0x11/imm32/alloc-id:fake:payload
    34325     # "23/and"
    34326     0x6/imm32/size
    34327     0x32/2 0x33/3 0x2f/slash 0x61/a 0x6e/n 0x64/d
    34328 _string_25_and_with_eax:  # (payload array byte)
    34329     0x11/imm32/alloc-id:fake:payload
    34330     # "25/and-with-eax"
    34331     0xf/imm32/size
    34332     0x32/2 0x35/5 0x2f/slash 0x61/a 0x6e/n 0x64/d 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h 0x2d/dash 0x65/e 0x61/a 0x78/x
    34333 _string_29_subtract_from:  # (payload array byte)
    34334     0x11/imm32/alloc-id:fake:payload
    34335     # "29/subtract-from"
    34336     0x10/imm32/size
    34337     0x32/2 0x39/9 0x2f/slash 0x73/s 0x75/u 0x62/b 0x74/t 0x72/r 0x61/a 0x63/c 0x74/t 0x2d/dash 0x66/f 0x72/r 0x6f/o 0x6d/m
    34338 _string_2b_subtract:  # (payload array byte)
    34339     0x11/imm32/alloc-id:fake:payload
    34340     # "2b/subtract"
    34341     0xb/imm32/size
    34342     0x32/2 0x62/b 0x2f/slash 0x73/s 0x75/u 0x62/b 0x74/t 0x72/r 0x61/a 0x63/c 0x74/t
    34343 _string_2d_subtract_from_eax:  # (payload array byte)
    34344     0x11/imm32/alloc-id:fake:payload
    34345     # "2d/subtract-from-eax"
    34346     0x14/imm32/size
    34347     0x32/2 0x64/d 0x2f/slash 0x73/s 0x75/u 0x62/b 0x74/t 0x72/r 0x61/a 0x63/c 0x74/t 0x2d/dash 0x66/f 0x72/r 0x6f/o 0x6d/m 0x2d/dash 0x65/e 0x61/a 0x78/x
    34348 _string_31_xor_with:  # (payload array byte)
    34349     0x11/imm32/alloc-id:fake:payload
    34350     # "31/xor-with"
    34351     0xb/imm32/size
    34352     0x33/3 0x31/1 0x2f/slash 0x78/x 0x6f/o 0x72/r 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h
    34353 _string_33_xor:  # (payload array byte)
    34354     0x11/imm32/alloc-id:fake:payload
    34355     # "33/xor"
    34356     0x6/imm32/size
    34357     0x33/3 0x33/3 0x2f/slash 0x78/x 0x6f/o 0x72/r
    34358 _string_35_xor_with_eax:  # (payload array byte)
    34359     0x11/imm32/alloc-id:fake:payload
    34360     # "35/xor-with-eax"
    34361     0xf/imm32/size
    34362     0x33/3 0x35/5 0x2f/slash 0x78/x 0x6f/o 0x72/r 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h 0x2d/dash 0x65/e 0x61/a 0x78/x
    34363 _string_39_compare->:  # (payload array byte)
    34364     0x11/imm32/alloc-id:fake:payload
    34365     # "39/compare->"
    34366     0xc/imm32/size
    34367     0x33/3 0x39/9 0x2f/slash 0x63/c 0x6f/o 0x6d/m 0x70/p 0x61/a 0x72/r 0x65/e 0x2d/dash 0x3e/>
    34368 _string_3b_compare<-:  # (payload array byte)
    34369     0x11/imm32/alloc-id:fake:payload
    34370     # "3b/compare<-"
    34371     0xc/imm32/size
    34372     0x33/3 0x62/b 0x2f/slash 0x63/c 0x6f/o 0x6d/m 0x70/p 0x61/a 0x72/r 0x65/e 0x3c/< 0x2d/dash
    34373 _string_3d_compare_eax_with:  # (payload array byte)
    34374     0x11/imm32/alloc-id:fake:payload
    34375     # "3d/compare-eax-with"
    34376     0x13/imm32/size
    34377     0x33/3 0x64/d 0x2f/slash 0x63/c 0x6f/o 0x6d/m 0x70/p 0x61/a 0x72/r 0x65/e 0x2d/dash 0x65/e 0x61/a 0x78/x 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h
    34378 _string_40_increment_eax:  # (payload array byte)
    34379     0x11/imm32/alloc-id:fake:payload
    34380     # "40/increment-eax"
    34381     0x10/imm32/size
    34382     0x34/4 0x30/0 0x2f/slash 0x69/i 0x6e/n 0x63/c 0x72/r 0x65/e 0x6d/m 0x65/e 0x6e/n 0x74/t 0x2d/dash 0x65/e 0x61/a 0x78/x
    34383 _string_41_increment_ecx:  # (payload array byte)
    34384     0x11/imm32/alloc-id:fake:payload
    34385     # "41/increment-ecx"
    34386     0x10/imm32/size
    34387     0x34/4 0x31/1 0x2f/slash 0x69/i 0x6e/n 0x63/c 0x72/r 0x65/e 0x6d/m 0x65/e 0x6e/n 0x74/t 0x2d/dash 0x65/e 0x63/c 0x78/x
    34388 _string_42_increment_edx:  # (payload array byte)
    34389     0x11/imm32/alloc-id:fake:payload
    34390     # "42/increment-edx"
    34391     0x10/imm32/size
    34392     0x34/4 0x32/2 0x2f/slash 0x69/i 0x6e/n 0x63/c 0x72/r 0x65/e 0x6d/m 0x65/e 0x6e/n 0x74/t 0x2d/dash 0x65/e 0x64/d 0x78/x
    34393 _string_43_increment_ebx:  # (payload array byte)
    34394     0x11/imm32/alloc-id:fake:payload
    34395     # "43/increment-ebx"
    34396     0x10/imm32/size
    34397     0x34/4 0x33/3 0x2f/slash 0x69/i 0x6e/n 0x63/c 0x72/r 0x65/e 0x6d/m 0x65/e 0x6e/n 0x74/t 0x2d/dash 0x65/e 0x62/b 0x78/x
    34398 _string_46_increment_esi:  # (payload array byte)
    34399     0x11/imm32/alloc-id:fake:payload
    34400     # "46/increment-esi"
    34401     0x10/imm32/size
    34402     0x34/4 0x36/6 0x2f/slash 0x69/i 0x6e/n 0x63/c 0x72/r 0x65/e 0x6d/m 0x65/e 0x6e/n 0x74/t 0x2d/dash 0x65/e 0x73/s 0x69/i
    34403 _string_47_increment_edi:  # (payload array byte)
    34404     0x11/imm32/alloc-id:fake:payload
    34405     # "47/increment-edi"
    34406     0x10/imm32/size
    34407     0x34/4 0x37/7 0x2f/slash 0x69/i 0x6e/n 0x63/c 0x72/r 0x65/e 0x6d/m 0x65/e 0x6e/n 0x74/t 0x2d/dash 0x65/e 0x64/d 0x69/i
    34408 _string_48_decrement_eax:  # (payload array byte)
    34409     0x11/imm32/alloc-id:fake:payload
    34410     # "48/decrement-eax"
    34411     0x10/imm32/size
    34412     0x34/4 0x38/8 0x2f/slash 0x64/d 0x65/e 0x63/c 0x72/r 0x65/e 0x6d/m 0x65/e 0x6e/n 0x74/t 0x2d/dash 0x65/e 0x61/a 0x78/x
    34413 _string_49_decrement_ecx:  # (payload array byte)
    34414     0x11/imm32/alloc-id:fake:payload
    34415     # "49/decrement-ecx"
    34416     0x10/imm32/size
    34417     0x34/4 0x39/9 0x2f/slash 0x64/d 0x65/e 0x63/c 0x72/r 0x65/e 0x6d/m 0x65/e 0x6e/n 0x74/t 0x2d/dash 0x65/e 0x63/c 0x78/x
    34418 _string_4a_decrement_edx:  # (payload array byte)
    34419     0x11/imm32/alloc-id:fake:payload
    34420     # "4a/decrement-edx"
    34421     0x10/imm32/size
    34422     0x34/4 0x61/a 0x2f/slash 0x64/d 0x65/e 0x63/c 0x72/r 0x65/e 0x6d/m 0x65/e 0x6e/n 0x74/t 0x2d/dash 0x65/e 0x64/d 0x78/x
    34423 _string_4b_decrement_ebx:  # (payload array byte)
    34424     0x11/imm32/alloc-id:fake:payload
    34425     # "4b/decrement-ebx"
    34426     0x10/imm32/size
    34427     0x34/4 0x62/b 0x2f/slash 0x64/d 0x65/e 0x63/c 0x72/r 0x65/e 0x6d/m 0x65/e 0x6e/n 0x74/t 0x2d/dash 0x65/e 0x62/b 0x78/x
    34428 _string_4e_decrement_esi:  # (payload array byte)
    34429     0x11/imm32/alloc-id:fake:payload
    34430     # "4e/decrement-esi"
    34431     0x10/imm32/size
    34432     0x34/4 0x65/e 0x2f/slash 0x64/d 0x65/e 0x63/c 0x72/r 0x65/e 0x6d/m 0x65/e 0x6e/n 0x74/t 0x2d/dash 0x65/e 0x73/s 0x69/i
    34433 _string_4f_decrement_edi:  # (payload array byte)
    34434     0x11/imm32/alloc-id:fake:payload
    34435     # "4f/decrement-edi"
    34436     0x10/imm32/size
    34437     0x34/4 0x66/f 0x2f/slash 0x64/d 0x65/e 0x63/c 0x72/r 0x65/e 0x6d/m 0x65/e 0x6e/n 0x74/t 0x2d/dash 0x65/e 0x64/d 0x69/i
    34438 _string_81_subop_add:  # (payload array byte)
    34439     0x11/imm32/alloc-id:fake:payload
    34440     # "81 0/subop/add"
    34441     0xe/imm32/size
    34442     0x38/8 0x31/1 0x20/space 0x30/0 0x2f/slash 0x73/s 0x75/u 0x62/b 0x6f/o 0x70/p 0x2f/slash 0x61/a 0x64/d 0x64/d
    34443 _string_81_subop_or:  # (payload array byte)
    34444     0x11/imm32/alloc-id:fake:payload
    34445     # "81 1/subop/or"
    34446     0xd/imm32/size
    34447     0x38/8 0x31/1 0x20/space 0x31/1 0x2f/slash 0x73/s 0x75/u 0x62/b 0x6f/o 0x70/p 0x2f/slash 0x6f/o 0x72/r
    34448 _string_81_subop_and:  # (payload array byte)
    34449     0x11/imm32/alloc-id:fake:payload
    34450     # "81 4/subop/and"
    34451     0xe/imm32/size
    34452     0x38/8 0x31/1 0x20/space 0x34/4 0x2f/slash 0x73/s 0x75/u 0x62/b 0x6f/o 0x70/p 0x2f/slash 0x61/a 0x6e/n 0x64/d
    34453 _string_81_subop_subtract:  # (payload array byte)
    34454     0x11/imm32/alloc-id:fake:payload
    34455     # "81 5/subop/subtract"
    34456     0x13/imm32/size
    34457     0x38/8 0x31/1 0x20/space 0x35/5 0x2f/slash 0x73/s 0x75/u 0x62/b 0x6f/o 0x70/p 0x2f/slash 0x73/s 0x75/u 0x62/b 0x74/t 0x72/r 0x61/a 0x63/c 0x74/t
    34458 _string_81_subop_xor:  # (payload array byte)
    34459     0x11/imm32/alloc-id:fake:payload
    34460     # "81 6/subop/xor"
    34461     0xe/imm32/size
    34462     0x38/8 0x31/1 0x20/space 0x36/6 0x2f/slash 0x73/s 0x75/u 0x62/b 0x6f/o 0x70/p 0x2f/slash 0x78/x 0x6f/o 0x72/r
    34463 _string_81_subop_compare:  # (payload array byte)
    34464     0x11/imm32/alloc-id:fake:payload
    34465     # "81 7/subop/compare"
    34466     0x12/imm32/size
    34467     0x38/8 0x31/1 0x20/space 0x37/7 0x2f/slash 0x73/s 0x75/u 0x62/b 0x6f/o 0x70/p 0x2f/slash 0x63/c 0x6f/o 0x6d/m 0x70/p 0x61/a 0x72/r 0x65/e
    34468 _string_89_<-:  # (payload array byte)
    34469     0x11/imm32/alloc-id:fake:payload
    34470     # "89/<-"
    34471     0x5/imm32/size
    34472     0x38/8 0x39/9 0x2f/slash 0x3c/< 0x2d/dash
    34473 _string_8b_->:  # (payload array byte)
    34474     0x11/imm32/alloc-id:fake:payload
    34475     # "8b/->"
    34476     0x5/imm32/size
    34477     0x38/8 0x62/b 0x2f/slash 0x2d/dash 0x3e/>
    34478 _string_8a_copy_byte:
    34479     0x11/imm32/alloc-id:fake:payload
    34480     # "8a/byte->"
    34481     0x9/imm32/size
    34482     0x38/8 0x61/a 0x2f// 0x62/b 0x79/y 0x74/t 0x65/e 0x2d/- 0x3e/>
    34483 _string_88_copy_byte:
    34484     0x11/imm32/alloc-id:fake:payload
    34485     # "88/byte<-"
    34486     0x9/imm32/size
    34487     0x38/8 0x38/8 0x2f// 0x62/b 0x79/y 0x74/t 0x65/e 0x3c/< 0x2d/-
    34488 _string_8d_copy_address:  # (payload array byte)
    34489     0x11/imm32/alloc-id:fake:payload
    34490     # "8d/copy-address"
    34491     0xf/imm32/size
    34492     0x38/8 0x64/d 0x2f/slash 0x63/c 0x6f/o 0x70/p 0x79/y 0x2d/dash 0x61/a 0x64/d 0x64/d 0x72/r 0x65/e 0x73/s 0x73/s
    34493 _string_b8_copy_to_eax:  # (payload array byte)
    34494     0x11/imm32/alloc-id:fake:payload
    34495     # "b8/copy-to-eax"
    34496     0xe/imm32/size
    34497     0x62/b 0x38/8 0x2f/slash 0x63/c 0x6f/o 0x70/p 0x79/y 0x2d/dash 0x74/t 0x6f/o 0x2d/dash 0x65/e 0x61/a 0x78/x
    34498 _string_b9_copy_to_ecx:  # (payload array byte)
    34499     0x11/imm32/alloc-id:fake:payload
    34500     # "b9/copy-to-ecx"
    34501     0xe/imm32/size
    34502     0x62/b 0x39/9 0x2f/slash 0x63/c 0x6f/o 0x70/p 0x79/y 0x2d/dash 0x74/t 0x6f/o 0x2d/dash 0x65/e 0x63/c 0x78/x
    34503 _string_ba_copy_to_edx:  # (payload array byte)
    34504     0x11/imm32/alloc-id:fake:payload
    34505     # "ba/copy-to-edx"
    34506     0xe/imm32/size
    34507     0x62/b 0x61/a 0x2f/slash 0x63/c 0x6f/o 0x70/p 0x79/y 0x2d/dash 0x74/t 0x6f/o 0x2d/dash 0x65/e 0x64/d 0x78/x
    34508 _string_bb_copy_to_ebx:  # (payload array byte)
    34509     0x11/imm32/alloc-id:fake:payload
    34510     # "bb/copy-to-ebx"
    34511     0xe/imm32/size
    34512     0x62/b 0x62/b 0x2f/slash 0x63/c 0x6f/o 0x70/p 0x79/y 0x2d/dash 0x74/t 0x6f/o 0x2d/dash 0x65/e 0x62/b 0x78/x
    34513 _string_be_copy_to_esi:  # (payload array byte)
    34514     0x11/imm32/alloc-id:fake:payload
    34515     # "be/copy-to-esi"
    34516     0xe/imm32/size
    34517     0x62/b 0x65/e 0x2f/slash 0x63/c 0x6f/o 0x70/p 0x79/y 0x2d/dash 0x74/t 0x6f/o 0x2d/dash 0x65/e 0x73/s 0x69/i
    34518 _string_bf_copy_to_edi:  # (payload array byte)
    34519     0x11/imm32/alloc-id:fake:payload
    34520     # "bf/copy-to-edi"
    34521     0xe/imm32/size
    34522     0x62/b 0x66/f 0x2f/slash 0x63/c 0x6f/o 0x70/p 0x79/y 0x2d/dash 0x74/t 0x6f/o 0x2d/dash 0x65/e 0x64/d 0x69/i
    34523 _string_c7_subop_copy:  # (payload array byte)
    34524     0x11/imm32/alloc-id:fake:payload
    34525     # "c7 0/subop/copy"
    34526     0xf/imm32/size
    34527     0x63/c 0x37/7 0x20/space 0x30/0 0x2f/slash 0x73/s 0x75/u 0x62/b 0x6f/o 0x70/p 0x2f/slash 0x63/c 0x6f/o 0x70/p 0x79/y
    34528 _string_e9_jump_label:  # (payload array byte)
    34529     0x11/imm32/alloc-id:fake:payload
    34530     # "e9/jump"
    34531     0x7/imm32/size
    34532     0x65/e 0x39/9 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p
    34533 _string_e9_jump_break:  # (payload array byte)
    34534     0x11/imm32/alloc-id:fake:payload
    34535     # "e9/jump break/disp32"
    34536     0x14/imm32/size
    34537     0x65/e 0x39/9 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x20/space 0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2
    34538 _string_e9_jump_loop:  # (payload array byte)
    34539     0x11/imm32/alloc-id:fake:payload
    34540     # "e9/jump loop/disp32"
    34541     0x13/imm32/size
    34542     0x65/e 0x39/9 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x20/space 0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2
    34543 _string_f7_subop_negate:
    34544     0x11/imm32/alloc-id:fake:payload
    34545     # "f7 3/subop/negate"
    34546     0x11/imm32/size
    34547     0x66/f 0x37/7 0x20/space 0x33/3 0x2f/slash 0x73/s 0x75/u 0x62/b 0x6f/o 0x70/p 0x2f/slash 0x6e/n 0x65/e 0x67/g 0x61/a 0x74/t 0x65/e
    34548 _string_ff_subop_increment:  # (payload array byte)
    34549     0x11/imm32/alloc-id:fake:payload
    34550     # "ff 0/subop/increment"
    34551     0x14/imm32/size
    34552     0x66/f 0x66/f 0x20/space 0x30/0 0x2f/slash 0x73/s 0x75/u 0x62/b 0x6f/o 0x70/p 0x2f/slash 0x69/i 0x6e/n 0x63/c 0x72/r 0x65/e 0x6d/m 0x65/e 0x6e/n 0x74/t
    34553 _string_ff_subop_decrement:  # (payload array byte)
    34554     0x11/imm32/alloc-id:fake:payload
    34555     # "ff 1/subop/decrement"
    34556     0x14/imm32/size
    34557     0x66/f 0x66/f 0x20/space 0x31/1 0x2f/slash 0x73/s 0x75/u 0x62/b 0x6f/o 0x70/p 0x2f/slash 0x64/d 0x65/e 0x63/c 0x72/r 0x65/e 0x6d/m 0x65/e 0x6e/n 0x74/t
    34558 _string_c1_subop_shift_left:  # (payload array byte)
    34559     0x11/imm32/alloc-id:fake:payload
    34560     # "c1/shift 4/subop/left"
    34561     0x15/imm32/size
    34562     0x63/c 0x31/1 0x2f/slash 0x73/s 0x68/h 0x69/i 0x66/f 0x74/t 0x20/space 0x34/4 0x2f/slash 0x73/s 0x75/u 0x62/b 0x6f/o 0x70/p 0x2f/slash 0x6c/l 0x65/e 0x66/f 0x74/t
    34563 _string_c1_subop_shift_right_padding_zeroes:  # (payload array byte)
    34564     0x11/imm32/alloc-id:fake:payload
    34565     # "c1/shift 5/subop/right-padding-zeroes"
    34566     0x25/imm32/size
    34567     0x63/c 0x31/1 0x2f/slash 0x73/s 0x68/h 0x69/i 0x66/f 0x74/t 0x20/space 0x35/5 0x2f/slash 0x73/s 0x75/u 0x62/b 0x6f/o 0x70/p 0x2f/slash 0x72/r 0x69/i 0x67/g 0x68/h 0x74/t 0x2d/dash 0x70/p 0x61/a 0x64/d 0x64/d 0x69/i 0x6e/n 0x67/g 0x2d/dash 0x7a/z 0x65/e 0x72/r 0x6f/o 0x65/e 0x73/s
    34568 _string_c1_subop_shift_right_preserving_sign:  # (payload array byte)
    34569     0x11/imm32/alloc-id:fake:payload
    34570     # "c1/shift 7/subop/right-preserving-sign"
    34571     0x26/imm32/size
    34572     0x63/c 0x31/1 0x2f/slash 0x73/s 0x68/h 0x69/i 0x66/f 0x74/t 0x20/space 0x37/7 0x2f/slash 0x73/s 0x75/u 0x62/b 0x6f/o 0x70/p 0x2f/slash 0x72/r 0x69/i 0x67/g 0x68/h 0x74/t 0x2d/dash 0x70/p 0x72/r 0x65/e 0x73/s 0x65/e 0x72/r 0x76/v 0x69/i 0x6e/n 0x67/g 0x2d/dash 0x73/s 0x69/i 0x67/g 0x6e/n
    34573
    34574 Single-int-var-in-mem:  # (payload list var)
    34575     0x11/imm32/alloc-id:fake:payload
    34576     0x11/imm32/alloc-id:fake
    34577     Int-var-in-mem/imm32
    34578     0/imm32/next
    34579     0/imm32/next
    34580
    34581 Int-var-in-mem:  # (payload var)
    34582     0x11/imm32/alloc-id:fake:payload
    34583     0/imm32/name
    34584     0/imm32/name
    34585     0x11/imm32/alloc-id:fake
    34586     Type-int/imm32
    34587     1/imm32/some-block-depth
    34588     1/imm32/some-stack-offset
    34589     0/imm32/no-register
    34590     0/imm32/no-register
    34591
    34592 # Not really legal, but closest we can currently represent a dereference of an (addr byte)
    34593 Single-byte-var-in-mem:  # (payload list var)
    34594     0x11/imm32/alloc-id:fake:payload
    34595     0x11/imm32/alloc-id:fake
    34596     Byte-var-in-mem/imm32
    34597     0/imm32/next
    34598     0/imm32/next
    34599
    34600 # Not really legal, but closest we can currently represent a dereference of an (addr byte)
    34601 Byte-var-in-mem:  # (payload var)
    34602     0x11/imm32/alloc-id:fake:payload
    34603     0/imm32/name
    34604     0/imm32/name
    34605     0x11/imm32/alloc-id:fake
    34606     Type-byte/imm32
    34607     1/imm32/some-block-depth
    34608     1/imm32/some-stack-offset
    34609     0/imm32/no-register
    34610     0/imm32/no-register
    34611
    34612 Two-args-int-stack-int-reg:  # (payload list var)
    34613     0x11/imm32/alloc-id:fake:payload
    34614     0x11/imm32/alloc-id:fake
    34615     Int-var-in-mem/imm32
    34616     0x11/imm32/alloc-id:fake
    34617     Single-int-var-in-some-register/imm32/next
    34618
    34619 Two-int-args-in-regs:  # (payload list var)
    34620     0x11/imm32/alloc-id:fake:payload
    34621     0x11/imm32/alloc-id:fake
    34622     Int-var-in-some-register/imm32
    34623     0x11/imm32/alloc-id:fake
    34624     Single-int-var-in-some-register/imm32/next
    34625
    34626 # Not really legal, but closest we can currently represent a dereference of an (addr byte)
    34627 Two-args-byte-stack-byte-reg:  # (payload list var)
    34628     0x11/imm32/alloc-id:fake:payload
    34629     0x11/imm32/alloc-id:fake
    34630     Byte-var-in-mem/imm32
    34631     0x11/imm32/alloc-id:fake
    34632     Single-byte-var-in-some-register/imm32/next
    34633
    34634 Two-args-int-reg-int-stack:  # (payload list var)
    34635     0x11/imm32/alloc-id:fake:payload
    34636     0x11/imm32/alloc-id:fake
    34637     Int-var-in-some-register/imm32
    34638     0x11/imm32/alloc-id:fake
    34639     Single-int-var-in-mem/imm32/next
    34640
    34641 Two-args-int-eax-int-literal:  # (payload list var)
    34642     0x11/imm32/alloc-id:fake:payload
    34643     0x11/imm32/alloc-id:fake
    34644     Int-var-in-eax/imm32
    34645     0x11/imm32/alloc-id:fake
    34646     Single-lit-var/imm32/next
    34647
    34648 Int-var-and-literal:  # (payload list var)
    34649     0x11/imm32/alloc-id:fake:payload
    34650     0x11/imm32/alloc-id:fake
    34651     Int-var-in-mem/imm32
    34652     0x11/imm32/alloc-id:fake
    34653     Single-lit-var/imm32/next
    34654
    34655 Int-var-in-register-and-literal:  # (payload list var)
    34656     0x11/imm32/alloc-id:fake:payload
    34657     0x11/imm32/alloc-id:fake
    34658     Int-var-in-some-register/imm32
    34659     0x11/imm32/alloc-id:fake
    34660     Single-lit-var/imm32/next
    34661
    34662 Two-float-args-in-regs:  # (payload list var)
    34663     0x11/imm32/alloc-id:fake:payload
    34664     0x11/imm32/alloc-id:fake
    34665     Float-var-in-some-register/imm32
    34666     0x11/imm32/alloc-id:fake
    34667     Single-float-var-in-some-register/imm32/next
    34668
    34669 Two-args-float-reg-float-stack:  # (payload list var)
    34670     0x11/imm32/alloc-id:fake:payload
    34671     0x11/imm32/alloc-id:fake
    34672     Float-var-in-some-register/imm32
    34673     0x11/imm32/alloc-id:fake
    34674     Single-float-var-in-mem/imm32/next
    34675
    34676 Two-args-float-stack-float-reg:  # (payload list var)
    34677     0x11/imm32/alloc-id:fake:payload
    34678     0x11/imm32/alloc-id:fake
    34679     Float-var-in-mem/imm32
    34680     0x11/imm32/alloc-id:fake
    34681     Single-float-var-in-some-register/imm32/next
    34682
    34683 Single-int-var-in-some-register:  # (payload list var)
    34684     0x11/imm32/alloc-id:fake:payload
    34685     0x11/imm32/alloc-id:fake
    34686     Int-var-in-some-register/imm32
    34687     0/imm32/next
    34688     0/imm32/next
    34689
    34690 Single-addr-var-in-some-register:  # (payload list var)
    34691     0x11/imm32/alloc-id:fake:payload
    34692     0x11/imm32/alloc-id:fake
    34693     Addr-var-in-some-register/imm32
    34694     0/imm32/next
    34695     0/imm32/next
    34696
    34697 Single-byte-var-in-some-register:  # (payload list var)
    34698     0x11/imm32/alloc-id:fake:payload
    34699     0x11/imm32/alloc-id:fake
    34700     Byte-var-in-some-register/imm32
    34701     0/imm32/next
    34702     0/imm32/next
    34703
    34704 Int-var-in-some-register:  # (payload var)
    34705     0x11/imm32/alloc-id:fake:payload
    34706     0/imm32/name
    34707     0/imm32/name
    34708     0x11/imm32/alloc-id:fake
    34709     Type-int/imm32
    34710     1/imm32/some-block-depth
    34711     0/imm32/no-stack-offset
    34712     0x11/imm32/alloc-id:fake
    34713     Any-register/imm32
    34714
    34715 Any-register:  # (payload array byte)
    34716     0x11/imm32/alloc-id:fake:payload
    34717     1/imm32/size
    34718     # data
    34719     2a/asterisk
    34720
    34721 Addr-var-in-some-register:  # (payload var)
    34722     0x11/imm32/alloc-id:fake:payload
    34723     0/imm32/name
    34724     0/imm32/name
    34725     0x11/imm32/alloc-id:fake
    34726     Type-addr/imm32
    34727     1/imm32/some-block-depth
    34728     0/imm32/no-stack-offset
    34729     0x11/imm32/alloc-id:fake
    34730     Any-register/imm32
    34731
    34732 Byte-var-in-some-register:  # (payload var)
    34733     0x11/imm32/alloc-id:fake:payload
    34734     0/imm32/name
    34735     0/imm32/name
    34736     0x11/imm32/alloc-id:fake
    34737     Type-byte/imm32
    34738     1/imm32/some-block-depth
    34739     0/imm32/no-stack-offset
    34740     0x11/imm32/alloc-id:fake
    34741     Any-register/imm32
    34742
    34743 Single-int-var-in-eax:  # (payload list var)
    34744     0x11/imm32/alloc-id:fake:payload
    34745     0x11/imm32/alloc-id:fake
    34746     Int-var-in-eax/imm32
    34747     0/imm32/next
    34748     0/imm32/next
    34749
    34750 Int-var-in-eax:
    34751     0x11/imm32/alloc-id:fake:payload
    34752     0/imm32/name
    34753     0/imm32/name
    34754     0x11/imm32/alloc-id:fake
    34755     Type-int/imm32
    34756     1/imm32/some-block-depth
    34757     0/imm32/no-stack-offset
    34758     0x11/imm32/alloc-id:fake
    34759     $Mu-register-eax/imm32  # can't use Register-eax only to keep our buggy tools/treeshake.cc happy (TODO)
    34760
    34761 Single-int-var-in-ecx:  # (payload list var)
    34762     0x11/imm32/alloc-id:fake:payload
    34763     0x11/imm32/alloc-id:fake
    34764     Int-var-in-ecx/imm32
    34765     0/imm32/next
    34766     0/imm32/next
    34767
    34768 Int-var-in-ecx:
    34769     0x11/imm32/alloc-id:fake:payload
    34770     0/imm32/name
    34771     0/imm32/name
    34772     0x11/imm32/alloc-id:fake
    34773     Type-int/imm32
    34774     1/imm32/some-block-depth
    34775     0/imm32/no-stack-offset
    34776     0x11/imm32/alloc-id:fake
    34777     $Register-ecx/imm32/register
    34778
    34779 Single-int-var-in-edx:  # (payload list var)
    34780     0x11/imm32/alloc-id:fake:payload
    34781     0x11/imm32/alloc-id:fake
    34782     Int-var-in-edx/imm32
    34783     0/imm32/next
    34784     0/imm32/next
    34785
    34786 Int-var-in-edx:  # (payload list var)
    34787     0x11/imm32/alloc-id:fake:payload
    34788     0/imm32/name
    34789     0/imm32/name
    34790     0x11/imm32/alloc-id:fake
    34791     Type-int/imm32
    34792     1/imm32/some-block-depth
    34793     0/imm32/no-stack-offset
    34794     0x11/imm32/alloc-id:fake
    34795     $Register-edx/imm32/register
    34796
    34797 Single-int-var-in-ebx:  # (payload list var)
    34798     0x11/imm32/alloc-id:fake:payload
    34799     0x11/imm32/alloc-id:fake
    34800     Int-var-in-ebx/imm32
    34801     0/imm32/next
    34802     0/imm32/next
    34803
    34804 Int-var-in-ebx:  # (payload list var)
    34805     0x11/imm32/alloc-id:fake:payload
    34806     0/imm32/name
    34807     0/imm32/name
    34808     0x11/imm32/alloc-id:fake
    34809     Type-int/imm32
    34810     1/imm32/some-block-depth
    34811     0/imm32/no-stack-offset
    34812     0x11/imm32/alloc-id:fake
    34813     $Register-ebx/imm32/register
    34814
    34815 Single-int-var-in-esi:  # (payload list var)
    34816     0x11/imm32/alloc-id:fake:payload
    34817     0x11/imm32/alloc-id:fake
    34818     Int-var-in-esi/imm32
    34819     0/imm32/next
    34820     0/imm32/next
    34821
    34822 Int-var-in-esi:  # (payload list var)
    34823     0x11/imm32/alloc-id:fake:payload
    34824     0/imm32/name
    34825     0/imm32/name
    34826     0x11/imm32/alloc-id:fake
    34827     Type-int/imm32
    34828     1/imm32/some-block-depth
    34829     0/imm32/no-stack-offset
    34830     0x11/imm32/alloc-id:fake
    34831     $Register-esi/imm32/register
    34832
    34833 Single-int-var-in-edi:  # (payload list var)
    34834     0x11/imm32/alloc-id:fake:payload
    34835     0x11/imm32/alloc-id:fake
    34836     Int-var-in-edi/imm32
    34837     0/imm32/next
    34838     0/imm32/next
    34839
    34840 Int-var-in-edi:  # (payload list var)
    34841     0x11/imm32/alloc-id:fake:payload
    34842     0/imm32/name
    34843     0/imm32/name
    34844     0x11/imm32/alloc-id:fake
    34845     Type-int/imm32
    34846     1/imm32/some-block-depth
    34847     0/imm32/no-stack-offset
    34848     0x11/imm32/alloc-id:fake
    34849     $Register-edi/imm32/register
    34850
    34851 Single-lit-var:  # (payload list var)
    34852     0x11/imm32/alloc-id:fake:payload
    34853     0x11/imm32/alloc-id:fake
    34854     Lit-var/imm32
    34855     0/imm32/next
    34856     0/imm32/next
    34857
    34858 Lit-var:  # (payload var)
    34859     0x11/imm32/alloc-id:fake:payload
    34860     0/imm32/name
    34861     0/imm32/name
    34862     0x11/imm32/alloc-id:fake
    34863     Type-literal/imm32
    34864     1/imm32/some-block-depth
    34865     0/imm32/no-stack-offset
    34866     0/imm32/no-register
    34867     0/imm32/no-register
    34868
    34869 Single-float-var-in-mem:  # (payload list var)
    34870     0x11/imm32/alloc-id:fake:payload
    34871     0x11/imm32/alloc-id:fake
    34872     Float-var-in-mem/imm32
    34873     0/imm32/next
    34874     0/imm32/next
    34875
    34876 Float-var-in-mem:  # (payload var)
    34877     0x11/imm32/alloc-id:fake:payload
    34878     0/imm32/name
    34879     0/imm32/name
    34880     0x11/imm32/alloc-id:fake
    34881     Type-float/imm32
    34882     1/imm32/some-block-depth
    34883     1/imm32/some-stack-offset
    34884     0/imm32/no-register
    34885     0/imm32/no-register
    34886
    34887 Single-float-var-in-some-register:  # (payload list var)
    34888     0x11/imm32/alloc-id:fake:payload
    34889     0x11/imm32/alloc-id:fake
    34890     Float-var-in-some-register/imm32
    34891     0/imm32/next
    34892     0/imm32/next
    34893
    34894 Float-var-in-some-register:  # (payload var)
    34895     0x11/imm32/alloc-id:fake:payload
    34896     0/imm32/name
    34897     0/imm32/name
    34898     0x11/imm32/alloc-id:fake
    34899     Type-float/imm32
    34900     1/imm32/some-block-depth
    34901     0/imm32/no-stack-offset
    34902     0x11/imm32/alloc-id:fake
    34903     Any-register/imm32
    34904
    34905 Type-int:  # (payload type-tree)
    34906     0x11/imm32/alloc-id:fake:payload
    34907     1/imm32/is-atom
    34908     1/imm32/value:int
    34909     0/imm32/left:unused
    34910     0/imm32/right:null
    34911     0/imm32/right:null
    34912
    34913 Type-literal:  # (payload type-tree)
    34914     0x11/imm32/alloc-id:fake:payload
    34915     1/imm32/is-atom
    34916     0/imm32/value:literal
    34917     0/imm32/left:unused
    34918     0/imm32/right:null
    34919     0/imm32/right:null
    34920
    34921 Type-addr:  # (payload type-tree)
    34922     0x11/imm32/alloc-id:fake:payload
    34923     1/imm32/is-atom
    34924     2/imm32/value:addr
    34925     0/imm32/left:unused
    34926     0/imm32/right:null
    34927     0/imm32/right:null
    34928
    34929 Type-byte:  # (payload type-tree)
    34930     0x11/imm32/alloc-id:fake:payload
    34931     1/imm32/is-atom
    34932     8/imm32/value:byte
    34933     0/imm32/left:unused
    34934     0/imm32/right:null
    34935     0/imm32/right:null
    34936
    34937 Type-float:  # (payload type-tree)
    34938     0x11/imm32/alloc-id:fake:payload
    34939     1/imm32/is-atom
    34940     0xf/imm32/value:float
    34941     0/imm32/left:unused
    34942     0/imm32/right:null
    34943     0/imm32/right:null
    34944
    34945 == code
    34946 emit-subx-primitive:  # out: (addr buffered-file), stmt: (addr stmt), primitive: (addr primitive), err: (addr buffered-file), ed: (addr exit-descriptor)
    34947     # . prologue
    34948     55/push-ebp
    34949     89/<- %ebp 4/r32/esp
    34950     # . save registers
    34951     50/push-eax
    34952     51/push-ecx
    34953     # ecx = primitive
    34954     8b/-> *(ebp+0x10) 1/r32/ecx
    34955     # emit primitive name
    34956     (emit-indent *(ebp+8) *Curr-block-depth)
    34957     (lookup *(ecx+0x18) *(ecx+0x1c))  # Primitive-subx-name Primitive-subx-name => eax
    34958     (write-buffered *(ebp+8) %eax)
    34959     # emit rm32 if necessary
    34960     (emit-subx-rm32 *(ebp+8) *(ecx+0x20) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))  # Primitive-subx-rm32
    34961     # emit xm32 if necessary
    34962     (emit-subx-rm32 *(ebp+8) *(ecx+0x34) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))  # Primitive-subx-xm32
    34963     # emit r32 if necessary
    34964     (emit-subx-r32 *(ebp+8) *(ecx+0x24) *(ebp+0xc))  # Primitive-subx-r32
    34965     # emit x32 if necessary
    34966     (emit-subx-x32 *(ebp+8) *(ecx+0x38) *(ebp+0xc))  # Primitive-subx-x32
    34967     # emit imm32 if necessary
    34968     (emit-subx-imm32 *(ebp+8) *(ecx+0x28) *(ebp+0xc))  # Primitive-subx-imm32
    34969     # emit imm8 if necessary
    34970     (emit-subx-imm8 *(ebp+8) *(ecx+0x2c) *(ebp+0xc))  # Primitive-subx-imm8
    34971     # emit disp32 if necessary
    34972     (emit-subx-disp32 *(ebp+8) *(ecx+0x30) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))  # Primitive-subx-disp32
    34973     (write-buffered *(ebp+8) Newline)
    34974 $emit-subx-primitive:end:
    34975     # . restore registers
    34976     59/pop-to-ecx
    34977     58/pop-to-eax
    34978     # . epilogue
    34979     89/<- %esp 5/r32/ebp
    34980     5d/pop-to-ebp
    34981     c3/return
    34982
    34983 emit-subx-rm32:  # out: (addr buffered-file), l: arg-location, stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
    34984     # . prologue
    34985     55/push-ebp
    34986     89/<- %ebp 4/r32/esp
    34987     # . save registers
    34988     50/push-eax
    34989     # if (l == 0) return
    34990     81 7/subop/compare *(ebp+0xc) 0/imm32
    34991     74/jump-if-= $emit-subx-rm32:end/disp8
    34992     # var v/eax: (addr stmt-var)
    34993     (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))  # => eax
    34994     (emit-subx-var-as-rm32 *(ebp+8) %eax)
    34995 $emit-subx-rm32:end:
    34996     # . restore registers
    34997     58/pop-to-eax
    34998     # . epilogue
    34999     89/<- %esp 5/r32/ebp
    35000     5d/pop-to-ebp
    35001     c3/return
    35002
    35003 get-stmt-operand-from-arg-location:  # stmt: (addr stmt), l: arg-location, err: (addr buffered-file), ed: (addr exit-descriptor) -> var/eax: (addr stmt-var)
    35004     # . prologue
    35005     55/push-ebp
    35006     89/<- %ebp 4/r32/esp
    35007     # . save registers
    35008     51/push-ecx
    35009     # eax = l
    35010     8b/-> *(ebp+0xc) 0/r32/eax
    35011     # ecx = stmt
    35012     8b/-> *(ebp+8) 1/r32/ecx
    35013     # if (l == 1) return stmt->inouts
    35014     {
    35015       3d/compare-eax-and 1/imm32
    35016       75/jump-if-!= break/disp8
    35017 $get-stmt-operand-from-arg-location:1:
    35018       (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    35019       eb/jump $get-stmt-operand-from-arg-location:end/disp8
    35020     }
    35021     # if (l == 2) return stmt->inouts->next
    35022     {
    35023       3d/compare-eax-and 2/imm32
    35024       75/jump-if-!= break/disp8
    35025 $get-stmt-operand-from-arg-location:2:
    35026       (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    35027       (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    35028       eb/jump $get-stmt-operand-from-arg-location:end/disp8
    35029     }
    35030     # if (l == 3) return stmt->outputs
    35031     {
    35032       3d/compare-eax-and 3/imm32
    35033       75/jump-if-!= break/disp8
    35034 $get-stmt-operand-from-arg-location:3:
    35035       (lookup *(ecx+0x14) *(ecx+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    35036       eb/jump $get-stmt-operand-from-arg-location:end/disp8
    35037     }
    35038     # abort
    35039     e9/jump $get-stmt-operand-from-arg-location:abort/disp32
    35040 $get-stmt-operand-from-arg-location:end:
    35041     # . restore registers
    35042     59/pop-to-ecx
    35043     # . epilogue
    35044     89/<- %esp 5/r32/ebp
    35045     5d/pop-to-ebp
    35046     c3/return
    35047
    35048 $get-stmt-operand-from-arg-location:abort:
    35049     # error("invalid arg-location " eax)
    35050     (write-buffered *(ebp+0x10) "invalid arg-location ")
    35051     (write-int32-hex-buffered *(ebp+0x10) %eax)
    35052     (write-buffered *(ebp+0x10) Newline)
    35053     (flush *(ebp+0x10))
    35054     (stop *(ebp+0x14) 1)
    35055     # never gets here
    35056
    35057 emit-subx-r32:  # out: (addr buffered-file), l: arg-location, stmt: (addr stmt)
    35058     # . prologue
    35059     55/push-ebp
    35060     89/<- %ebp 4/r32/esp
    35061     # . save registers
    35062     50/push-eax
    35063     51/push-ecx
    35064     # if (l == 0) return
    35065     81 7/subop/compare *(ebp+0xc) 0/imm32
    35066     0f 84/jump-if-= $emit-subx-r32:end/disp32
    35067     # var v/eax: (addr stmt-var)
    35068     (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc))  # => eax
    35069     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    35070     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    35071 #?     (write-buffered Stderr "looking up ")
    35072 #?     (write-buffered Stderr %eax)
    35073 #?     (write-buffered Stderr Newline)
    35074 #?     (flush Stderr)
    35075     (maybe-get Mu-registers %eax 0xc)  # => eax: (addr register-index)
    35076     (write-buffered *(ebp+8) Space)
    35077     (write-int32-hex-buffered *(ebp+8) *eax)
    35078     (write-buffered *(ebp+8) "/r32")
    35079 $emit-subx-r32:end:
    35080     # . restore registers
    35081     59/pop-to-ecx
    35082     58/pop-to-eax
    35083     # . epilogue
    35084     89/<- %esp 5/r32/ebp
    35085     5d/pop-to-ebp
    35086     c3/return
    35087
    35088 emit-subx-x32:  # out: (addr buffered-file), l: arg-location, stmt: (addr stmt)
    35089     # . prologue
    35090     55/push-ebp
    35091     89/<- %ebp 4/r32/esp
    35092     # . save registers
    35093     50/push-eax
    35094     51/push-ecx
    35095     # if (l == 0) return
    35096     81 7/subop/compare *(ebp+0xc) 0/imm32
    35097     0f 84/jump-if-= $emit-subx-x32:end/disp32
    35098     # var v/eax: (addr stmt-var)
    35099     (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc))  # => eax
    35100     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    35101     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    35102 #?     (write-buffered Stderr "looking up ")
    35103 #?     (write-buffered Stderr %eax)
    35104 #?     (write-buffered Stderr Newline)
    35105 #?     (flush Stderr)
    35106     (maybe-get Mu-registers %eax 0xc)  # => eax: (addr register-index)
    35107     (write-buffered *(ebp+8) Space)
    35108     (write-int32-hex-buffered *(ebp+8) *eax)
    35109     (write-buffered *(ebp+8) "/x32")
    35110 $emit-subx-x32:end:
    35111     # . restore registers
    35112     59/pop-to-ecx
    35113     58/pop-to-eax
    35114     # . epilogue
    35115     89/<- %esp 5/r32/ebp
    35116     5d/pop-to-ebp
    35117     c3/return
    35118
    35119 emit-subx-imm32:  # out: (addr buffered-file), l: arg-location, stmt: (addr stmt)
    35120     # . prologue
    35121     55/push-ebp
    35122     89/<- %ebp 4/r32/esp
    35123     # . save registers
    35124     50/push-eax
    35125     51/push-ecx
    35126     # if (l == 0) return
    35127     81 7/subop/compare *(ebp+0xc) 0/imm32
    35128     0f 84/jump-if-= $emit-subx-imm32:end/disp32
    35129     # var v/eax: (handle var)
    35130     (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc))  # => eax
    35131     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    35132     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    35133     (write-buffered *(ebp+8) Space)
    35134     (write-buffered *(ebp+8) %eax)
    35135     (write-buffered *(ebp+8) "/imm32")
    35136 $emit-subx-imm32:end:
    35137     # . restore registers
    35138     59/pop-to-ecx
    35139     58/pop-to-eax
    35140     # . epilogue
    35141     89/<- %esp 5/r32/ebp
    35142     5d/pop-to-ebp
    35143     c3/return
    35144
    35145 emit-subx-imm8:  # out: (addr buffered-file), l: arg-location, stmt: (addr stmt)
    35146     # . prologue
    35147     55/push-ebp
    35148     89/<- %ebp 4/r32/esp
    35149     # . save registers
    35150     50/push-eax
    35151     51/push-ecx
    35152     # if (l == 0) return
    35153     81 7/subop/compare *(ebp+0xc) 0/imm32
    35154     0f 84/jump-if-= $emit-subx-imm32:end/disp32
    35155     # var v/eax: (handle var)
    35156     (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc))  # => eax
    35157     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    35158     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    35159     (write-buffered *(ebp+8) Space)
    35160     (write-buffered *(ebp+8) %eax)
    35161     (write-buffered *(ebp+8) "/imm8")
    35162 $emit-subx-imm8:end:
    35163     # . restore registers
    35164     59/pop-to-ecx
    35165     58/pop-to-eax
    35166     # . epilogue
    35167     89/<- %esp 5/r32/ebp
    35168     5d/pop-to-ebp
    35169     c3/return
    35170
    35171 emit-subx-disp32:  # out: (addr buffered-file), l: arg-location, stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
    35172     # . prologue
    35173     55/push-ebp
    35174     89/<- %ebp 4/r32/esp
    35175     # . save registers
    35176     50/push-eax
    35177     51/push-ecx
    35178     # if (location == 0) return
    35179     81 7/subop/compare *(ebp+0xc) 0/imm32
    35180     0f 84/jump-if-= $emit-subx-disp32:end/disp32
    35181     # var v/eax: (addr stmt-var)
    35182     (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))  # => eax
    35183     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    35184     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    35185     (write-buffered *(ebp+8) Space)
    35186     (write-buffered *(ebp+8) %eax)
    35187     # hack: if instruction operation starts with "break", emit ":break"
    35188     # var name/ecx: (addr array byte) = lookup(stmt->operation)
    35189     8b/-> *(ebp+0x10) 0/r32/eax
    35190     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
    35191     89/<- %ecx 0/r32/eax
    35192     {
    35193       (string-starts-with? %ecx "break")  # => eax
    35194       3d/compare-eax-and 0/imm32/false
    35195       74/jump-if-= break/disp8
    35196       (write-buffered *(ebp+8) ":break")
    35197     }
    35198     # hack: if instruction operation starts with "loop", emit ":loop"
    35199     {
    35200       (string-starts-with? %ecx "loop")  # => eax
    35201       3d/compare-eax-and 0/imm32/false
    35202       74/jump-if-= break/disp8
    35203       (write-buffered *(ebp+8) ":loop")
    35204     }
    35205     (write-buffered *(ebp+8) "/disp32")
    35206 $emit-subx-disp32:end:
    35207     # . restore registers
    35208     59/pop-to-ecx
    35209     58/pop-to-eax
    35210     # . epilogue
    35211     89/<- %esp 5/r32/ebp
    35212     5d/pop-to-ebp
    35213     c3/return
    35214
    35215 emit-call:  # out: (addr buffered-file), stmt: (addr stmt)
    35216     # . prologue
    35217     55/push-ebp
    35218     89/<- %ebp 4/r32/esp
    35219     # . save registers
    35220     50/push-eax
    35221     51/push-ecx
    35222     #
    35223     (emit-indent *(ebp+8) *Curr-block-depth)
    35224     (write-buffered *(ebp+8) "(")
    35225     # ecx = stmt
    35226     8b/-> *(ebp+0xc) 1/r32/ecx
    35227     # - emit function name
    35228     (lookup *(ecx+4) *(ecx+8))  # Stmt1-operation Stmt1-operation => eax
    35229     (write-buffered *(ebp+8) %eax)
    35230     # - emit arguments
    35231     # var curr/eax: (addr stmt-var) = lookup(stmt->inouts)
    35232     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    35233     {
    35234       # if (curr == null) break
    35235       3d/compare-eax-and 0/imm32
    35236       74/jump-if-= break/disp8
    35237       #
    35238       (emit-subx-call-operand *(ebp+8) %eax)
    35239       # curr = lookup(curr->next)
    35240       (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    35241       eb/jump loop/disp8
    35242     }
    35243     #
    35244     (write-buffered *(ebp+8) ")\n")
    35245 $emit-call:end:
    35246     # . restore registers
    35247     59/pop-to-ecx
    35248     58/pop-to-eax
    35249     # . epilogue
    35250     89/<- %esp 5/r32/ebp
    35251     5d/pop-to-ebp
    35252     c3/return
    35253
    35254 emit-subx-call-operand:  # out: (addr buffered-file), s: (addr stmt-var)
    35255     # shares code with emit-subx-var-as-rm32
    35256     # . prologue
    35257     55/push-ebp
    35258     89/<- %ebp 4/r32/esp
    35259     # . save registers
    35260     50/push-eax
    35261     51/push-ecx
    35262     56/push-esi
    35263     # ecx = s
    35264     8b/-> *(ebp+0xc) 1/r32/ecx
    35265     # var operand/esi: (addr var) = lookup(s->value)
    35266     (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
    35267     89/<- %esi 0/r32/eax
    35268     # if (operand->register && !s->is-deref?) emit "%__"
    35269     {
    35270 $emit-subx-call-operand:check-for-register-direct:
    35271       81 7/subop/compare *(esi+0x18) 0/imm32  # Var-register
    35272       74/jump-if-= break/disp8
    35273       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
    35274       75/jump-if-!= break/disp8
    35275 $emit-subx-call-operand:register-direct:
    35276       (write-buffered *(ebp+8) " %")
    35277       (lookup *(esi+0x18) *(esi+0x1c))  # Var-register Var-register => eax
    35278       (write-buffered *(ebp+8) %eax)
    35279       e9/jump $emit-subx-call-operand:end/disp32
    35280     }
    35281     # else if (operand->register && s->is-deref?) emit "*__"
    35282     {
    35283 $emit-subx-call-operand:check-for-register-indirect:
    35284       81 7/subop/compare *(esi+0x18) 0/imm32  # Var-register
    35285       74/jump-if-= break/disp8
    35286       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
    35287       74/jump-if-= break/disp8
    35288 $emit-subx-call-operand:register-indirect:
    35289       (emit-subx-call-operand-register-indirect *(ebp+8) %esi)
    35290       e9/jump $emit-subx-call-operand:end/disp32
    35291     }
    35292     # else if (operand->stack-offset) emit "*(ebp+__)"
    35293     {
    35294       81 7/subop/compare *(esi+0x14) 0/imm32  # Var-offset
    35295       74/jump-if-= break/disp8
    35296 $emit-subx-call-operand:stack:
    35297       (emit-subx-call-operand-stack *(ebp+8) %esi)
    35298       e9/jump $emit-subx-call-operand:end/disp32
    35299     }
    35300     # else if (operand->type == literal) emit "__"
    35301     {
    35302       (lookup *(esi+8) *(esi+0xc))  # Var-type Var-type => eax
    35303       81 7/subop/compare *(eax+4) 0/imm32  # Type-tree-value
    35304       75/jump-if-!= break/disp8
    35305 $emit-subx-call-operand:literal:
    35306       (write-buffered *(ebp+8) Space)
    35307       (lookup *esi *(esi+4))  # Var-name Var-name => eax
    35308       (write-buffered *(ebp+8) %eax)
    35309       e9/jump $emit-subx-call-operand:end/disp32
    35310     }
    35311     # else if (operand->type == literal-string) emit "__"
    35312     {
    35313       (lookup *(esi+8) *(esi+0xc))  # Var-type Var-type => eax
    35314       81 7/subop/compare *(eax+4) 0x10/imm32  # Type-tree-value
    35315       75/jump-if-!= break/disp8
    35316 $emit-subx-call-operand:literal-string:
    35317       (write-buffered *(ebp+8) Space)
    35318       (lookup *esi *(esi+4))  # Var-name Var-name => eax
    35319       (write-buffered *(ebp+8) %eax)
    35320     }
    35321 $emit-subx-call-operand:end:
    35322     # . restore registers
    35323     5e/pop-to-esi
    35324     59/pop-to-ecx
    35325     58/pop-to-eax
    35326     # . epilogue
    35327     89/<- %esp 5/r32/ebp
    35328     5d/pop-to-ebp
    35329     c3/return
    35330
    35331 emit-subx-call-operand-register-indirect:  # out: (addr buffered-file), v: (addr var)
    35332     # . prologue
    35333     55/push-ebp
    35334     89/<- %ebp 4/r32/esp
    35335     # . save registers
    35336     50/push-eax
    35337     51/push-ecx
    35338     56/push-esi
    35339     # esi = v
    35340     8b/-> *(ebp+0xc) 6/r32/esi
    35341     # var size/ecx: int = size-of-deref(v)
    35342     (size-of-deref %esi)  # => eax
    35343     89/<- %ecx 0/r32/eax
    35344     # var reg-name/esi: (addr array byte) = lookup(v->register)
    35345     (lookup *(esi+0x18) *(esi+0x1c))  # Var-register Var-register => eax
    35346     89/<- %esi 0/r32/eax
    35347     # TODO: assert size is a multiple of 4
    35348     # var i/eax: int = 0
    35349     b8/copy-to-eax 0/imm32
    35350     {
    35351 $emit-subx-call-operand-register-indirect:loop:
    35352       # if (i >= size) break
    35353       39/compare %eax 1/r32/ecx
    35354       7d/jump-if->= break/disp8
    35355       # emit " *(" v->register "+" i ")"
    35356       (write-buffered *(ebp+8) " *(")
    35357       (write-buffered *(ebp+8) %esi)
    35358       (write-buffered *(ebp+8) "+")
    35359       (write-int32-hex-buffered *(ebp+8) %eax)
    35360       (write-buffered *(ebp+8) ")")
    35361       # i += 4
    35362       05/add-to-eax 4/imm32
    35363       #
    35364       eb/jump loop/disp8
    35365     }
    35366 $emit-subx-call-operand-register-indirect:end:
    35367     # . restore registers
    35368     5e/pop-to-esi
    35369     59/pop-to-ecx
    35370     58/pop-to-eax
    35371     # . epilogue
    35372     89/<- %esp 5/r32/ebp
    35373     5d/pop-to-ebp
    35374     c3/return
    35375
    35376 emit-subx-call-operand-stack:  # out: (addr buffered-file), v: (addr var)
    35377     # . prologue
    35378     55/push-ebp
    35379     89/<- %ebp 4/r32/esp
    35380     # . save registers
    35381     50/push-eax
    35382     51/push-ecx
    35383     56/push-esi
    35384     # esi = v
    35385     8b/-> *(ebp+0xc) 6/r32/esi
    35386     # var curr/ecx: int = v->offset
    35387     8b/-> *(esi+0x14) 1/r32/ecx  # Var-offset
    35388     # var max/eax: int = v->offset + size-of(v)
    35389     (size-of %esi)  # => eax
    35390     # TODO: assert size is a multiple of 4
    35391     01/add-to %eax 1/r32/ecx
    35392     {
    35393 $emit-subx-call-operand-stack:loop:
    35394       # if (curr >= max) break
    35395       39/compare %ecx 0/r32/eax
    35396       7d/jump-if->= break/disp8
    35397       # emit " *(ebp+" curr ")"
    35398       (write-buffered *(ebp+8) " *(ebp+")
    35399       (write-int32-hex-buffered *(ebp+8) %ecx)
    35400       (write-buffered *(ebp+8) ")")
    35401       # i += 4
    35402       81 0/subop/add %ecx 4/imm32
    35403       #
    35404       eb/jump loop/disp8
    35405     }
    35406 $emit-subx-call-operand-stack:end:
    35407     # . restore registers
    35408     5e/pop-to-esi
    35409     59/pop-to-ecx
    35410     58/pop-to-eax
    35411     # . epilogue
    35412     89/<- %esp 5/r32/ebp
    35413     5d/pop-to-ebp
    35414     c3/return
    35415
    35416 emit-subx-var-as-rm32:  # out: (addr buffered-file), s: (addr stmt-var)
    35417     # . prologue
    35418     55/push-ebp
    35419     89/<- %ebp 4/r32/esp
    35420     # . save registers
    35421     50/push-eax
    35422     51/push-ecx
    35423     56/push-esi
    35424     # ecx = s
    35425     8b/-> *(ebp+0xc) 1/r32/ecx
    35426     # var operand/esi: (addr var) = lookup(s->value)
    35427     (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
    35428     89/<- %esi 0/r32/eax
    35429     # if (operand->register && s->is-deref?) emit "*__"
    35430     {
    35431 $emit-subx-var-as-rm32:check-for-register-indirect:
    35432       81 7/subop/compare *(esi+0x18) 0/imm32  # Var-register
    35433       74/jump-if-= break/disp8
    35434       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
    35435       74/jump-if-= break/disp8
    35436 $emit-subx-var-as-rm32:register-indirect:
    35437       (write-buffered *(ebp+8) " *")
    35438       (lookup *(esi+0x18) *(esi+0x1c))  # Var-register Var-register => eax
    35439       (write-buffered *(ebp+8) %eax)
    35440       e9/jump $emit-subx-var-as-rm32:end/disp32
    35441     }
    35442     # if (operand->register && !s->is-deref?) emit "%__"
    35443     {
    35444 $emit-subx-var-as-rm32:check-for-register-direct:
    35445       81 7/subop/compare *(esi+0x18) 0/imm32  # Var-register
    35446       74/jump-if-= break/disp8
    35447       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
    35448       75/jump-if-!= break/disp8
    35449 $emit-subx-var-as-rm32:register-direct:
    35450       (write-buffered *(ebp+8) " %")
    35451       (lookup *(esi+0x18) *(esi+0x1c))  # Var-register Var-register => eax
    35452       (write-buffered *(ebp+8) %eax)
    35453       e9/jump $emit-subx-var-as-rm32:end/disp32
    35454     }
    35455     # else if (operand->stack-offset) emit "*(ebp+__)"
    35456     {
    35457       81 7/subop/compare *(esi+0x14) 0/imm32  # Var-offset
    35458       74/jump-if-= break/disp8
    35459 $emit-subx-var-as-rm32:stack:
    35460       (write-buffered *(ebp+8) Space)
    35461       (write-buffered *(ebp+8) "*(ebp+")
    35462       (write-int32-hex-buffered *(ebp+8) *(esi+0x14))  # Var-offset
    35463       (write-buffered *(ebp+8) ")")
    35464     }
    35465 $emit-subx-var-as-rm32:end:
    35466     # . restore registers
    35467     5e/pop-to-esi
    35468     59/pop-to-ecx
    35469     58/pop-to-eax
    35470     # . epilogue
    35471     89/<- %esp 5/r32/ebp
    35472     5d/pop-to-ebp
    35473     c3/return
    35474
    35475 find-matching-primitive:  # primitives: (addr primitive), stmt: (addr stmt) -> result/eax: (addr primitive)
    35476     # . prologue
    35477     55/push-ebp
    35478     89/<- %ebp 4/r32/esp
    35479     # . save registers
    35480     51/push-ecx
    35481     # var curr/ecx: (addr primitive) = primitives
    35482     8b/-> *(ebp+8) 1/r32/ecx
    35483     {
    35484 $find-matching-primitive:loop:
    35485       # if (curr == null) break
    35486       81 7/subop/compare %ecx 0/imm32
    35487       74/jump-if-= break/disp8
    35488       # if match(curr, stmt) return curr
    35489       {
    35490         (mu-stmt-matches-primitive? *(ebp+0xc) %ecx)  # => eax
    35491         3d/compare-eax-and 0/imm32/false
    35492         74/jump-if-= break/disp8
    35493         89/<- %eax 1/r32/ecx
    35494         eb/jump $find-matching-primitive:end/disp8
    35495       }
    35496 $find-matching-primitive:next-primitive:
    35497       # curr = curr->next
    35498       (lookup *(ecx+0x3c) *(ecx+0x40))  # Primitive-next Primitive-next => eax
    35499       89/<- %ecx 0/r32/eax
    35500       #
    35501       e9/jump loop/disp32
    35502     }
    35503     # return null
    35504     b8/copy-to-eax 0/imm32
    35505 $find-matching-primitive:end:
    35506     # . restore registers
    35507     59/pop-to-ecx
    35508     # . epilogue
    35509     89/<- %esp 5/r32/ebp
    35510     5d/pop-to-ebp
    35511     c3/return
    35512
    35513 mu-stmt-matches-primitive?:  # stmt: (addr stmt), primitive: (addr primitive) -> result/eax: boolean
    35514     # A mu stmt matches a primitive if the name matches, all the inout vars
    35515     # match, and all the output vars match.
    35516     # Vars match if types match and registers match.
    35517     # In addition, a stmt output matches a primitive's output if types match
    35518     # and the primitive has a wildcard register.
    35519     # . prologue
    35520     55/push-ebp
    35521     89/<- %ebp 4/r32/esp
    35522     # . save registers
    35523     51/push-ecx
    35524     52/push-edx
    35525     53/push-ebx
    35526     56/push-esi
    35527     57/push-edi
    35528     # ecx = stmt
    35529     8b/-> *(ebp+8) 1/r32/ecx
    35530     # edx = primitive
    35531     8b/-> *(ebp+0xc) 2/r32/edx
    35532     {
    35533 $mu-stmt-matches-primitive?:check-name:
    35534       # if (primitive->name != stmt->operation) return false
    35535       # . var esi: (addr array byte) = lookup(stmt->operation)
    35536       (lookup *(ecx+4) *(ecx+8))  # Stmt1-operation Stmt1-operation => eax
    35537       89/<- %esi 0/r32/eax
    35538       # . var edi: (addr array byte) = lookup(primitive->name)
    35539       (lookup *edx *(edx+4))  # Primitive-name Primitive-name => eax
    35540 #?       (write-buffered Stderr %eax)
    35541 #?       (write-buffered Stderr Newline)
    35542 #?       (flush Stderr)
    35543       89/<- %edi 0/r32/eax
    35544       (string-equal? %esi %edi)  # => eax
    35545       3d/compare-eax-and 0/imm32/false
    35546       75/jump-if-!= break/disp8
    35547       b8/copy-to-eax 0/imm32
    35548       e9/jump $mu-stmt-matches-primitive?:end/disp32
    35549     }
    35550     # var curr/esi: (addr stmt-var) = lookup(stmt->inouts)
    35551     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    35552     89/<- %esi 0/r32/eax
    35553     # var curr2/edi: (addr list var) = lookup(primitive->inouts)
    35554     (lookup *(edx+8) *(edx+0xc))  # Primitive-inouts Primitive-inouts => eax
    35555     89/<- %edi 0/r32/eax
    35556     {
    35557 $mu-stmt-matches-primitive?:inouts-loop:
    35558       # if (curr == 0 && curr2 == 0) move on to check outputs
    35559       {
    35560 $mu-stmt-matches-primitive?:check-both-inouts-null:
    35561         81 7/subop/compare %esi 0/imm32
    35562         75/jump-if-!= break/disp8
    35563 $mu-stmt-matches-primitive?:stmt-inout-null:
    35564         81 7/subop/compare %edi 0/imm32
    35565         0f 84/jump-if-= $mu-stmt-matches-primitive?:check-outputs/disp32
    35566 $mu-stmt-matches-primitive?:stmt-inout-null-and-prim-inout-not-null:
    35567         # return false
    35568         b8/copy-to-eax 0/imm32/false
    35569         e9/jump $mu-stmt-matches-primitive?:end/disp32
    35570       }
    35571       # if (curr2 == 0) return false
    35572       {
    35573 $mu-stmt-matches-primitive?:check-prim-inout-null:
    35574         81 7/subop/compare %edi 0/imm32
    35575         75/jump-if-!= break/disp8
    35576 $mu-stmt-matches-primitive?:prim-inout-null:
    35577         b8/copy-to-eax 0/imm32/false
    35578         e9/jump $mu-stmt-matches-primitive?:end/disp32
    35579       }
    35580       # if (curr != curr2) return false
    35581       {
    35582 $mu-stmt-matches-primitive?:check-inouts-match:
    35583         (lookup *edi *(edi+4))  # List-value List-value => eax
    35584         (operand-matches-primitive? %esi %eax)  # => eax
    35585         3d/compare-eax-and 0/imm32/false
    35586         75/jump-if-!= break/disp8
    35587 $mu-stmt-matches-primitive?:inouts-match:
    35588         b8/copy-to-eax 0/imm32/false
    35589         e9/jump $mu-stmt-matches-primitive?:end/disp32
    35590       }
    35591 $mu-stmt-matches-primitive?:next-inout:
    35592       # curr = lookup(curr->next)
    35593       (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
    35594       89/<- %esi 0/r32/eax
    35595       # curr2 = lookup(curr2->next)
    35596       (lookup *(edi+8) *(edi+0xc))  # List-next List-next => eax
    35597       89/<- %edi 0/r32/eax
    35598       #
    35599       e9/jump loop/disp32
    35600     }
    35601 $mu-stmt-matches-primitive?:check-outputs:
    35602     # var curr/esi: (addr stmt-var) = lookup(stmt->outputs)
    35603     (lookup *(ecx+0x14) *(ecx+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    35604     89/<- %esi 0/r32/eax
    35605     # var curr2/edi: (addr list var) = lookup(primitive->outputs)
    35606     (lookup *(edx+0x10) *(edx+0x14))  # Primitive-outputs Primitive-outputs => eax
    35607     89/<- %edi 0/r32/eax
    35608     {
    35609 $mu-stmt-matches-primitive?:outputs-loop:
    35610       # if (curr == 0) return (curr2 == 0)
    35611       {
    35612 $mu-stmt-matches-primitive?:check-both-outputs-null:
    35613         81 7/subop/compare %esi 0/imm32
    35614         75/jump-if-!= break/disp8
    35615         {
    35616 $mu-stmt-matches-primitive?:stmt-output-null:
    35617           81 7/subop/compare %edi 0/imm32
    35618           75/jump-if-!= break/disp8
    35619 $mu-stmt-matches-primitive?:both-outputs-null:
    35620           # return true
    35621           b8/copy-to-eax 1/imm32
    35622           e9/jump $mu-stmt-matches-primitive?:end/disp32
    35623         }
    35624 $mu-stmt-matches-primitive?:stmt-output-null-and-prim-output-not-null:
    35625         # return false
    35626         b8/copy-to-eax 0/imm32
    35627         e9/jump $mu-stmt-matches-primitive?:end/disp32
    35628       }
    35629       # if (curr2 == 0) return false
    35630       {
    35631 $mu-stmt-matches-primitive?:check-prim-output-null:
    35632         81 7/subop/compare %edi 0/imm32
    35633         75/jump-if-!= break/disp8
    35634 $mu-stmt-matches-primitive?:prim-output-is-null:
    35635         b8/copy-to-eax 0/imm32
    35636         e9/jump $mu-stmt-matches-primitive?:end/disp32
    35637       }
    35638       # if (curr != curr2) return false
    35639       {
    35640 $mu-stmt-matches-primitive?:check-outputs-match:
    35641         (lookup *edi *(edi+4))  # List-value List-value => eax
    35642         (operand-matches-primitive? %esi %eax)  # => eax
    35643         3d/compare-eax-and 0/imm32/false
    35644         75/jump-if-!= break/disp8
    35645 $mu-stmt-matches-primitive?:outputs-match:
    35646         b8/copy-to-eax 0/imm32
    35647         e9/jump $mu-stmt-matches-primitive?:end/disp32
    35648       }
    35649 $mu-stmt-matches-primitive?:next-output:
    35650       # curr = lookup(curr->next)
    35651       (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
    35652       89/<- %esi 0/r32/eax
    35653       # curr2 = lookup(curr2->next)
    35654       (lookup *(edi+8) *(edi+0xc))  # List-next List-next => eax
    35655       89/<- %edi 0/r32/eax
    35656       #
    35657       e9/jump loop/disp32
    35658     }
    35659 $mu-stmt-matches-primitive?:return-true:
    35660     b8/copy-to-eax 1/imm32
    35661 $mu-stmt-matches-primitive?:end:
    35662     # . restore registers
    35663     5f/pop-to-edi
    35664     5e/pop-to-esi
    35665     5b/pop-to-ebx
    35666     5a/pop-to-edx
    35667     59/pop-to-ecx
    35668     # . epilogue
    35669     89/<- %esp 5/r32/ebp
    35670     5d/pop-to-ebp
    35671     c3/return
    35672
    35673 operand-matches-primitive?:  # s: (addr stmt-var), prim-var: (addr var) -> result/eax: boolean
    35674     # . prologue
    35675     55/push-ebp
    35676     89/<- %ebp 4/r32/esp
    35677     # . save registers
    35678     51/push-ecx
    35679     52/push-edx
    35680     53/push-ebx
    35681     56/push-esi
    35682     57/push-edi
    35683     # ecx = s
    35684     8b/-> *(ebp+8) 1/r32/ecx
    35685     # var var/esi: (addr var) = lookup(s->value)
    35686     (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
    35687     89/<- %esi 0/r32/eax
    35688     # edi = prim-var
    35689     8b/-> *(ebp+0xc) 7/r32/edi
    35690 $operand-matches-primitive?:check-type:
    35691     # if !category-match?(var->type, prim-var->type) return false
    35692     # . var vtype/ebx: (addr type-tree) = lookup(var->type)
    35693     (lookup *(esi+8) *(esi+0xc))  # Var-type Var-type => eax
    35694     89/<- %ebx 0/r32/eax
    35695     # . if s is deref, vtype = vtype->right
    35696     {
    35697       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
    35698       74/jump-if-= break/disp8
    35699 $operand-matches-primitive?:is-deref:
    35700       # . var t/eax: (addr type)
    35701       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
    35702       # . if !t->is-atom? t = t->left
    35703       81 7/subop/compare *eax 0/imm32/false
    35704       {
    35705         75/jump-if-!= break/disp8
    35706         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    35707       }
    35708       # .
    35709       89/<- %ebx 0/r32/eax
    35710     }
    35711     # . var ptype/eax: (addr type-tree) = lookup(prim-var->type)
    35712     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
    35713     (subx-type-category-match? %ebx %eax)  # => eax
    35714     3d/compare-eax-and 0/imm32/false
    35715     0f 84/jump-if-= $operand-matches-primitive?:return-false/disp32
    35716     {
    35717 $operand-matches-primitive?:check-register:
    35718       # if prim-var is in memory and var is in register but dereference, match
    35719       {
    35720         81 7/subop/compare *(edi+0x18) 0/imm32  # Var-register
    35721         0f 85/jump-if-!= break/disp32
    35722         81 7/subop/compare *(esi+0x18) 0/imm32  # Var-register
    35723         74/jump-if-= break/disp8
    35724         81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
    35725         74/jump-if-= break/disp8
    35726 $operand-matches-primitive?:var-deref-match:
    35727         e9/jump $operand-matches-primitive?:return-true/disp32
    35728       }
    35729       # if prim-var is in register and var is in register but dereference, no match
    35730       {
    35731         81 7/subop/compare *(edi+0x18) 0/imm32  # Var-register
    35732         0f 84/jump-if-= break/disp32
    35733         81 7/subop/compare *(esi+0x18) 0/imm32  # Var-register
    35734         0f 84/jump-if-= break/disp32
    35735         81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
    35736         74/jump-if-= break/disp8
    35737 $operand-matches-primitive?:var-deref-no-match:
    35738         e9/jump $operand-matches-primitive?:return-false/disp32
    35739       }
    35740       # return false if var->register doesn't match prim-var->register
    35741       {
    35742         # if register addresses are equal, it's a match
    35743         # var vreg/ebx: (addr array byte) = lookup(var->register)
    35744         (lookup *(esi+0x18) *(esi+0x1c))  # Var-register Var-register => eax
    35745         89/<- %ebx 0/r32/eax
    35746         # var preg/ecx: (addr array byte) = lookup(prim-var->register)
    35747         (lookup *(edi+0x18) *(edi+0x1c))  # Var-register Var-register => eax
    35748         89/<- %ecx 0/r32/eax
    35749         # if (vreg == preg) break
    35750         39/compare %ecx 3/r32/ebx
    35751         74/jump-if-= break/disp8
    35752 $operand-matches-primitive?:var-register-no-match:
    35753         # if either address is 0, return false
    35754         81 7/subop/compare %ebx 0/imm32
    35755         74/jump-if-=  $operand-matches-primitive?:return-false/disp8
    35756         81 7/subop/compare %ecx 0/imm32
    35757         74/jump-if-=  $operand-matches-primitive?:return-false/disp8
    35758         # if prim-var->register is wildcard, it's a match
    35759         (string-equal? %ecx "*")  # Any-register => eax
    35760         3d/compare-eax-and 0/imm32/false
    35761         75/jump-if-!= break/disp8
    35762 $operand-matches-primitive?:wildcard-no-match:
    35763         # if string contents aren't equal, return false
    35764         (string-equal? %ecx %ebx)  # => eax
    35765         3d/compare-eax-and 0/imm32/false
    35766         74/jump-if-= $operand-matches-primitive?:return-false/disp8
    35767       }
    35768     }
    35769 $operand-matches-primitive?:return-true:
    35770     b8/copy-to-eax 1/imm32/true
    35771     eb/jump $operand-matches-primitive?:end/disp8
    35772 $operand-matches-primitive?:return-false:
    35773     b8/copy-to-eax 0/imm32/false
    35774 $operand-matches-primitive?:end:
    35775     # . restore registers
    35776     5f/pop-to-edi
    35777     5e/pop-to-esi
    35778     5b/pop-to-ebx
    35779     5a/pop-to-edx
    35780     59/pop-to-ecx
    35781     # . epilogue
    35782     89/<- %esp 5/r32/ebp
    35783     5d/pop-to-ebp
    35784     c3/return
    35785
    35786 find-matching-function:  # functions: (addr function), stmt: (addr stmt) -> result/eax: (addr function)
    35787     # . prologue
    35788     55/push-ebp
    35789     89/<- %ebp 4/r32/esp
    35790     # . save registers
    35791     51/push-ecx
    35792     # var curr/ecx: (handle function) = functions
    35793     8b/-> *(ebp+8) 1/r32/ecx
    35794     {
    35795       # if (curr == null) break
    35796       81 7/subop/compare %ecx 0/imm32
    35797       74/jump-if-= break/disp8
    35798 #?       (write-buffered Stderr "iter\n")
    35799 #?       (flush Stderr)
    35800       # if match(stmt, curr) return curr
    35801       {
    35802         (mu-stmt-matches-function? *(ebp+0xc) %ecx)  # => eax
    35803         3d/compare-eax-and 0/imm32/false
    35804         74/jump-if-= break/disp8
    35805         89/<- %eax 1/r32/ecx
    35806         eb/jump $find-matching-function:end/disp8
    35807       }
    35808       # curr = curr->next
    35809       (lookup *(ecx+0x20) *(ecx+0x24))  # Function-next Function-next => eax
    35810       89/<- %ecx 0/r32/eax
    35811       #
    35812       eb/jump loop/disp8
    35813     }
    35814     # return null
    35815     b8/copy-to-eax 0/imm32
    35816 $find-matching-function:end:
    35817     # . restore registers
    35818     59/pop-to-ecx
    35819     # . epilogue
    35820     89/<- %esp 5/r32/ebp
    35821     5d/pop-to-ebp
    35822     c3/return
    35823
    35824 # Just compare names; user-defined functions don't support overloading yet.
    35825 mu-stmt-matches-function?:  # stmt: (addr stmt1), function: (addr function) -> result/eax: boolean
    35826     # . prologue
    35827     55/push-ebp
    35828     89/<- %ebp 4/r32/esp
    35829     # . save registers
    35830     51/push-ecx
    35831     # return function->name == stmt->operation
    35832     # ecx = lookup(stmt->operation)
    35833     8b/-> *(ebp+8) 0/r32/eax
    35834     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
    35835     89/<- %ecx 0/r32/eax
    35836     # eax = lookup(function->name)
    35837     8b/-> *(ebp+0xc) 0/r32/eax
    35838     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    35839     (string-equal? %eax %ecx)  # => eax
    35840 $mu-stmt-matches-function?:end:
    35841     # . restore registers
    35842     59/pop-to-ecx
    35843     # . epilogue
    35844     89/<- %esp 5/r32/ebp
    35845     5d/pop-to-ebp
    35846     c3/return
    35847
    35848 # Type-checking happens elsewhere. This method is for selecting between
    35849 # primitives.
    35850 subx-type-category-match?:  # a: (addr type-tree), b: (addr type-tree) -> result/eax: boolean
    35851     # . prologue
    35852     55/push-ebp
    35853     89/<- %ebp 4/r32/esp
    35854     # . save registers
    35855     51/push-ecx
    35856     # var cata/ecx: int = type-category(a)
    35857     (type-category *(ebp+8))  # => eax
    35858     89/<- %ecx 0/r32/eax
    35859     # var catb/eax: int = type-category(b)
    35860     (type-category *(ebp+0xc))  # => eax
    35861     # return cata == catb
    35862     39/compare %eax 1/r32/ecx
    35863     0f 94/set-byte-if-= %al
    35864     81 4/subop/and %eax 0xff/imm32
    35865 $subx-type-category-match?:end:
    35866     # . restore registers
    35867     59/pop-to-ecx
    35868     # . epilogue
    35869     89/<- %esp 5/r32/ebp
    35870     5d/pop-to-ebp
    35871     c3/return
    35872
    35873 type-category:  # a: (addr type-tree) -> result/eax: int
    35874     # . prologue
    35875     55/push-ebp
    35876     89/<- %ebp 4/r32/esp
    35877     # . save registers
    35878     51/push-ecx
    35879     # var lit?/ecx: boolean = literal-type?(a)
    35880     (simple-mu-type? *(ebp+8) 0)  # literal => eax
    35881     89/<- %ecx 0/r32/eax
    35882     # var float?/eax: int = float?(a)
    35883     (simple-mu-type? *(ebp+8) 0xf)  # => eax
    35884     # set bits for lit? and float?
    35885     c1/shift 4/subop/left %ecx 1/imm8
    35886     09/or %eax 1/r32/ecx
    35887 $type-category:end:
    35888     # . restore registers
    35889     59/pop-to-ecx
    35890     # . epilogue
    35891     89/<- %esp 5/r32/ebp
    35892     5d/pop-to-ebp
    35893     c3/return
    35894
    35895 simple-mu-type?:  # a: (addr type-tree), n: type-id -> result/eax: boolean
    35896     # . prologue
    35897     55/push-ebp
    35898     89/<- %ebp 4/r32/esp
    35899     # . save registers
    35900     51/push-ecx
    35901     # ecx = n
    35902     8b/-> *(ebp+0xc) 1/r32/ecx
    35903     # return (a->value == n)
    35904     8b/-> *(ebp+8) 0/r32/eax
    35905     39/compare *(eax+4) 1/r32/ecx  # Type-tree-value
    35906     0f 94/set-byte-if-= %al
    35907     81 4/subop/and %eax 0xff/imm32
    35908 $simple-mu-type?:end:
    35909     # . restore registers
    35910     59/pop-to-ecx
    35911     # . epilogue
    35912     89/<- %esp 5/r32/ebp
    35913     5d/pop-to-ebp
    35914     c3/return
    35915
    35916 mu-addr-type?:  # a: (addr type-tree) -> result/eax: boolean
    35917     # . prologue
    35918     55/push-ebp
    35919     89/<- %ebp 4/r32/esp
    35920     # eax = a
    35921     8b/-> *(ebp+8) 0/r32/eax
    35922     # if (!a->is-atom?) a = a->left
    35923     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
    35924     {
    35925       75/jump-if-!= break/disp8
    35926       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    35927     }
    35928     # return (a->value == addr)
    35929     81 7/subop/compare *(eax+4) 2/imm32/addr  # Type-tree-value
    35930     0f 94/set-byte-if-= %al
    35931     81 4/subop/and %eax 0xff/imm32
    35932 $mu-addr-type?:end:
    35933     # . epilogue
    35934     89/<- %esp 5/r32/ebp
    35935     5d/pop-to-ebp
    35936     c3/return
    35937
    35938 mu-array-type?:  # a: (addr type-tree) -> result/eax: boolean
    35939     # . prologue
    35940     55/push-ebp
    35941     89/<- %ebp 4/r32/esp
    35942     # eax = a
    35943     8b/-> *(ebp+8) 0/r32/eax
    35944     # if (!a->is-atom?) a = a->left
    35945     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
    35946     {
    35947       75/jump-if-!= break/disp8
    35948       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    35949     }
    35950     # return (a->value == array)
    35951     81 7/subop/compare *(eax+4) 3/imm32/array  # Type-tree-value
    35952     0f 94/set-byte-if-= %al
    35953     81 4/subop/and %eax 0xff/imm32
    35954 $mu-array-type?:end:
    35955     # . epilogue
    35956     89/<- %esp 5/r32/ebp
    35957     5d/pop-to-ebp
    35958     c3/return
    35959
    35960 mu-string-type?:  # a: (addr type-tree) -> result/eax: boolean
    35961     # . prologue
    35962     55/push-ebp
    35963     89/<- %ebp 4/r32/esp
    35964     # . save registers
    35965     56/push-esi
    35966     # esi = a
    35967     8b/-> *(ebp+8) 6/r32/esi
    35968     # if (a->is-atom?) return false
    35969     81 7/subop/compare *esi 0/imm32/false  # Type-tree-is-atom
    35970     0f 85/jump-if-!= $mu-string-type?:return-false/disp32
    35971     # if a is not an addr, return false
    35972     (mu-addr-type? %esi)  # => eax
    35973     3d/compare-eax-with 0/imm32/false
    35974     0f 84/jump-if-= $mu-string-type?:end/disp32  # eax changes var
    35975     # if a is not an array, return false
    35976     (lookup *(esi+0xc) *(esi+0x10))  # Type-tree-right Type-tree-right => eax
    35977     (mu-array-type? %eax)  # => eax
    35978     3d/compare-eax-with 0/imm32/false
    35979     74/jump-if-= $mu-string-type?:end/disp8  # eax changes var
    35980     # var p/eax: (addr type-tree) = payload of a
    35981     (lookup *(esi+0xc) *(esi+0x10))  # Type-tree-right Type-tree-right => eax
    35982     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
    35983     # if p is an atom, return false
    35984     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
    35985     75/jump-if-!= $mu-string-type?:return-false/disp8
    35986     # return (p == byte)
    35987     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    35988     (simple-mu-type? %eax 8)  # byte => eax
    35989     eb/jump $mu-string-type?:end/disp8
    35990 $mu-string-type?:return-false:
    35991     b8/copy-to-eax 0/imm32/false
    35992 $mu-string-type?:end:
    35993     # . restore registers
    35994     5e/pop-to-esi
    35995     # . epilogue
    35996     89/<- %esp 5/r32/ebp
    35997     5d/pop-to-ebp
    35998     c3/return
    35999
    36000 mu-stream-type?:  # a: (addr type-tree) -> result/eax: boolean
    36001     # . prologue
    36002     55/push-ebp
    36003     89/<- %ebp 4/r32/esp
    36004     # eax = a
    36005     8b/-> *(ebp+8) 0/r32/eax
    36006     # if (!a->is-atom?) a = a->left
    36007     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
    36008     {
    36009       75/jump-if-!= break/disp8
    36010       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    36011     }
    36012     # return (a->value == stream)
    36013     81 7/subop/compare *(eax+4) 0xb/imm32/stream  # Type-tree-value
    36014     0f 94/set-byte-if-= %al
    36015     81 4/subop/and %eax 0xff/imm32
    36016 $mu-stream-type?:end:
    36017     # . epilogue
    36018     89/<- %esp 5/r32/ebp
    36019     5d/pop-to-ebp
    36020     c3/return
    36021
    36022 test-emit-subx-stmt-primitive:
    36023     # Primitive operation on a variable on the stack.
    36024     #   increment foo
    36025     # =>
    36026     #   ff 0/subop/increment *(ebp-8)
    36027     #
    36028     # There's a variable on the var stack as follows:
    36029     #   name: 'foo'
    36030     #   type: int
    36031     #   stack-offset: -8
    36032     #
    36033     # There's a primitive with this info:
    36034     #   name: 'increment'
    36035     #   inouts: int/mem
    36036     #   value: 'ff 0/subop/increment'
    36037     #
    36038     # . prologue
    36039     55/push-ebp
    36040     89/<- %ebp 4/r32/esp
    36041     # setup
    36042     (clear-stream _test-output-stream)
    36043     (clear-stream $_test-output-buffered-file->buffer)
    36044     # simulate allocated payloads starting with an initial fake alloc-id (0x11)
    36045 $test-emit-subx-stmt-primitive:initialize-type:
    36046     # var type/ecx: (payload type-tree) = int
    36047     68/push 0/imm32/right:null
    36048     68/push 0/imm32/right:null
    36049     68/push 0/imm32/left:unused
    36050     68/push 1/imm32/value:int
    36051     68/push 1/imm32/is-atom?:true
    36052     68/push 0x11/imm32/alloc-id:fake:payload
    36053     89/<- %ecx 4/r32/esp
    36054 $test-emit-subx-stmt-primitive:initialize-var:
    36055     # var var-foo/ecx: (payload var) = var(type)
    36056     68/push 0/imm32/no-register
    36057     68/push 0/imm32/no-register
    36058     68/push -8/imm32/stack-offset
    36059     68/push 1/imm32/block-depth
    36060     51/push-ecx/type
    36061     68/push 0x11/imm32/alloc-id:fake
    36062     68/push 0/imm32/name
    36063     68/push 0/imm32/name
    36064     68/push 0x11/imm32/alloc-id:fake:payload
    36065     89/<- %ecx 4/r32/esp
    36066 $test-emit-subx-stmt-primitive:initialize-var-name:
    36067     # var-foo->name = "foo"
    36068     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
    36069     (copy-array Heap "foo" %eax)
    36070 $test-emit-subx-stmt-primitive:initialize-stmt-var:
    36071     # var operand/ebx: (payload stmt-var) = stmt-var(var-foo)
    36072     68/push 0/imm32/is-deref:false
    36073     68/push 0/imm32/next
    36074     68/push 0/imm32/next
    36075     51/push-ecx/var-foo
    36076     68/push 0x11/imm32/alloc-id:fake
    36077     68/push 0x11/imm32/alloc-id:fake:payload
    36078     89/<- %ebx 4/r32/esp
    36079 $test-emit-subx-stmt-primitive:initialize-stmt:
    36080     # var stmt/esi: (addr statement)
    36081     68/push 0/imm32/no-outputs
    36082     68/push 0/imm32/no-outputs
    36083     53/push-ebx/inouts
    36084     68/push 0x11/imm32/alloc-id:fake
    36085     68/push 0/imm32/operation
    36086     68/push 0/imm32/operation
    36087     68/push 1/imm32/tag
    36088     89/<- %esi 4/r32/esp
    36089 $test-emit-subx-stmt-primitive:initialize-stmt-operation:
    36090     # stmt->operation = "increment"
    36091     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
    36092     (copy-array Heap "increment" %eax)
    36093 $test-emit-subx-stmt-primitive:initialize-primitive:
    36094     # var primitives/ebx: (addr primitive)
    36095     68/push 0/imm32/next
    36096     68/push 0/imm32/next
    36097     68/push 0/imm32/no-x32
    36098     68/push 0/imm32/no-xm32
    36099     68/push 0/imm32/no-disp32
    36100     68/push 0/imm32/no-imm8
    36101     68/push 0/imm32/no-imm32
    36102     68/push 0/imm32/no-r32
    36103     68/push 1/imm32/rm32-is-first-inout
    36104     68/push 0/imm32/subx-name
    36105     68/push 0/imm32/subx-name
    36106     68/push 0/imm32/no-outputs
    36107     68/push 0/imm32/no-outputs
    36108     53/push-ebx/inouts  # hack: reuse stmt-var from call stmt as (list var) in function declaration
    36109     68/push 0x11/imm32/alloc-id:fake
    36110     68/push 0/imm32/name
    36111     68/push 0/imm32/name
    36112     89/<- %ebx 4/r32/esp
    36113 $test-emit-subx-stmt-primitive:initialize-primitive-name:
    36114     # primitives->name = "increment"
    36115     (copy-array Heap "increment" %ebx)  # Primitive-name
    36116 $test-emit-subx-stmt-primitive:initialize-primitive-subx-name:
    36117     # primitives->subx-name = "ff 0/subop/increment"
    36118     8d/copy-address *(ebx+0x18) 0/r32/eax  # Primitive-subx-name
    36119     (copy-array Heap "ff 0/subop/increment" %eax)
    36120     # convert
    36121     c7 0/subop/copy *Curr-block-depth 0/imm32
    36122     (emit-subx-stmt _test-output-buffered-file %esi %ebx 0 Stderr 0)
    36123     (flush _test-output-buffered-file)
    36124 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
    36130     # check output
    36131     (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment *(ebp+0xfffffff8)" "F - test-emit-subx-stmt-primitive")
    36132     # . epilogue
    36133     89/<- %esp 5/r32/ebp
    36134     5d/pop-to-ebp
    36135     c3/return
    36136
    36137 test-emit-subx-stmt-primitive-register:
    36138     # Primitive operation on a variable in a register.
    36139     #   foo <- increment
    36140     # =>
    36141     #   ff 0/subop/increment %eax  # sub-optimal, but should suffice
    36142     #
    36143     # There's a variable on the var stack as follows:
    36144     #   name: 'foo'
    36145     #   type: int
    36146     #   register: 'eax'
    36147     #
    36148     # There's a primitive with this info:
    36149     #   name: 'increment'
    36150     #   out: int/reg
    36151     #   value: 'ff 0/subop/increment'
    36152     #
    36153     # . prologue
    36154     55/push-ebp
    36155     89/<- %ebp 4/r32/esp
    36156     # setup
    36157     (clear-stream _test-output-stream)
    36158     (clear-stream $_test-output-buffered-file->buffer)
    36159 $test-emit-subx-stmt-primitive-register:initialize-type:
    36160     # var type/ecx: (payload type-tree) = int
    36161     68/push 0/imm32/right:null
    36162     68/push 0/imm32/right:null
    36163     68/push 0/imm32/left:unused
    36164     68/push 1/imm32/value:int
    36165     68/push 1/imm32/is-atom?:true
    36166     68/push 0x11/imm32/alloc-id:fake:payload
    36167     89/<- %ecx 4/r32/esp
    36168 $test-emit-subx-stmt-primitive-register:initialize-var:
    36169     # var var-foo/ecx: (payload var)
    36170     68/push 0/imm32/register
    36171     68/push 0/imm32/register
    36172     68/push 0/imm32/no-stack-offset
    36173     68/push 1/imm32/block-depth
    36174     51/push-ecx
    36175     68/push 0x11/imm32/alloc-id:fake
    36176     68/push 0/imm32/name
    36177     68/push 0/imm32/name
    36178     68/push 0x11/imm32/alloc-id:fake:payload
    36179     89/<- %ecx 4/r32/esp
    36180 $test-emit-subx-stmt-primitive-register:initialize-var-name:
    36181     # var-foo->name = "foo"
    36182     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
    36183     (copy-array Heap "foo" %eax)
    36184 $test-emit-subx-stmt-primitive-register:initialize-var-register:
    36185     # var-foo->register = "eax"
    36186     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
    36187     (copy-array Heap "eax" %eax)
    36188 $test-emit-subx-stmt-primitive-register:initialize-stmt-var:
    36189     # var operand/ebx: (payload stmt-var)
    36190     68/push 0/imm32/is-deref:false
    36191     68/push 0/imm32/next
    36192     68/push 0/imm32/next
    36193     51/push-ecx/var-foo
    36194     68/push 0x11/imm32/alloc-id:fake
    36195     68/push 0x11/imm32/alloc-id:fake:payload
    36196     89/<- %ebx 4/r32/esp
    36197 $test-emit-subx-stmt-primitive-register:initialize-stmt:
    36198     # var stmt/esi: (addr statement)
    36199     53/push-ebx/outputs
    36200     68/push 0x11/imm32/alloc-id:fake
    36201     68/push 0/imm32/no-inouts
    36202     68/push 0/imm32/no-inouts
    36203     68/push 0/imm32/operation
    36204     68/push 0/imm32/operation
    36205     68/push 1/imm32
    36206     89/<- %esi 4/r32/esp
    36207 $test-emit-subx-stmt-primitive-register:initialize-stmt-operation:
    36208     # stmt->operation = "increment"
    36209     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
    36210     (copy-array Heap "increment" %eax)
    36211 $test-emit-subx-stmt-primitive-register:initialize-formal-var:
    36212     # var formal-var/ebx: (payload var)
    36213     68/push 0/imm32/register
    36214     68/push 0/imm32/register
    36215     68/push 0/imm32/no-stack-offset
    36216     68/push 1/imm32/block-depth
    36217     ff 6/subop/push *(ecx+0x10)  # Var-type + payload alloc id + handle alloc id
    36218     68/push 0x11/imm32/alloc-id:fake
    36219     68/push 0/imm32/name
    36220     68/push 0/imm32/name
    36221     68/push 0x11/imm32/alloc-id:fake:payload
    36222     89/<- %ebx 4/r32/esp
    36223 $test-emit-subx-stmt-primitive-register:initialize-formal-var-name:
    36224     # formal-var->name = "dummy"
    36225     8d/copy-address *(ebx+4) 0/r32/eax  # Var-name + 4
    36226     (copy-array Heap "dummy" %eax)
    36227 $test-emit-subx-stmt-primitive-register:initialize-formal-register:
    36228     # formal-var->register = "*"
    36229     8d/copy-address *(ebx+0x1c) 0/r32/eax  # Var-register + 4
    36230     (copy-array Heap "*" %eax)  # Any-register
    36231 $test-emit-subx-stmt-primitive-register:initialize-var-list:
    36232     # var formal-outputs/ebx: (payload list var)
    36233     68/push 0/imm32/next
    36234     68/push 0/imm32/next
    36235     53/push-ebx/formal-var
    36236     68/push 0x11/imm32/alloc-id:fake
    36237     68/push 0x11/imm32/alloc-id:fake:payload
    36238     89/<- %ebx 4/r32/esp
    36239 $test-emit-subx-stmt-primitive-register:initialize-primitive:
    36240     # var primitives/ebx: (addr primitive)
    36241     68/push 0/imm32/next
    36242     68/push 0/imm32/next
    36243     68/push 0/imm32/no-x32
    36244     68/push 0/imm32/no-xm32
    36245     68/push 0/imm32/no-disp32
    36246     68/push 0/imm32/no-imm8
    36247     68/push 0/imm32/no-imm32
    36248     68/push 0/imm32/no-r32
    36249     68/push 3/imm32/rm32-is-first-output
    36250     68/push 0/imm32/subx-name
    36251     68/push 0/imm32/subx-name
    36252     53/push-ebx/outputs
    36253     68/push 0x11/imm32/alloc-id:fake
    36254     68/push 0/imm32/no-inouts
    36255     68/push 0/imm32/no-inouts
    36256     68/push 0/imm32/name
    36257     68/push 0/imm32/name
    36258     89/<- %ebx 4/r32/esp
    36259 $test-emit-subx-stmt-primitive-register:initialize-primitive-name:
    36260     # primitives->name = "increment"
    36261     (copy-array Heap "increment" %ebx)  # Primitive-name
    36262 $test-emit-subx-stmt-primitive-register:initialize-primitive-subx-name:
    36263     # primitives->subx-name = "ff 0/subop/increment"
    36264     8d/copy-address *(ebx+0x18) 0/r32/eax  # Primitive-subx-name
    36265     (copy-array Heap "ff 0/subop/increment" %eax)
    36266     # convert
    36267     c7 0/subop/copy *Curr-block-depth 0/imm32
    36268     (emit-subx-stmt _test-output-buffered-file %esi %ebx 0 Stderr 0)
    36269     (flush _test-output-buffered-file)
    36270 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
    36276     # check output
    36277     (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-stmt-primitive-register")
    36278     # . epilogue
    36279     89/<- %esp 5/r32/ebp
    36280     5d/pop-to-ebp
    36281     c3/return
    36282
    36283 test-emit-subx-stmt-select-primitive:
    36284     # Select the right primitive between overloads.
    36285     #   foo <- increment
    36286     # =>
    36287     #   ff 0/subop/increment %eax  # sub-optimal, but should suffice
    36288     #
    36289     # There's a variable on the var stack as follows:
    36290     #   name: 'foo'
    36291     #   type: int
    36292     #   register: 'eax'
    36293     #
    36294     # There's two primitives, as follows:
    36295     #   - name: 'increment'
    36296     #     out: int/reg
    36297     #     value: 'ff 0/subop/increment'
    36298     #   - name: 'increment'
    36299     #     inout: int/mem
    36300     #     value: 'ff 0/subop/increment'
    36301     #
    36302     # . prologue
    36303     55/push-ebp
    36304     89/<- %ebp 4/r32/esp
    36305     # setup
    36306     (clear-stream _test-output-stream)
    36307     (clear-stream $_test-output-buffered-file->buffer)
    36308 $test-emit-subx-stmt-select-primitive:initialize-type:
    36309     # var type/ecx: (payload type-tree) = int
    36310     68/push 0/imm32/right:null
    36311     68/push 0/imm32/right:null
    36312     68/push 0/imm32/left:unused
    36313     68/push 1/imm32/value:int
    36314     68/push 1/imm32/is-atom?:true
    36315     68/push 0x11/imm32/alloc-id:fake:payload
    36316     89/<- %ecx 4/r32/esp
    36317 $test-emit-subx-stmt-select-primitive:initialize-var:
    36318     # var var-foo/ecx: (payload var)
    36319     68/push 0/imm32/register
    36320     68/push 0/imm32/register
    36321     68/push 0/imm32/no-stack-offset
    36322     68/push 1/imm32/block-depth
    36323     51/push-ecx
    36324     68/push 0x11/imm32/alloc-id:fake
    36325     68/push 0/imm32/name
    36326     68/push 0/imm32/name
    36327     68/push 0x11/imm32/alloc-id:fake:payload
    36328     89/<- %ecx 4/r32/esp
    36329 $test-emit-subx-stmt-select-primitive:initialize-var-name:
    36330     # var-foo->name = "foo"
    36331     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
    36332     (copy-array Heap "foo" %eax)
    36333 $test-emit-subx-stmt-select-primitive:initialize-var-register:
    36334     # var-foo->register = "eax"
    36335     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
    36336     (copy-array Heap "eax" %eax)
    36337 $test-emit-subx-stmt-select-primitive:initialize-stmt-var:
    36338     # var operand/ebx: (payload stmt-var)
    36339     68/push 0/imm32/is-deref:false
    36340     68/push 0/imm32/next
    36341     68/push 0/imm32/next
    36342     51/push-ecx/var-foo
    36343     68/push 0x11/imm32/alloc-id:fake
    36344     68/push 0x11/imm32/alloc-id:fake:payload
    36345     89/<- %ebx 4/r32/esp
    36346 $test-emit-subx-stmt-select-primitive:initialize-stmt:
    36347     # var stmt/esi: (addr statement)
    36348     53/push-ebx/outputs
    36349     68/push 0x11/imm32/alloc-id:fake
    36350     68/push 0/imm32/no-inouts
    36351     68/push 0/imm32/no-inouts
    36352     68/push 0/imm32/operation
    36353     68/push 0/imm32/operation
    36354     68/push 1/imm32
    36355     89/<- %esi 4/r32/esp
    36356 $test-emit-subx-stmt-select-primitive:initialize-stmt-operation:
    36357     # stmt->operation = "increment"
    36358     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
    36359     (copy-array Heap "increment" %eax)
    36360 $test-emit-subx-stmt-select-primitive:initialize-formal-var:
    36361     # var formal-var/ebx: (payload var)
    36362     68/push 0/imm32/register
    36363     68/push 0/imm32/register
    36364     68/push 0/imm32/no-stack-offset
    36365     68/push 1/imm32/block-depth
    36366     ff 6/subop/push *(ecx+0x10)  # Var-type + payload alloc id + handle alloc id
    36367     68/push 0x11/imm32/alloc-id:fake
    36368     68/push 0/imm32/name
    36369     68/push 0/imm32/name
    36370     68/push 0x11/imm32/alloc-id:fake:payload
    36371     89/<- %ebx 4/r32/esp
    36372 $test-emit-subx-stmt-select-primitive:initialize-formal-var-name:
    36373     # formal-var->name = "dummy"
    36374     8d/copy-address *(ebx+4) 0/r32/eax  # Var-name + 4
    36375     (copy-array Heap "dummy" %eax)
    36376 $test-emit-subx-stmt-select-primitive:initialize-formal-register:
    36377     # formal-var->register = "*"
    36378     8d/copy-address *(ebx+0x1c) 0/r32/eax  # Var-register + 4
    36379     (copy-array Heap "*" %eax)  # Any-register
    36380 $test-emit-subx-stmt-select-primitive:initialize-var-list:
    36381     # var formal-outputs/ebx: (payload list var)
    36382     68/push 0/imm32/next
    36383     68/push 0/imm32/next
    36384     53/push-ebx/formal-var
    36385     68/push 0x11/imm32/alloc-id:fake
    36386     68/push 0x11/imm32/alloc-id:fake:payload
    36387     89/<- %ebx 4/r32/esp
    36388 $test-emit-subx-stmt-select-primitive:initialize-primitive2:
    36389     # var primitive2/edi: (payload primitive)
    36390     68/push 0/imm32/next
    36391     68/push 0/imm32/next
    36392     68/push 0/imm32/no-x32
    36393     68/push 0/imm32/no-xm32
    36394     68/push 0/imm32/no-disp32
    36395     68/push 0/imm32/no-imm8
    36396     68/push 0/imm32/no-imm32
    36397     68/push 0/imm32/no-r32
    36398     68/push 3/imm32/rm32-is-first-output
    36399     68/push 0/imm32/subx-name
    36400     68/push 0/imm32/subx-name
    36401     53/push-ebx/outputs
    36402     68/push 0x11/imm32/alloc-id:fake
    36403     68/push 0/imm32/no-inouts
    36404     68/push 0/imm32/no-inouts
    36405     68/push 0/imm32/name
    36406     68/push 0/imm32/name
    36407     68/push 0x11/imm32/alloc-id:fake:payload
    36408     89/<- %edi 4/r32/esp
    36409 $test-emit-subx-stmt-select-primitive:initialize-primitive2-name:
    36410     # primitives->name = "increment"
    36411     8d/copy-address *(edi+4) 0/r32/eax  # Primitive-name + 4
    36412     (copy-array Heap "increment" %eax)
    36413 $test-emit-subx-stmt-select-primitive:initialize-primitive2-subx-name:
    36414     # primitives->subx-name = "ff 0/subop/increment"
    36415     8d/copy-address *(edi+0x1c) 0/r32/eax  # Primitive-subx-name + 4
    36416     (copy-array Heap "ff 0/subop/increment" %eax)
    36417 $test-emit-subx-stmt-select-primitive:initialize-primitive:
    36418     # var primitives/ebx: (addr primitive)
    36419     57/push-edi
    36420     68/push 0x11/imm32/alloc-id:fake
    36421     68/push 0/imm32/no-x32
    36422     68/push 0/imm32/no-xm32
    36423     68/push 0/imm32/no-disp32
    36424     68/push 0/imm32/no-imm8
    36425     68/push 0/imm32/no-imm32
    36426     68/push 0/imm32/no-r32
    36427     68/push 1/imm32/rm32-is-first-inout
    36428     68/push 0/imm32/subx-name
    36429     68/push 0/imm32/subx-name
    36430     68/push 0/imm32/no-outputs
    36431     68/push 0/imm32/no-outputs
    36432     53/push-ebx/inouts  # hack: reuse stmt-var from call stmt as (list var) in function declaration
    36433     68/push 0x11/imm32/alloc-id:fake
    36434     68/push 0/imm32/name
    36435     68/push 0/imm32/name
    36436     89/<- %ebx 4/r32/esp
    36437 $test-emit-subx-stmt-select-primitive:initialize-primitive-name:
    36438     # primitives->name = "increment"
    36439     (copy-array Heap "increment" %ebx)  # Primitive-name
    36440 $test-emit-subx-stmt-select-primitive:initialize-primitive-subx-name:
    36441     # primitives->subx-name = "ff 0/subop/increment"
    36442     8d/copy-address *(ebx+0x18) 0/r32/eax  # Primitive-subx-name
    36443     (copy-array Heap "ff 0/subop/increment" %eax)
    36444     # convert
    36445     c7 0/subop/copy *Curr-block-depth 0/imm32
    36446     (emit-subx-stmt _test-output-buffered-file %esi %ebx 0 Stderr 0)
    36447     (flush _test-output-buffered-file)
    36448 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
    36454     # check output
    36455     (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-stmt-select-primitive")
    36456     # . epilogue
    36457     89/<- %esp 5/r32/ebp
    36458     5d/pop-to-ebp
    36459     c3/return
    36460
    36461 test-emit-subx-stmt-select-primitive-2:
    36462     # Select the right primitive between overloads.
    36463     #   increment foo
    36464     # =>
    36465     #   ff 0/subop/increment %eax  # sub-optimal, but should suffice
    36466     #
    36467     # There's a variable on the var stack as follows:
    36468     #   name: 'foo'
    36469     #   type: int
    36470     #   register: 'eax'
    36471     #
    36472     # There's two primitives, as follows:
    36473     #   - name: 'increment'
    36474     #     out: int/reg
    36475     #     value: 'ff 0/subop/increment'
    36476     #   - name: 'increment'
    36477     #     inout: int/mem
    36478     #     value: 'ff 0/subop/increment'
    36479     #
    36480     # . prologue
    36481     55/push-ebp
    36482     89/<- %ebp 4/r32/esp
    36483     # setup
    36484     (clear-stream _test-output-stream)
    36485     (clear-stream $_test-output-buffered-file->buffer)
    36486 $test-emit-subx-stmt-select-primitive-2:initialize-type:
    36487     # var type/ecx: (payload type-tree) = int
    36488     68/push 0/imm32/right:null
    36489     68/push 0/imm32/right:null
    36490     68/push 0/imm32/left:unused
    36491     68/push 1/imm32/value:int
    36492     68/push 1/imm32/is-atom?:true
    36493     68/push 0x11/imm32/alloc-id:fake:payload
    36494     89/<- %ecx 4/r32/esp
    36495 $test-emit-subx-stmt-select-primitive-2:initialize-var:
    36496     # var var-foo/ecx: (payload var)
    36497     68/push 0/imm32/register
    36498     68/push 0/imm32/register
    36499     68/push 0/imm32/no-stack-offset
    36500     68/push 1/imm32/block-depth
    36501     51/push-ecx
    36502     68/push 0x11/imm32/alloc-id:fake
    36503     68/push 0/imm32/name
    36504     68/push 0/imm32/name
    36505     68/push 0x11/imm32/alloc-id:fake:payload
    36506     89/<- %ecx 4/r32/esp
    36507 $test-emit-subx-stmt-select-primitive-2:initialize-var-name:
    36508     # var-foo->name = "foo"
    36509     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
    36510     (copy-array Heap "foo" %eax)
    36511 $test-emit-subx-stmt-select-primitive-2:initialize-var-register:
    36512     # var-foo->register = "eax"
    36513     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
    36514     (copy-array Heap "eax" %eax)
    36515 $test-emit-subx-stmt-select-primitive-2:initialize-stmt-var:
    36516     # var operand/ebx: (payload stmt-var)
    36517     68/push 0/imm32/is-deref:false
    36518     68/push 0/imm32/next
    36519     68/push 0/imm32/next
    36520     51/push-ecx/var-foo
    36521     68/push 0x11/imm32/alloc-id:fake
    36522     68/push 0x11/imm32/alloc-id:fake:payload
    36523     89/<- %ebx 4/r32/esp
    36524 $test-emit-subx-stmt-select-primitive-2:initialize-stmt:
    36525     # var stmt/esi: (addr statement)
    36526     68/push 0/imm32/no-outputs
    36527     68/push 0/imm32/no-outputs
    36528     53/push-ebx/inouts
    36529     68/push 0x11/imm32/alloc-id:fake
    36530     68/push 0/imm32/operation
    36531     68/push 0/imm32/operation
    36532     68/push 1/imm32
    36533     89/<- %esi 4/r32/esp
    36534 $test-emit-subx-stmt-select-primitive-2:initialize-stmt-operation:
    36535     # stmt->operation = "increment"
    36536     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
    36537     (copy-array Heap "increment" %eax)
    36538 $test-emit-subx-stmt-select-primitive-2:initialize-formal-var:
    36539     # var formal-var/ebx: (payload var)
    36540     68/push 0/imm32/register
    36541     68/push 0/imm32/register
    36542     68/push 0/imm32/no-stack-offset
    36543     68/push 1/imm32/block-depth
    36544     ff 6/subop/push *(ecx+0x10)  # Var-type + payload alloc id + handle alloc id
    36545     68/push 0x11/imm32/alloc-id:fake
    36546     68/push 0/imm32/name
    36547     68/push 0/imm32/name
    36548     68/push 0x11/imm32/alloc-id:fake:payload
    36549     89/<- %ebx 4/r32/esp
    36550 $test-emit-subx-stmt-select-primitive-2:initialize-formal-var-name:
    36551     # formal-var->name = "dummy"
    36552     8d/copy-address *(ebx+4) 0/r32/eax  # Var-name + 4
    36553     (copy-array Heap "dummy" %eax)
    36554 $test-emit-subx-stmt-select-primitive-2:initialize-formal-register:
    36555     # formal-var->register = "*"
    36556     8d/copy-address *(ebx+0x1c) 0/r32/eax  # Var-register + 4
    36557     (copy-array Heap "*" %eax)  # Any-register
    36558 $test-emit-subx-stmt-select-primitive-2:initialize-var-list:
    36559     # var formal-outputs/ebx: (payload list stmt-var)
    36560     68/push 0/imm32/next
    36561     68/push 0/imm32/next
    36562     53/push-ebx/formal-var
    36563     68/push 0x11/imm32/alloc-id:fake
    36564     68/push 0x11/imm32/alloc-id:fake:payload
    36565     89/<- %ebx 4/r32/esp
    36566 $test-emit-subx-stmt-select-primitive-2:initialize-primitive2:
    36567     # var primitive2/edi: (payload primitive)
    36568     68/push 0/imm32/next
    36569     68/push 0/imm32/next
    36570     68/push 0/imm32/no-x32
    36571     68/push 0/imm32/no-xm32
    36572     68/push 0/imm32/no-disp32
    36573     68/push 0/imm32/no-imm8
    36574     68/push 0/imm32/no-imm32
    36575     68/push 0/imm32/no-r32
    36576     68/push 3/imm32/rm32-is-first-output
    36577     68/push 0/imm32/subx-name
    36578     68/push 0/imm32/subx-name
    36579     53/push-ebx/outputs
    36580     68/push 0x11/imm32/alloc-id:fake
    36581     68/push 0/imm32/no-inouts
    36582     68/push 0/imm32/no-inouts
    36583     68/push 0/imm32/name
    36584     68/push 0/imm32/name
    36585     68/push 0x11/imm32/alloc-id:fake:payload
    36586     89/<- %edi 4/r32/esp
    36587 $test-emit-subx-stmt-select-primitive-2:initialize-primitive2-name:
    36588     # primitives->name = "increment"
    36589     8d/copy-address *(edi+4) 0/r32/eax  # Primitive-name + 4
    36590     (copy-array Heap "increment" %eax)
    36591 $test-emit-subx-stmt-select-primitive-2:initialize-primitive2-subx-name:
    36592     # primitives->subx-name = "ff 0/subop/increment"
    36593     8d/copy-address *(edi+0x1c) 0/r32/eax  # Primitive-subx-name + 4
    36594     (copy-array Heap "ff 0/subop/increment" %eax)
    36595 $test-emit-subx-stmt-select-primitive-2:initialize-primitive:
    36596     # var primitives/ebx: (addr primitive)
    36597     57/push-edi
    36598     68/push 0x11/imm32/alloc-id:fake
    36599     68/push 0/imm32/no-x32
    36600     68/push 0/imm32/no-xm32
    36601     68/push 0/imm32/no-disp32
    36602     68/push 0/imm32/no-imm8
    36603     68/push 0/imm32/no-imm32
    36604     68/push 0/imm32/no-r32
    36605     68/push 1/imm32/rm32-is-first-inout
    36606     68/push 0/imm32/subx-name
    36607     68/push 0/imm32/subx-name
    36608     68/push 0/imm32/no-outputs
    36609     68/push 0/imm32/no-outputs
    36610     53/push-ebx/inouts  # hack: reuse stmt-var from call stmt as (list var) in function declaration
    36611     68/push 0x11/imm32/alloc-id:fake
    36612     68/push 0/imm32/name
    36613     68/push 0/imm32/name
    36614     89/<- %ebx 4/r32/esp
    36615 $test-emit-subx-stmt-select-primitive-2:initialize-primitive-name:
    36616     # primitives->name = "increment"
    36617     (copy-array Heap "increment" %ebx)  # Primitive-name
    36618 $test-emit-subx-stmt-select-primitive-2:initialize-primitive-subx-name:
    36619     # primitives->subx-name = "ff 0/subop/increment"
    36620     8d/copy-address *(ebx+0x18) 0/r32/eax  # Primitive-subx-name
    36621     (copy-array Heap "ff 0/subop/increment" %eax)
    36622     # convert
    36623     c7 0/subop/copy *Curr-block-depth 0/imm32
    36624     (emit-subx-stmt _test-output-buffered-file %esi %ebx 0 Stderr 0)
    36625     (flush _test-output-buffered-file)
    36626 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
    36632     # check output
    36633     (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-stmt-select-primitive-2")
    36634     # . epilogue
    36635     89/<- %esp 5/r32/ebp
    36636     5d/pop-to-ebp
    36637     c3/return
    36638
    36639 test-increment-register:
    36640     # Select the right register between overloads.
    36641     #   foo <- increment
    36642     # =>
    36643     #   50/increment-eax
    36644     #
    36645     # There's a variable on the var stack as follows:
    36646     #   name: 'foo'
    36647     #   type: int
    36648     #   register: 'eax'
    36649     #
    36650     # Primitives are the global definitions.
    36651     #
    36652     # . prologue
    36653     55/push-ebp
    36654     89/<- %ebp 4/r32/esp
    36655     # setup
    36656     (clear-stream _test-output-stream)
    36657     (clear-stream $_test-output-buffered-file->buffer)
    36658 $test-increment-register:initialize-type:
    36659     # var type/ecx: (payload type-tree) = int
    36660     68/push 0/imm32/right:null
    36661     68/push 0/imm32/right:null
    36662     68/push 0/imm32/left:unused
    36663     68/push 1/imm32/value:int
    36664     68/push 1/imm32/is-atom?:true
    36665     68/push 0x11/imm32/alloc-id:fake:payload
    36666     89/<- %ecx 4/r32/esp
    36667 $test-increment-register:initialize-var:
    36668     # var var-foo/ecx: (payload var)
    36669     68/push 0/imm32/register
    36670     68/push 0/imm32/register
    36671     68/push 0/imm32/no-stack-offset
    36672     68/push 1/imm32/block-depth
    36673     51/push-ecx
    36674     68/push 0x11/imm32/alloc-id:fake
    36675     68/push 0/imm32/name
    36676     68/push 0/imm32/name
    36677     68/push 0x11/imm32/alloc-id:fake:payload
    36678     89/<- %ecx 4/r32/esp
    36679 $test-increment-register:initialize-var-name:
    36680     # var-foo->name = "foo"
    36681     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
    36682     (copy-array Heap "foo" %eax)
    36683 $test-increment-register:initialize-var-register:
    36684     # var-foo->register = "eax"
    36685     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
    36686     (copy-array Heap "eax" %eax)
    36687 $test-increment-register:initialize-stmt-var:
    36688     # var operand/ebx: (payload stmt-var)
    36689     68/push 0/imm32/is-deref:false
    36690     68/push 0/imm32/next
    36691     68/push 0/imm32/next
    36692     51/push-ecx/var-foo
    36693     68/push 0x11/imm32/alloc-id:fake
    36694     68/push 0x11/imm32/alloc-id:fake:payload
    36695     89/<- %ebx 4/r32/esp
    36696 $test-increment-register:initialize-stmt:
    36697     # var stmt/esi: (addr statement)
    36698     53/push-ebx/outputs
    36699     68/push 0x11/imm32/alloc-id:fake
    36700     68/push 0/imm32/no-inouts
    36701     68/push 0/imm32/no-inouts
    36702     68/push 0/imm32/operation
    36703     68/push 0/imm32/operation
    36704     68/push 1/imm32
    36705     89/<- %esi 4/r32/esp
    36706 $test-increment-register:initialize-stmt-operation:
    36707     # stmt->operation = "increment"
    36708     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
    36709     (copy-array Heap "increment" %eax)
    36710     # convert
    36711     c7 0/subop/copy *Curr-block-depth 0/imm32
    36712     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
    36713     (flush _test-output-buffered-file)
    36714 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
    36720     # check output
    36721     (check-next-stream-line-equal _test-output-stream "40/increment-eax" "F - test-increment-register")
    36722     # . epilogue
    36723     89/<- %esp 5/r32/ebp
    36724     5d/pop-to-ebp
    36725     c3/return
    36726
    36727 test-add-reg-to-reg:
    36728     #   var1/reg <- add var2/reg
    36729     # =>
    36730     #   01/add-to %var1 var2
    36731     #
    36732     # . prologue
    36733     55/push-ebp
    36734     89/<- %ebp 4/r32/esp
    36735     # setup
    36736     (clear-stream _test-output-stream)
    36737     (clear-stream $_test-output-buffered-file->buffer)
    36738 $test-add-reg-to-reg:initialize-type:
    36739     # var type/ecx: (payload type-tree) = int
    36740     68/push 0/imm32/right:null
    36741     68/push 0/imm32/right:null
    36742     68/push 0/imm32/left:unused
    36743     68/push 1/imm32/value:int
    36744     68/push 1/imm32/is-atom?:true
    36745     68/push 0x11/imm32/alloc-id:fake:payload
    36746     89/<- %ecx 4/r32/esp
    36747 $test-add-reg-to-reg:initialize-var1:
    36748     # var var1/ecx: (payload var)
    36749     68/push 0/imm32/register
    36750     68/push 0/imm32/register
    36751     68/push 0/imm32/no-stack-offset
    36752     68/push 1/imm32/block-depth
    36753     51/push-ecx
    36754     68/push 0x11/imm32/alloc-id:fake
    36755     68/push 0/imm32/name
    36756     68/push 0/imm32/name
    36757     68/push 0x11/imm32/alloc-id:fake:payload
    36758     89/<- %ecx 4/r32/esp
    36759 $test-add-reg-to-reg:initialize-var1-name:
    36760     # var1->name = "var1"
    36761     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
    36762     (copy-array Heap "var1" %eax)
    36763 $test-add-reg-to-reg:initialize-var1-register:
    36764     # var1->register = "eax"
    36765     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
    36766     (copy-array Heap "eax" %eax)
    36767 $test-add-reg-to-reg:initialize-var2:
    36768     # var var2/edx: (payload var)
    36769     68/push 0/imm32/register
    36770     68/push 0/imm32/register
    36771     68/push 0/imm32/no-stack-offset
    36772     68/push 1/imm32/block-depth
    36773     ff 6/subop/push *(ecx+0x10)
    36774     68/push 0x11/imm32/alloc-id:fake
    36775     68/push 0/imm32/name
    36776     68/push 0/imm32/name
    36777     68/push 0x11/imm32/alloc-id:fake:payload
    36778     89/<- %edx 4/r32/esp
    36779 $test-add-reg-to-reg:initialize-var2-name:
    36780     # var2->name = "var2"
    36781     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
    36782     (copy-array Heap "var2" %eax)
    36783 $test-add-reg-to-reg:initialize-var2-register:
    36784     # var2->register = "ecx"
    36785     8d/copy-address *(edx+0x1c) 0/r32/eax  # Var-register + 4
    36786     (copy-array Heap "ecx" %eax)
    36787 $test-add-reg-to-reg:initialize-inouts:
    36788     # var inouts/esi: (payload stmt-var) = [var2]
    36789     68/push 0/imm32/is-deref:false
    36790     68/push 0/imm32/next
    36791     68/push 0/imm32/next
    36792     52/push-edx/var2
    36793     68/push 0x11/imm32/alloc-id:fake
    36794     68/push 0x11/imm32/alloc-id:fake:payload
    36795     89/<- %esi 4/r32/esp
    36796 $test-add-reg-to-reg:initialize-outputs:
    36797     # var outputs/edi: (payload stmt-var) = [var1]
    36798     68/push 0/imm32/is-deref:false
    36799     68/push 0/imm32/next
    36800     68/push 0/imm32/next
    36801     51/push-ecx/var1
    36802     68/push 0x11/imm32/alloc-id:fake
    36803     68/push 0x11/imm32/alloc-id:fake:payload
    36804     89/<- %edi 4/r32/esp
    36805 $test-add-reg-to-reg:initialize-stmt:
    36806     # var stmt/esi: (addr statement)
    36807     68/push 0/imm32/next
    36808     68/push 0/imm32/next
    36809     57/push-edi/outputs
    36810     68/push 0x11/imm32/alloc-id:fake
    36811     56/push-esi/inouts
    36812     68/push 0x11/imm32/alloc-id:fake
    36813     68/push 0/imm32/operation
    36814     68/push 0/imm32/operation
    36815     68/push 1/imm32/tag:stmt1
    36816     89/<- %esi 4/r32/esp
    36817 $test-add-reg-to-reg:initialize-stmt-operation:
    36818     # stmt->operation = "add"
    36819     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
    36820     (copy-array Heap "add" %eax)
    36821     # convert
    36822     c7 0/subop/copy *Curr-block-depth 0/imm32
    36823     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
    36824     (flush _test-output-buffered-file)
    36825 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
    36831     # check output
    36832     (check-next-stream-line-equal _test-output-stream "01/add-to %eax 0x00000001/r32" "F - test-add-reg-to-reg")
    36833     # . epilogue
    36834     89/<- %esp 5/r32/ebp
    36835     5d/pop-to-ebp
    36836     c3/return
    36837
    36838 test-add-reg-to-mem:
    36839     #   add-to var1 var2/reg
    36840     # =>
    36841     #   01/add-to *(ebp+__) var2
    36842     #
    36843     # . prologue
    36844     55/push-ebp
    36845     89/<- %ebp 4/r32/esp
    36846     # setup
    36847     (clear-stream _test-output-stream)
    36848     (clear-stream $_test-output-buffered-file->buffer)
    36849 $test-add-reg-to-mem:initialize-type:
    36850     # var type/ecx: (payload type-tree) = int
    36851     68/push 0/imm32/right:null
    36852     68/push 0/imm32/right:null
    36853     68/push 0/imm32/left:unused
    36854     68/push 1/imm32/value:int
    36855     68/push 1/imm32/is-atom?:true
    36856     68/push 0x11/imm32/alloc-id:fake:payload
    36857     89/<- %ecx 4/r32/esp
    36858 $test-add-reg-to-mem:initialize-var1:
    36859     # var var1/ecx: (payload var)
    36860     68/push 0/imm32/register
    36861     68/push 0/imm32/register
    36862     68/push 8/imm32/stack-offset
    36863     68/push 1/imm32/block-depth
    36864     51/push-ecx
    36865     68/push 0x11/imm32/alloc-id:fake
    36866     68/push 0/imm32/name
    36867     68/push 0/imm32/name
    36868     68/push 0x11/imm32/alloc-id:fake:payload
    36869     89/<- %ecx 4/r32/esp
    36870 $test-add-reg-to-mem:initialize-var1-name:
    36871     # var1->name = "var1"
    36872     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
    36873     (copy-array Heap "var1" %eax)
    36874 $test-add-reg-to-mem:initialize-var2:
    36875     # var var2/edx: (payload var)
    36876     68/push 0/imm32/register
    36877     68/push 0/imm32/register
    36878     68/push 0/imm32/no-stack-offset
    36879     68/push 1/imm32/block-depth
    36880     ff 6/subop/push *(ecx+0x10)
    36881     68/push 0x11/imm32/alloc-id:fake
    36882     68/push 0/imm32/name
    36883     68/push 0/imm32/name
    36884     68/push 0x11/imm32/alloc-id:fake:payload
    36885     89/<- %edx 4/r32/esp
    36886 $test-add-reg-to-mem:initialize-var2-name:
    36887     # var2->name = "var2"
    36888     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
    36889     (copy-array Heap "var2" %eax)
    36890 $test-add-reg-to-mem:initialize-var2-register:
    36891     # var2->register = "ecx"
    36892     8d/copy-address *(edx+0x1c) 0/r32/eax  # Var-register + 4
    36893     (copy-array Heap "ecx" %eax)
    36894 $test-add-reg-to-mem:initialize-inouts:
    36895     # var inouts/esi: (payload stmt-var) = [var2]
    36896     68/push 0/imm32/is-deref:false
    36897     68/push 0/imm32/next
    36898     68/push 0/imm32/next
    36899     52/push-edx/var2
    36900     68/push 0x11/imm32/alloc-id:fake
    36901     68/push 0x11/imm32/alloc-id:fake:payload
    36902     89/<- %esi 4/r32/esp
    36903     # inouts = [var1, var2]
    36904     68/push 0/imm32/is-deref:false
    36905     56/push-esi/next
    36906     68/push 0x11/imm32/alloc-id:fake
    36907     51/push-ecx/var1
    36908     68/push 0x11/imm32/alloc-id:fake
    36909     68/push 0x11/imm32/alloc-id:fake:payload
    36910     89/<- %esi 4/r32/esp
    36911 $test-add-reg-to-mem:initialize-stmt:
    36912     # var stmt/esi: (addr statement)
    36913     68/push 0/imm32/next
    36914     68/push 0/imm32/next
    36915     68/push 0/imm32/outputs
    36916     68/push 0/imm32/outputs
    36917     56/push-esi/inouts
    36918     68/push 0x11/imm32/alloc-id:fake
    36919     68/push 0/imm32/operation
    36920     68/push 0/imm32/operation
    36921     68/push 1/imm32/tag:stmt1
    36922     89/<- %esi 4/r32/esp
    36923 $test-add-reg-to-mem:initialize-stmt-operation:
    36924     # stmt->operation = "add-to"
    36925     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
    36926     (copy-array Heap "add-to" %eax)
    36927     # convert
    36928     c7 0/subop/copy *Curr-block-depth 0/imm32
    36929     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
    36930     (flush _test-output-buffered-file)
    36931 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
    36937     # check output
    36938     (check-next-stream-line-equal _test-output-stream "01/add-to *(ebp+0x00000008) 0x00000001/r32" "F - test-add-reg-to-mem")
    36939     # . epilogue
    36940     89/<- %esp 5/r32/ebp
    36941     5d/pop-to-ebp
    36942     c3/return
    36943
    36944 test-add-mem-to-reg:
    36945     #   var1/reg <- add var2
    36946     # =>
    36947     #   03/add *(ebp+__) var1
    36948     #
    36949     # . prologue
    36950     55/push-ebp
    36951     89/<- %ebp 4/r32/esp
    36952     # setup
    36953     (clear-stream _test-output-stream)
    36954     (clear-stream $_test-output-buffered-file->buffer)
    36955 $test-add-mem-to-reg:initialize-type:
    36956     # var type/ecx: (payload type-tree) = int
    36957     68/push 0/imm32/right:null
    36958     68/push 0/imm32/right:null
    36959     68/push 0/imm32/left:unused
    36960     68/push 1/imm32/value:int
    36961     68/push 1/imm32/is-atom?:true
    36962     68/push 0x11/imm32/alloc-id:fake:payload
    36963     89/<- %ecx 4/r32/esp
    36964 $test-add-mem-to-reg:initialize-var:
    36965     # var var1/ecx: (payload var)
    36966     68/push 0/imm32/register
    36967     68/push 0/imm32/register
    36968     68/push 0/imm32/no-stack-offset
    36969     68/push 1/imm32/block-depth
    36970     51/push-ecx
    36971     68/push 0x11/imm32/alloc-id:fake
    36972     68/push 0/imm32/name
    36973     68/push 0/imm32/name
    36974     68/push 0x11/imm32/alloc-id:fake:payload
    36975     89/<- %ecx 4/r32/esp
    36976 $test-add-mem-to-reg:initialize-var-name:
    36977     # var1->name = "foo"
    36978     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
    36979     (copy-array Heap "var1" %eax)
    36980 $test-add-mem-to-reg:initialize-var-register:
    36981     # var1->register = "eax"
    36982     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
    36983     (copy-array Heap "eax" %eax)
    36984 $test-add-mem-to-reg:initialize-var2:
    36985     # var var2/edx: (payload var)
    36986     68/push 0/imm32/register
    36987     68/push 0/imm32/register
    36988     68/push 8/imm32/stack-offset
    36989     68/push 1/imm32/block-depth
    36990     ff 6/subop/push *(ecx+0x10)
    36991     68/push 0x11/imm32/alloc-id:fake
    36992     68/push 0/imm32/name
    36993     68/push 0/imm32/name
    36994     68/push 0x11/imm32/alloc-id:fake:payload
    36995     89/<- %edx 4/r32/esp
    36996 $test-add-mem-to-reg:initialize-var2-name:
    36997     # var2->name = "var2"
    36998     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
    36999     (copy-array Heap "var2" %eax)
    37000 $test-add-mem-to-reg:initialize-inouts:
    37001     # var inouts/esi: (payload stmt-var) = [var2]
    37002     68/push 0/imm32/is-deref:false
    37003     68/push 0/imm32/next
    37004     68/push 0/imm32/next
    37005     52/push-edx/var2
    37006     68/push 0x11/imm32/alloc-id:fake
    37007     68/push 0x11/imm32/alloc-id:fake:payload
    37008     89/<- %esi 4/r32/esp
    37009 $test-add-mem-to-reg:initialize-outputs:
    37010     # var outputs/edi: (payload stmt-var) = [var1]
    37011     68/push 0/imm32/is-deref:false
    37012     68/push 0/imm32/next
    37013     68/push 0/imm32/next
    37014     51/push-ecx/var1
    37015     68/push 0x11/imm32/alloc-id:fake
    37016     68/push 0x11/imm32/alloc-id:fake:payload
    37017     89/<- %edi 4/r32/esp
    37018 $test-add-mem-to-reg:initialize-stmt:
    37019     # var stmt/esi: (addr statement)
    37020     68/push 0/imm32/next
    37021     68/push 0/imm32/next
    37022     57/push-edi/outputs
    37023     68/push 0x11/imm32/alloc-id:fake
    37024     56/push-esi/inouts
    37025     68/push 0x11/imm32/alloc-id:fake
    37026     68/push 0/imm32/operation
    37027     68/push 0/imm32/operation
    37028     68/push 1/imm32/tag:stmt1
    37029     89/<- %esi 4/r32/esp
    37030 $test-add-mem-to-reg:initialize-stmt-operation:
    37031     # stmt->operation = "add"
    37032     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
    37033     (copy-array Heap "add" %eax)
    37034     # convert
    37035     c7 0/subop/copy *Curr-block-depth 0/imm32
    37036     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
    37037     (flush _test-output-buffered-file)
    37038 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
    37044     # check output
    37045     (check-next-stream-line-equal _test-output-stream "03/add *(ebp+0x00000008) 0x00000000/r32" "F - test-add-mem-to-reg")
    37046     # . epilogue
    37047     89/<- %esp 5/r32/ebp
    37048     5d/pop-to-ebp
    37049     c3/return
    37050
    37051 test-add-literal-to-eax:
    37052     #   var1/eax <- add 0x34
    37053     # =>
    37054     #   05/add-to-eax 0x34/imm32
    37055     #
    37056     # . prologue
    37057     55/push-ebp
    37058     89/<- %ebp 4/r32/esp
    37059     # setup
    37060     (clear-stream _test-output-stream)
    37061     (clear-stream $_test-output-buffered-file->buffer)
    37062 $test-add-literal-to-eax:initialize-var-type:
    37063     # var type/ecx: (payload type-tree) = int
    37064     68/push 0/imm32/right:null
    37065     68/push 0/imm32/right:null
    37066     68/push 0/imm32/left:unused
    37067     68/push 1/imm32/value:int
    37068     68/push 1/imm32/is-atom?:true
    37069     68/push 0x11/imm32/alloc-id:fake:payload
    37070     89/<- %ecx 4/r32/esp
    37071 $test-add-literal-to-eax:initialize-var:
    37072     # var v/ecx: (payload var)
    37073     68/push 0/imm32/register
    37074     68/push 0/imm32/register
    37075     68/push 0/imm32/no-stack-offset
    37076     68/push 1/imm32/block-depth
    37077     51/push-ecx
    37078     68/push 0x11/imm32/alloc-id:fake
    37079     68/push 0/imm32/name
    37080     68/push 0/imm32/name
    37081     68/push 0x11/imm32/alloc-id:fake:payload
    37082     89/<- %ecx 4/r32/esp
    37083 $test-add-literal-to-eax:initialize-var-name:
    37084     # v->name = "v"
    37085     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
    37086     (copy-array Heap "v" %eax)
    37087 $test-add-literal-to-eax:initialize-var-register:
    37088     # v->register = "eax"
    37089     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
    37090     (copy-array Heap "eax" %eax)
    37091 $test-add-literal-to-eax:initialize-literal-type:
    37092     # var type/edx: (payload type-tree) = literal
    37093     68/push 0/imm32/right:null
    37094     68/push 0/imm32/right:null
    37095     68/push 0/imm32/left:unused
    37096     68/push 0/imm32/value:literal
    37097     68/push 1/imm32/is-atom?:true
    37098     68/push 0x11/imm32/alloc-id:fake:payload
    37099     89/<- %edx 4/r32/esp
    37100 $test-add-literal-to-eax:initialize-literal:
    37101     # var l/edx: (payload var)
    37102     68/push 0/imm32/register
    37103     68/push 0/imm32/register
    37104     68/push 0/imm32/no-stack-offset
    37105     68/push 1/imm32/block-depth
    37106     52/push-edx
    37107     68/push 0x11/imm32/alloc-id:fake
    37108     68/push 0/imm32/name
    37109     68/push 0/imm32/name
    37110     68/push 0x11/imm32/alloc-id:fake:payload
    37111     89/<- %edx 4/r32/esp
    37112 $test-add-literal-to-eax:initialize-literal-value:
    37113     # l->name = "0x34"
    37114     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
    37115     (copy-array Heap "0x34" %eax)
    37116 $test-add-literal-to-eax:initialize-inouts:
    37117     # var inouts/esi: (payload stmt-var) = [l]
    37118     68/push 0/imm32/is-deref:false
    37119     68/push 0/imm32/next
    37120     68/push 0/imm32/next
    37121     52/push-edx/l
    37122     68/push 0x11/imm32/alloc-id:fake
    37123     68/push 0x11/imm32/alloc-id:fake:payload
    37124     89/<- %esi 4/r32/esp
    37125 $test-add-literal-to-eax:initialize-outputs:
    37126     # var outputs/edi: (payload stmt-var) = [v]
    37127     68/push 0/imm32/is-deref:false
    37128     68/push 0/imm32/next
    37129     68/push 0/imm32/next
    37130     51/push-ecx/v
    37131     68/push 0x11/imm32/alloc-id:fake
    37132     68/push 0x11/imm32/alloc-id:fake:payload
    37133     89/<- %edi 4/r32/esp
    37134 $test-add-literal-to-eax:initialize-stmt:
    37135     # var stmt/esi: (addr statement)
    37136     68/push 0/imm32/next
    37137     68/push 0/imm32/next
    37138     57/push-edi/outputs
    37139     68/push 0x11/imm32/alloc-id:fake
    37140     56/push-esi/inouts
    37141     68/push 0x11/imm32/alloc-id:fake
    37142     68/push 0/imm32/operation
    37143     68/push 0/imm32/operation
    37144     68/push 1/imm32/tag:stmt1
    37145     89/<- %esi 4/r32/esp
    37146 $test-add-literal-to-eax:initialize-stmt-operation:
    37147     # stmt->operation = "add"
    37148     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
    37149     (copy-array Heap "add" %eax)
    37150     # convert
    37151     c7 0/subop/copy *Curr-block-depth 0/imm32
    37152     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
    37153     (flush _test-output-buffered-file)
    37154 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
    37160     # check output
    37161     (check-next-stream-line-equal _test-output-stream "05/add-to-eax 0x34/imm32" "F - test-add-literal-to-eax")
    37162     # . epilogue
    37163     89/<- %esp 5/r32/ebp
    37164     5d/pop-to-ebp
    37165     c3/return
    37166
    37167 test-add-literal-to-reg:
    37168     #   var1/ecx <- add 0x34
    37169     # =>
    37170     #   81 0/subop/add %ecx 0x34/imm32
    37171     #
    37172     # . prologue
    37173     55/push-ebp
    37174     89/<- %ebp 4/r32/esp
    37175     # setup
    37176     (clear-stream _test-output-stream)
    37177     (clear-stream $_test-output-buffered-file->buffer)
    37178 $test-add-literal-to-reg:initialize-var-type:
    37179     # var type/ecx: (payload type-tree) = int
    37180     68/push 0/imm32/right:null
    37181     68/push 0/imm32/right:null
    37182     68/push 0/imm32/left:unused
    37183     68/push 1/imm32/value:int
    37184     68/push 1/imm32/is-atom?:true
    37185     68/push 0x11/imm32/alloc-id:fake:payload
    37186     89/<- %ecx 4/r32/esp
    37187 $test-add-literal-to-reg:initialize-var:
    37188     # var v/ecx: (payload var)
    37189     68/push 0/imm32/register
    37190     68/push 0/imm32/register
    37191     68/push 0/imm32/no-stack-offset
    37192     68/push 1/imm32/block-depth
    37193     51/push-ecx
    37194     68/push 0x11/imm32/alloc-id:fake
    37195     68/push 0/imm32/name
    37196     68/push 0/imm32/name
    37197     68/push 0x11/imm32/alloc-id:fake:payload
    37198     89/<- %ecx 4/r32/esp
    37199 $test-add-literal-to-reg:initialize-var-name:
    37200     # v->name = "v"
    37201     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
    37202     (copy-array Heap "v" %eax)
    37203 $test-add-literal-to-reg:initialize-var-register:
    37204     # v->register = "ecx"
    37205     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
    37206     (copy-array Heap "ecx" %eax)
    37207 $test-add-literal-to-reg:initialize-literal-type:
    37208     # var type/edx: (payload type-tree) = literal
    37209     68/push 0/imm32/right:null
    37210     68/push 0/imm32/right:null
    37211     68/push 0/imm32/left:unused
    37212     68/push 0/imm32/value:literal
    37213     68/push 1/imm32/is-atom?:true
    37214     68/push 0x11/imm32/alloc-id:fake:payload
    37215     89/<- %edx 4/r32/esp
    37216 $test-add-literal-to-reg:initialize-literal:
    37217     # var l/edx: (payload var)
    37218     68/push 0/imm32/register
    37219     68/push 0/imm32/register
    37220     68/push 0/imm32/no-stack-offset
    37221     68/push 1/imm32/block-depth
    37222     52/push-edx
    37223     68/push 0x11/imm32/alloc-id:fake
    37224     68/push 0/imm32/name
    37225     68/push 0/imm32/name
    37226     68/push 0x11/imm32/alloc-id:fake:payload
    37227     89/<- %edx 4/r32/esp
    37228 $test-add-literal-to-reg:initialize-literal-value:
    37229     # l->name = "0x34"
    37230     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
    37231     (copy-array Heap "0x34" %eax)
    37232 $test-add-literal-to-reg:initialize-inouts:
    37233     # var inouts/esi: (payload stmt-var) = [l]
    37234     68/push 0/imm32/is-deref:false
    37235     68/push 0/imm32/next
    37236     68/push 0/imm32/next
    37237     52/push-edx/l
    37238     68/push 0x11/imm32/alloc-id:fake
    37239     68/push 0x11/imm32/alloc-id:fake:payload
    37240     89/<- %esi 4/r32/esp
    37241 $test-add-literal-to-reg:initialize-outputs:
    37242     # var outputs/edi: (payload stmt-var) = [v]
    37243     68/push 0/imm32/is-deref:false
    37244     68/push 0/imm32/next
    37245     68/push 0/imm32/next
    37246     51/push-ecx/v
    37247     68/push 0x11/imm32/alloc-id:fake
    37248     68/push 0x11/imm32/alloc-id:fake:payload
    37249     89/<- %edi 4/r32/esp
    37250 $test-add-literal-to-reg:initialize-stmt:
    37251     # var stmt/esi: (addr statement)
    37252     68/push 0/imm32/next
    37253     68/push 0/imm32/next
    37254     57/push-edi/outputs
    37255     68/push 0x11/imm32/alloc-id:fake
    37256     56/push-esi/inouts
    37257     68/push 0x11/imm32/alloc-id:fake
    37258     68/push 0/imm32/operation
    37259     68/push 0/imm32/operation
    37260     68/push 1/imm32/tag:stmt1
    37261     89/<- %esi 4/r32/esp
    37262 $test-add-literal-to-reg:initialize-stmt-operation:
    37263     # stmt->operation = "add"
    37264     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
    37265     (copy-array Heap "add" %eax)
    37266     # convert
    37267     c7 0/subop/copy *Curr-block-depth 0/imm32
    37268     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
    37269     (flush _test-output-buffered-file)
    37270 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
    37276     # check output
    37277     (check-next-stream-line-equal _test-output-stream "81 0/subop/add %ecx 0x34/imm32" "F - test-add-literal-to-reg")
    37278     # . epilogue
    37279     89/<- %esp 5/r32/ebp
    37280     5d/pop-to-ebp
    37281     c3/return
    37282
    37283 test-add-literal-to-mem:
    37284     #   add-to var1, 0x34
    37285     # =>
    37286     #   81 0/subop/add %eax 0x34/imm32
    37287     #
    37288     # . prologue
    37289     55/push-ebp
    37290     89/<- %ebp 4/r32/esp
    37291     # setup
    37292     (clear-stream _test-output-stream)
    37293     (clear-stream $_test-output-buffered-file->buffer)
    37294 $test-add-literal-to-mem:initialize-type:
    37295     # var type/ecx: (payload type-tree) = int
    37296     68/push 0/imm32/right:null
    37297     68/push 0/imm32/right:null
    37298     68/push 0/imm32/left:unused
    37299     68/push 1/imm32/value:int
    37300     68/push 1/imm32/is-atom?:true
    37301     68/push 0x11/imm32/alloc-id:fake:payload
    37302     89/<- %ecx 4/r32/esp
    37303 $test-add-literal-to-mem:initialize-var1:
    37304     # var var1/ecx: (payload var)
    37305     68/push 0/imm32/register
    37306     68/push 0/imm32/register
    37307     68/push 8/imm32/stack-offset
    37308     68/push 1/imm32/block-depth
    37309     51/push-ecx
    37310     68/push 0x11/imm32/alloc-id:fake
    37311     68/push 0/imm32/name
    37312     68/push 0/imm32/name
    37313     68/push 0x11/imm32/alloc-id:fake:payload
    37314     89/<- %ecx 4/r32/esp
    37315 $test-add-literal-to-mem:initialize-var1-name:
    37316     # var1->name = "var1"
    37317     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
    37318     (copy-array Heap "var1" %eax)
    37319 $test-add-literal-to-mem:initialize-literal-type:
    37320     # var type/edx: (payload type-tree) = literal
    37321     68/push 0/imm32/right:null
    37322     68/push 0/imm32/right:null
    37323     68/push 0/imm32/left:unused
    37324     68/push 0/imm32/value:literal
    37325     68/push 1/imm32/is-atom?:true
    37326     68/push 0x11/imm32/alloc-id:fake:payload
    37327     89/<- %edx 4/r32/esp
    37328 $test-add-literal-to-mem:initialize-literal:
    37329     # var l/edx: (payload var)
    37330     68/push 0/imm32/register
    37331     68/push 0/imm32/register
    37332     68/push 0/imm32/no-stack-offset
    37333     68/push 1/imm32/block-depth
    37334     52/push-edx
    37335     68/push 0x11/imm32/alloc-id:fake
    37336     68/push 0/imm32/name
    37337     68/push 0/imm32/name
    37338     68/push 0x11/imm32/alloc-id:fake:payload
    37339     89/<- %edx 4/r32/esp
    37340 $test-add-literal-to-mem:initialize-literal-value:
    37341     # l->name = "0x34"
    37342     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
    37343     (copy-array Heap "0x34" %eax)
    37344 $test-add-literal-to-mem:initialize-inouts:
    37345     # var inouts/esi: (payload stmt-var) = [l]
    37346     68/push 0/imm32/is-deref:false
    37347     68/push 0/imm32/next
    37348     68/push 0/imm32/next
    37349     52/push-edx/l
    37350     68/push 0x11/imm32/alloc-id:fake
    37351     68/push 0x11/imm32/alloc-id:fake:payload
    37352     89/<- %esi 4/r32/esp
    37353     # var inouts = (handle stmt-var) = [var1, var2]
    37354     68/push 0/imm32/is-deref:false
    37355     56/push-esi/next
    37356     68/push 0x11/imm32/alloc-id:fake
    37357     51/push-ecx/var1
    37358     68/push 0x11/imm32/alloc-id:fake
    37359     68/push 0x11/imm32/alloc-id:fake:payload
    37360     89/<- %esi 4/r32/esp
    37361 $test-add-literal-to-mem:initialize-stmt:
    37362     # var stmt/esi: (addr statement)
    37363     68/push 0/imm32/next
    37364     68/push 0/imm32/next
    37365     68/push 0/imm32/outputs
    37366     68/push 0/imm32/outputs
    37367     56/push-esi/inouts
    37368     68/push 0x11/imm32/alloc-id:fake
    37369     68/push 0/imm32/operation
    37370     68/push 0/imm32/operation
    37371     68/push 1/imm32/tag:stmt1
    37372     89/<- %esi 4/r32/esp
    37373 $test-add-literal-to-mem:initialize-stmt-operation:
    37374     # stmt->operation = "add-to"
    37375     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
    37376     (copy-array Heap "add-to" %eax)
    37377     # convert
    37378     c7 0/subop/copy *Curr-block-depth 0/imm32
    37379     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
    37380     (flush _test-output-buffered-file)
    37381 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
    37387     # check output
    37388     (check-next-stream-line-equal _test-output-stream "81 0/subop/add *(ebp+0x00000008) 0x34/imm32" "F - test-add-literal-to-mem")
    37389     # . epilogue
    37390     89/<- %esp 5/r32/ebp
    37391     5d/pop-to-ebp
    37392     c3/return
    37393
    37394 test-shift-reg-by-literal:
    37395     #   var1/ecx <- shift-left 2
    37396     # =>
    37397     #   c1/shift 4/subop/left %ecx 2/imm8
    37398     #
    37399     # . prologue
    37400     55/push-ebp
    37401     89/<- %ebp 4/r32/esp
    37402     # setup
    37403     (clear-stream _test-output-stream)
    37404     (clear-stream $_test-output-buffered-file->buffer)
    37405 $test-shift-reg-by-literal:initialize-var-type:
    37406     # var type/ecx: (payload type-tree) = int
    37407     68/push 0/imm32/right:null
    37408     68/push 0/imm32/right:null
    37409     68/push 0/imm32/left:unused
    37410     68/push 1/imm32/value:int
    37411     68/push 1/imm32/is-atom?:true
    37412     68/push 0x11/imm32/alloc-id:fake:payload
    37413     89/<- %ecx 4/r32/esp
    37414 $test-shift-reg-by-literal:initialize-var:
    37415     # var v/ecx: (payload var)
    37416     68/push 0/imm32/register
    37417     68/push 0/imm32/register
    37418     68/push 0/imm32/no-stack-offset
    37419     68/push 1/imm32/block-depth
    37420     51/push-ecx
    37421     68/push 0x11/imm32/alloc-id:fake
    37422     68/push 0/imm32/name
    37423     68/push 0/imm32/name
    37424     68/push 0x11/imm32/alloc-id:fake:payload
    37425     89/<- %ecx 4/r32/esp
    37426 $test-shift-reg-by-literal:initialize-var-name:
    37427     # v->name = "v"
    37428     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
    37429     (copy-array Heap "v" %eax)
    37430 $test-shift-reg-by-literal:initialize-var-register:
    37431     # v->register = "ecx"
    37432     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
    37433     (copy-array Heap "ecx" %eax)
    37434 $test-shift-reg-by-literal:initialize-literal-type:
    37435     # var type/edx: (payload type-tree) = literal
    37436     68/push 0/imm32/right:null
    37437     68/push 0/imm32/right:null
    37438     68/push 0/imm32/left:unused
    37439     68/push 0/imm32/value:literal
    37440     68/push 1/imm32/is-atom?:true
    37441     68/push 0x11/imm32/alloc-id:fake:payload
    37442     89/<- %edx 4/r32/esp
    37443 $test-shift-reg-by-literal:initialize-literal:
    37444     # var l/edx: (payload var)
    37445     68/push 0/imm32/register
    37446     68/push 0/imm32/register
    37447     68/push 0/imm32/no-stack-offset
    37448     68/push 1/imm32/block-depth
    37449     52/push-edx
    37450     68/push 0x11/imm32/alloc-id:fake
    37451     68/push 0/imm32/name
    37452     68/push 0/imm32/name
    37453     68/push 0x11/imm32/alloc-id:fake:payload
    37454     89/<- %edx 4/r32/esp
    37455 $test-shift-reg-by-literal:initialize-literal-value:
    37456     # l->name = "2"
    37457     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
    37458     (copy-array Heap "2" %eax)
    37459 $test-shift-reg-by-literal:initialize-inouts:
    37460     # var inouts/esi: (payload stmt-var) = [l]
    37461     68/push 0/imm32/is-deref:false
    37462     68/push 0/imm32/next
    37463     68/push 0/imm32/next
    37464     52/push-edx/l
    37465     68/push 0x11/imm32/alloc-id:fake
    37466     68/push 0x11/imm32/alloc-id:fake:payload
    37467     89/<- %esi 4/r32/esp
    37468 $test-shift-reg-by-literal:initialize-outputs:
    37469     # var outputs/edi: (payload stmt-var) = [v]
    37470     68/push 0/imm32/is-deref:false
    37471     68/push 0/imm32/next
    37472     68/push 0/imm32/next
    37473     51/push-ecx/v
    37474     68/push 0x11/imm32/alloc-id:fake
    37475     68/push 0x11/imm32/alloc-id:fake:payload
    37476     89/<- %edi 4/r32/esp
    37477 $test-shift-reg-by-literal:initialize-stmt:
    37478     # var stmt/esi: (addr statement)
    37479     68/push 0/imm32/next
    37480     68/push 0/imm32/next
    37481     57/push-edi/outputs
    37482     68/push 0x11/imm32/alloc-id:fake
    37483     56/push-esi/inouts
    37484     68/push 0x11/imm32/alloc-id:fake
    37485     68/push 0/imm32/operation
    37486     68/push 0/imm32/operation
    37487     68/push 1/imm32/tag:stmt1
    37488     89/<- %esi 4/r32/esp
    37489 $test-shift-reg-by-literal:initialize-stmt-operation:
    37490     # stmt->operation = "shift-left"
    37491     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
    37492     (copy-array Heap "shift-left" %eax)
    37493     # convert
    37494     c7 0/subop/copy *Curr-block-depth 0/imm32
    37495     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
    37496     (flush _test-output-buffered-file)
    37497 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
    37503     # check output
    37504     (check-next-stream-line-equal _test-output-stream "c1/shift 4/subop/left %ecx 2/imm8" "F - test-shift-reg-by-literal")
    37505     # . epilogue
    37506     89/<- %esp 5/r32/ebp
    37507     5d/pop-to-ebp
    37508     c3/return
    37509
    37510 test-shift-mem-by-literal:
    37511     #   shift-left var 3
    37512     # =>
    37513     #   c1/shift 4/subop/left *(ebp+8) 3/imm8
    37514     #
    37515     # . prologue
    37516     55/push-ebp
    37517     89/<- %ebp 4/r32/esp
    37518     # setup
    37519     (clear-stream _test-output-stream)
    37520     (clear-stream $_test-output-buffered-file->buffer)
    37521 $test-shift-mem-by-literal:initialize-type:
    37522     # var type/ecx: (payload type-tree) = int
    37523     68/push 0/imm32/right:null
    37524     68/push 0/imm32/right:null
    37525     68/push 0/imm32/left:unused
    37526     68/push 1/imm32/value:int
    37527     68/push 1/imm32/is-atom?:true
    37528     68/push 0x11/imm32/alloc-id:fake:payload
    37529     89/<- %ecx 4/r32/esp
    37530 $test-shift-mem-by-literal:initialize-var1:
    37531     # var var1/ecx: (payload var)
    37532     68/push 0/imm32/register
    37533     68/push 0/imm32/register
    37534     68/push 8/imm32/stack-offset
    37535     68/push 1/imm32/block-depth
    37536     51/push-ecx
    37537     68/push 0x11/imm32/alloc-id:fake
    37538     68/push 0/imm32/name
    37539     68/push 0/imm32/name
    37540     68/push 0x11/imm32/alloc-id:fake:payload
    37541     89/<- %ecx 4/r32/esp
    37542 $test-shift-mem-by-literal:initialize-var1-name:
    37543     # var1->name = "var1"
    37544     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
    37545     (copy-array Heap "var1" %eax)
    37546 $test-shift-mem-by-literal:initialize-literal-type:
    37547     # var type/edx: (payload type-tree) = literal
    37548     68/push 0/imm32/right:null
    37549     68/push 0/imm32/right:null
    37550     68/push 0/imm32/left:unused
    37551     68/push 0/imm32/value:literal
    37552     68/push 1/imm32/is-atom?:true
    37553     68/push 0x11/imm32/alloc-id:fake:payload
    37554     89/<- %edx 4/r32/esp
    37555 $test-shift-mem-by-literal:initialize-literal:
    37556     # var l/edx: (payload var)
    37557     68/push 0/imm32/register
    37558     68/push 0/imm32/register
    37559     68/push 0/imm32/no-stack-offset
    37560     68/push 1/imm32/block-depth
    37561     52/push-edx
    37562     68/push 0x11/imm32/alloc-id:fake
    37563     68/push 0/imm32/name
    37564     68/push 0/imm32/name
    37565     68/push 0x11/imm32/alloc-id:fake:payload
    37566     89/<- %edx 4/r32/esp
    37567 $test-shift-mem-by-literal:initialize-literal-value:
    37568     # l->name = "3"
    37569     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
    37570     (copy-array Heap "3" %eax)
    37571 $test-shift-mem-by-literal:initialize-inouts:
    37572     # var inouts/esi: (payload stmt-var) = [l]
    37573     68/push 0/imm32/is-deref:false
    37574     68/push 0/imm32/next
    37575     68/push 0/imm32/next
    37576     52/push-edx/l
    37577     68/push 0x11/imm32/alloc-id:fake
    37578     68/push 0x11/imm32/alloc-id:fake:payload
    37579     89/<- %esi 4/r32/esp
    37580     # var inouts = (handle stmt-var) = [var1, var2]
    37581     68/push 0/imm32/is-deref:false
    37582     56/push-esi/next
    37583     68/push 0x11/imm32/alloc-id:fake
    37584     51/push-ecx/var1
    37585     68/push 0x11/imm32/alloc-id:fake
    37586     68/push 0x11/imm32/alloc-id:fake:payload
    37587     89/<- %esi 4/r32/esp
    37588 $test-shift-mem-by-literal:initialize-stmt:
    37589     # var stmt/esi: (addr statement)
    37590     68/push 0/imm32/next
    37591     68/push 0/imm32/next
    37592     68/push 0/imm32/outputs
    37593     68/push 0/imm32/outputs
    37594     56/push-esi/inouts
    37595     68/push 0x11/imm32/alloc-id:fake
    37596     68/push 0/imm32/operation
    37597     68/push 0/imm32/operation
    37598     68/push 1/imm32/tag:stmt1
    37599     89/<- %esi 4/r32/esp
    37600 $test-shift-mem-by-literal:initialize-stmt-operation:
    37601     # stmt->operation = "shift-left"
    37602     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
    37603     (copy-array Heap "shift-left" %eax)
    37604     # convert
    37605     c7 0/subop/copy *Curr-block-depth 0/imm32
    37606     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
    37607     (flush _test-output-buffered-file)
    37608 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
    37614     # check output
    37615     (check-next-stream-line-equal _test-output-stream "c1/shift 4/subop/left *(ebp+0x00000008) 3/imm8" "F - test-shift-mem-by-literal")
    37616     # . epilogue
    37617     89/<- %esp 5/r32/ebp
    37618     5d/pop-to-ebp
    37619     c3/return
    37620
    37621 test-compare-reg-with-reg:
    37622     #   compare var1/ecx, var2/eax
    37623     # =>
    37624     #   39/compare %ecx 0/r32/eax
    37625     #
    37626     # . prologue
    37627     55/push-ebp
    37628     89/<- %ebp 4/r32/esp
    37629     # setup
    37630     (clear-stream _test-output-stream)
    37631     (clear-stream $_test-output-buffered-file->buffer)
    37632 $test-compare-reg-with-reg:initialize-type:
    37633     # var type/ecx: (payload type-tree) = int
    37634     68/push 0/imm32/right:null
    37635     68/push 0/imm32/right:null
    37636     68/push 0/imm32/left:unused
    37637     68/push 1/imm32/value:int
    37638     68/push 1/imm32/is-atom?:true
    37639     68/push 0x11/imm32/alloc-id:fake:payload
    37640     89/<- %ecx 4/r32/esp
    37641 $test-compare-reg-with-reg:initialize-var1:
    37642     # var var1/ecx: (payload var)
    37643     68/push 0/imm32/register
    37644     68/push 0/imm32/register
    37645     68/push 0/imm32/no-stack-offset
    37646     68/push 1/imm32/block-depth
    37647     51/push-ecx
    37648     68/push 0x11/imm32/alloc-id:fake
    37649     68/push 0/imm32/name
    37650     68/push 0/imm32/name
    37651     68/push 0x11/imm32/alloc-id:fake:payload
    37652     89/<- %ecx 4/r32/esp
    37653 $test-compare-reg-with-reg:initialize-var1-name:
    37654     # var1->name = "var1"
    37655     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
    37656     (copy-array Heap "var1" %eax)
    37657 $test-compare-reg-with-reg:initialize-var1-register:
    37658     # var1->register = "ecx"
    37659     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
    37660     (copy-array Heap "ecx" %eax)
    37661 $test-compare-reg-with-reg:initialize-var2:
    37662     # var var2/edx: (payload var)
    37663     68/push 0/imm32/register
    37664     68/push 0/imm32/register
    37665     68/push 0/imm32/no-stack-offset
    37666     68/push 1/imm32/block-depth
    37667     ff 6/subop/push *(ecx+0x10)
    37668     68/push 0x11/imm32/alloc-id:fake
    37669     68/push 0/imm32/name
    37670     68/push 0/imm32/name
    37671     68/push 0x11/imm32/alloc-id:fake:payload
    37672     89/<- %edx 4/r32/esp
    37673 $test-compare-reg-with-reg:initialize-var2-name:
    37674     # var2->name = "var2"
    37675     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
    37676     (copy-array Heap "var2" %eax)
    37677 $test-compare-reg-with-reg:initialize-var2-register:
    37678     # var2->register = "eax"
    37679     8d/copy-address *(edx+0x1c) 0/r32/eax  # Var-register + 4
    37680     (copy-array Heap "eax" %eax)
    37681 $test-compare-reg-with-reg:initialize-inouts:
    37682     # var inouts/esi: (payload stmt-var) = [var2]
    37683     68/push 0/imm32/is-deref:false
    37684     68/push 0/imm32/next
    37685     68/push 0/imm32/next
    37686     52/push-edx/var2
    37687     68/push 0x11/imm32/alloc-id:fake
    37688     68/push 0x11/imm32/alloc-id:fake:payload
    37689     89/<- %esi 4/r32/esp
    37690     # inouts = [var1, var2]
    37691     68/push 0/imm32/is-deref:false
    37692     56/push-esi/next
    37693     68/push 0x11/imm32/alloc-id:fake
    37694     51/push-ecx/var1
    37695     68/push 0x11/imm32/alloc-id:fake
    37696     68/push 0x11/imm32/alloc-id:fake:payload
    37697     89/<- %esi 4/r32/esp
    37698 $test-compare-reg-with-reg:initialize-stmt:
    37699     # var stmt/esi: (addr statement)
    37700     68/push 0/imm32/next
    37701     68/push 0/imm32/next
    37702     68/push 0/imm32/outputs
    37703     68/push 0/imm32/outputs
    37704     56/push-esi/inouts
    37705     68/push 0x11/imm32/alloc-id:fake
    37706     68/push 0/imm32/operation
    37707     68/push 0/imm32/operation
    37708     68/push 1/imm32/tag:stmt1
    37709     89/<- %esi 4/r32/esp
    37710 $test-compare-reg-with-reg:initialize-stmt-operation:
    37711     # stmt->operation = "compare"
    37712     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
    37713     (copy-array Heap "compare" %eax)
    37714     # convert
    37715     c7 0/subop/copy *Curr-block-depth 0/imm32
    37716     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
    37717     (flush _test-output-buffered-file)
    37718 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
    37724     # check output
    37725     (check-next-stream-line-equal _test-output-stream "39/compare-> %ecx 0x00000000/r32" "F - test-compare-reg-with-reg")
    37726     # . epilogue
    37727     89/<- %esp 5/r32/ebp
    37728     5d/pop-to-ebp
    37729     c3/return
    37730
    37731 test-compare-mem-with-reg:
    37732     #   compare var1, var2/eax
    37733     # =>
    37734     #   39/compare *(ebp+___) 0/r32/eax
    37735     #
    37736     # . prologue
    37737     55/push-ebp
    37738     89/<- %ebp 4/r32/esp
    37739     # setup
    37740     (clear-stream _test-output-stream)
    37741     (clear-stream $_test-output-buffered-file->buffer)
    37742 $test-compare-mem-with-reg:initialize-type:
    37743     # var type/ecx: (payload type-tree) = int
    37744     68/push 0/imm32/right:null
    37745     68/push 0/imm32/right:null
    37746     68/push 0/imm32/left:unused
    37747     68/push 1/imm32/value:int
    37748     68/push 1/imm32/is-atom?:true
    37749     68/push 0x11/imm32/alloc-id:fake:payload
    37750     89/<- %ecx 4/r32/esp
    37751 $test-compare-mem-with-reg:initialize-var1:
    37752     # var var1/ecx: (payload var)
    37753     68/push 0/imm32/register
    37754     68/push 0/imm32/register
    37755     68/push 8/imm32/stack-offset
    37756     68/push 1/imm32/block-depth
    37757     51/push-ecx
    37758     68/push 0x11/imm32/alloc-id:fake
    37759     68/push 0/imm32/name
    37760     68/push 0/imm32/name
    37761     68/push 0x11/imm32/alloc-id:fake:payload
    37762     89/<- %ecx 4/r32/esp
    37763 $test-compare-mem-with-reg:initialize-var1-name:
    37764     # var1->name = "var1"
    37765     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
    37766     (copy-array Heap "var1" %eax)
    37767 $test-compare-mem-with-reg:initialize-var2:
    37768     # var var2/edx: (payload var)
    37769     68/push 0/imm32/register
    37770     68/push 0/imm32/register
    37771     68/push 0/imm32/no-stack-offset
    37772     68/push 1/imm32/block-depth
    37773     ff 6/subop/push *(ecx+0x10)
    37774     68/push 0x11/imm32/alloc-id:fake
    37775     68/push 0/imm32/name
    37776     68/push 0/imm32/name
    37777     68/push 0x11/imm32/alloc-id:fake:payload
    37778     89/<- %edx 4/r32/esp
    37779 $test-compare-mem-with-reg:initialize-var2-name:
    37780     # var2->name = "var2"
    37781     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
    37782     (copy-array Heap "var2" %eax)
    37783 $test-compare-mem-with-reg:initialize-var2-register:
    37784     # var2->register = "eax"
    37785     8d/copy-address *(edx+0x1c) 0/r32/eax  # Var-register + 4
    37786     (copy-array Heap "eax" %eax)
    37787 $test-compare-mem-with-reg:initialize-inouts:
    37788     # var inouts/esi: (payload stmt-var) = [var2]
    37789     68/push 0/imm32/is-deref:false
    37790     68/push 0/imm32/next
    37791     68/push 0/imm32/next
    37792     52/push-edx/var2
    37793     68/push 0x11/imm32/alloc-id:fake
    37794     68/push 0x11/imm32/alloc-id:fake:payload
    37795     89/<- %esi 4/r32/esp
    37796     # inouts = [var1, var2]
    37797     68/push 0/imm32/is-deref:false
    37798     56/push-esi/next
    37799     68/push 0x11/imm32/alloc-id:fake
    37800     51/push-ecx/var1
    37801     68/push 0x11/imm32/alloc-id:fake
    37802     68/push 0x11/imm32/alloc-id:fake:payload
    37803     89/<- %esi 4/r32/esp
    37804 $test-compare-mem-with-reg:initialize-stmt:
    37805     # var stmt/esi: (addr statement)
    37806     68/push 0/imm32/next
    37807     68/push 0/imm32/next
    37808     68/push 0/imm32/outputs
    37809     68/push 0/imm32/outputs
    37810     56/push-esi/inouts
    37811     68/push 0x11/imm32/alloc-id:fake
    37812     68/push 0/imm32/operation
    37813     68/push 0/imm32/operation
    37814     68/push 1/imm32/tag:stmt1
    37815     89/<- %esi 4/r32/esp
    37816 $test-compare-mem-with-reg:initialize-stmt-operation:
    37817     # stmt->operation = "compare"
    37818     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
    37819     (copy-array Heap "compare" %eax)
    37820     # convert
    37821     c7 0/subop/copy *Curr-block-depth 0/imm32
    37822     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
    37823     (flush _test-output-buffered-file)
    37824 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
    37830     # check output
    37831     (check-next-stream-line-equal _test-output-stream "39/compare-> *(ebp+0x00000008) 0x00000000/r32" "F - test-compare-mem-with-reg")
    37832     # . epilogue
    37833     89/<- %esp 5/r32/ebp
    37834     5d/pop-to-ebp
    37835     c3/return
    37836
    37837 test-compare-reg-with-mem:
    37838     #   compare var1/eax, var2
    37839     # =>
    37840     #   3b/compare<- *(ebp+___) 0/r32/eax
    37841     #
    37842     # . prologue
    37843     55/push-ebp
    37844     89/<- %ebp 4/r32/esp
    37845     # setup
    37846     (clear-stream _test-output-stream)
    37847     (clear-stream $_test-output-buffered-file->buffer)
    37848 $test-compare-reg-with-mem:initialize-type:
    37849     # var type/ecx: (payload type-tree) = int
    37850     68/push 0/imm32/right:null
    37851     68/push 0/imm32/right:null
    37852     68/push 0/imm32/left:unused
    37853     68/push 1/imm32/value:int
    37854     68/push 1/imm32/is-atom?:true
    37855     68/push 0x11/imm32/alloc-id:fake:payload
    37856     89/<- %ecx 4/r32/esp
    37857 $test-compare-reg-with-mem:initialize-var1:
    37858     # var var1/ecx: (payload var)
    37859     68/push 0/imm32/register
    37860     68/push 0/imm32/register
    37861     68/push 0/imm32/no-stack-offset
    37862     68/push 1/imm32/block-depth
    37863     51/push-ecx
    37864     68/push 0x11/imm32/alloc-id:fake
    37865     68/push 0/imm32/name
    37866     68/push 0/imm32/name
    37867     68/push 0x11/imm32/alloc-id:fake:payload
    37868     89/<- %ecx 4/r32/esp
    37869 $test-compare-reg-with-mem:initialize-var1-name:
    37870     # var1->name = "var1"
    37871     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
    37872     (copy-array Heap "var1" %eax)
    37873 $test-compare-reg-with-mem:initialize-var1-register:
    37874     # var1->register = "eax"
    37875     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
    37876     (copy-array Heap "eax" %eax)
    37877 $test-compare-reg-with-mem:initialize-var2:
    37878     # var var2/edx: (payload var)
    37879     68/push 0/imm32/register
    37880     68/push 0/imm32/register
    37881     68/push 8/imm32/stack-offset
    37882     68/push 1/imm32/block-depth
    37883     ff 6/subop/push *(ecx+0x10)
    37884     68/push 0x11/imm32/alloc-id:fake
    37885     68/push 0/imm32/name
    37886     68/push 0/imm32/name
    37887     68/push 0x11/imm32/alloc-id:fake:payload
    37888     89/<- %edx 4/r32/esp
    37889 $test-compare-reg-with-mem:initialize-var2-name:
    37890     # var2->name = "var2"
    37891     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
    37892     (copy-array Heap "var2" %eax)
    37893 $test-compare-reg-with-mem:initialize-inouts:
    37894     # var inouts/esi: (payload stmt-var) = [var2]
    37895     68/push 0/imm32/is-deref:false
    37896     68/push 0/imm32/next
    37897     68/push 0/imm32/next
    37898     52/push-edx/var2
    37899     68/push 0x11/imm32/alloc-id:fake
    37900     68/push 0x11/imm32/alloc-id:fake:payload
    37901     89/<- %esi 4/r32/esp
    37902     # inouts = [var1, var2]
    37903     68/push 0/imm32/is-deref:false
    37904     56/push-esi/next
    37905     68/push 0x11/imm32/alloc-id:fake
    37906     51/push-ecx/var1
    37907     68/push 0x11/imm32/alloc-id:fake
    37908     68/push 0x11/imm32/alloc-id:fake:payload
    37909     89/<- %esi 4/r32/esp
    37910 $test-compare-reg-with-mem:initialize-stmt:
    37911     # var stmt/esi: (addr statement)
    37912     68/push 0/imm32/next
    37913     68/push 0/imm32/next
    37914     68/push 0/imm32/outputs
    37915     68/push 0/imm32/outputs
    37916     56/push-esi/inouts
    37917     68/push 0x11/imm32/alloc-id:fake
    37918     68/push 0/imm32/operation
    37919     68/push 0/imm32/operation
    37920     68/push 1/imm32/tag:stmt1
    37921     89/<- %esi 4/r32/esp
    37922 $test-compare-reg-with-mem:initialize-stmt-operation:
    37923     # stmt->operation = "compare"
    37924     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
    37925     (copy-array Heap "compare" %eax)
    37926     # convert
    37927     c7 0/subop/copy *Curr-block-depth 0/imm32
    37928     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
    37929     (flush _test-output-buffered-file)
    37930 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
    37936     # check output
    37937     (check-next-stream-line-equal _test-output-stream "3b/compare<- *(ebp+0x00000008) 0x00000000/r32" "F - test-compare-reg-with-mem")
    37938     # . epilogue
    37939     89/<- %esp 5/r32/ebp
    37940     5d/pop-to-ebp
    37941     c3/return
    37942
    37943 test-compare-mem-with-literal:
    37944     #   compare var1, 0x34
    37945     # =>
    37946     #   81 7/subop/compare *(ebp+___) 0x34/imm32
    37947     #
    37948     # . prologue
    37949     55/push-ebp
    37950     89/<- %ebp 4/r32/esp
    37951     # setup
    37952     (clear-stream _test-output-stream)
    37953     (clear-stream $_test-output-buffered-file->buffer)
    37954 $test-compare-mem-with-literal:initialize-type:
    37955     # var type/ecx: (payload type-tree) = int
    37956     68/push 0/imm32/right:null
    37957     68/push 0/imm32/right:null
    37958     68/push 0/imm32/left:unused
    37959     68/push 1/imm32/value:int
    37960     68/push 1/imm32/is-atom?:true
    37961     68/push 0x11/imm32/alloc-id:fake:payload
    37962     89/<- %ecx 4/r32/esp
    37963 $test-compare-mem-with-literal:initialize-var1:
    37964     # var var1/ecx: (payload var)
    37965     68/push 0/imm32/register
    37966     68/push 0/imm32/register
    37967     68/push 8/imm32/stack-offset
    37968     68/push 1/imm32/block-depth
    37969     51/push-ecx
    37970     68/push 0x11/imm32/alloc-id:fake
    37971     68/push 0/imm32/name
    37972     68/push 0/imm32/name
    37973     68/push 0x11/imm32/alloc-id:fake:payload
    37974     89/<- %ecx 4/r32/esp
    37975 $test-compare-mem-with-literal:initialize-var1-name:
    37976     # var1->name = "var1"
    37977     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
    37978     (copy-array Heap "var1" %eax)
    37979 $test-compare-mem-with-literal:initialize-literal-type:
    37980     # var type/edx: (payload type-tree) = literal
    37981     68/push 0/imm32/right:null
    37982     68/push 0/imm32/right:null
    37983     68/push 0/imm32/left:unused
    37984     68/push 0/imm32/value:literal
    37985     68/push 1/imm32/is-atom?:true
    37986     68/push 0x11/imm32/alloc-id:fake:payload
    37987     89/<- %edx 4/r32/esp
    37988 $test-compare-mem-with-literal:initialize-literal:
    37989     # var l/edx: (payload var)
    37990     68/push 0/imm32/register
    37991     68/push 0/imm32/register
    37992     68/push 0/imm32/no-stack-offset
    37993     68/push 1/imm32/block-depth
    37994     52/push-edx
    37995     68/push 0x11/imm32/alloc-id:fake
    37996     68/push 0/imm32/name
    37997     68/push 0/imm32/name
    37998     68/push 0x11/imm32/alloc-id:fake:payload
    37999     89/<- %edx 4/r32/esp
    38000 $test-compare-mem-with-literal:initialize-literal-value:
    38001     # l->name = "0x34"
    38002     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
    38003     (copy-array Heap "0x34" %eax)
    38004 $test-compare-mem-with-literal:initialize-inouts:
    38005     # var inouts/esi: (payload stmt-var) = [l]
    38006     68/push 0/imm32/is-deref:false
    38007     68/push 0/imm32/next
    38008     68/push 0/imm32/next
    38009     52/push-edx/l
    38010     68/push 0x11/imm32/alloc-id:fake
    38011     68/push 0x11/imm32/alloc-id:fake:payload
    38012     89/<- %esi 4/r32/esp
    38013     # var inouts = (handle stmt-var) = [var1, var2]
    38014     68/push 0/imm32/is-deref:false
    38015     56/push-esi/next
    38016     68/push 0x11/imm32/alloc-id:fake
    38017     51/push-ecx/var1
    38018     68/push 0x11/imm32/alloc-id:fake
    38019     68/push 0x11/imm32/alloc-id:fake:payload
    38020     89/<- %esi 4/r32/esp
    38021 $test-compare-mem-with-literal:initialize-stmt:
    38022     # var stmt/esi: (addr statement)
    38023     68/push 0/imm32/next
    38024     68/push 0/imm32/next
    38025     68/push 0/imm32/outputs
    38026     68/push 0/imm32/outputs
    38027     56/push-esi/inouts
    38028     68/push 0x11/imm32/alloc-id:fake
    38029     68/push 0/imm32/operation
    38030     68/push 0/imm32/operation
    38031     68/push 1/imm32/tag:stmt1
    38032     89/<- %esi 4/r32/esp
    38033 $test-compare-mem-with-literal:initialize-stmt-operation:
    38034     # stmt->operation = "compare"
    38035     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
    38036     (copy-array Heap "compare" %eax)
    38037     # convert
    38038     c7 0/subop/copy *Curr-block-depth 0/imm32
    38039     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
    38040     (flush _test-output-buffered-file)
    38041 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
    38047     # check output
    38048     (check-next-stream-line-equal _test-output-stream "81 7/subop/compare *(ebp+0x00000008) 0x34/imm32" "F - test-compare-mem-with-literal")
    38049     # . epilogue
    38050     89/<- %esp 5/r32/ebp
    38051     5d/pop-to-ebp
    38052     c3/return
    38053
    38054 test-compare-eax-with-literal:
    38055     #   compare var1/eax 0x34
    38056     # =>
    38057     #   3d/compare-eax-with 0x34/imm32
    38058     #
    38059     # . prologue
    38060     55/push-ebp
    38061     89/<- %ebp 4/r32/esp
    38062     # setup
    38063     (clear-stream _test-output-stream)
    38064     (clear-stream $_test-output-buffered-file->buffer)
    38065 $test-compare-eax-with-literal:initialize-type:
    38066     # var type/ecx: (payload type-tree) = int
    38067     68/push 0/imm32/right:null
    38068     68/push 0/imm32/right:null
    38069     68/push 0/imm32/left:unused
    38070     68/push 1/imm32/value:int
    38071     68/push 1/imm32/is-atom?:true
    38072     68/push 0x11/imm32/alloc-id:fake:payload
    38073     89/<- %ecx 4/r32/esp
    38074 $test-compare-eax-with-literal:initialize-var1:
    38075     # var var1/ecx: (payload var)
    38076     68/push 0/imm32/register
    38077     68/push 0/imm32/register
    38078     68/push 0/imm32/no-stack-offset
    38079     68/push 1/imm32/block-depth
    38080     51/push-ecx
    38081     68/push 0x11/imm32/alloc-id:fake
    38082     68/push 0/imm32/name
    38083     68/push 0/imm32/name
    38084     68/push 0x11/imm32/alloc-id:fake:payload
    38085     89/<- %ecx 4/r32/esp
    38086 $test-compare-eax-with-literal:initialize-var1-name:
    38087     # var1->name = "var1"
    38088     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
    38089     (copy-array Heap "var1" %eax)
    38090 $test-compare-eax-with-literal:initialize-var1-register:
    38091     # v->register = "eax"
    38092     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
    38093     (copy-array Heap "eax" %eax)
    38094 $test-compare-eax-with-literal:initialize-literal-type:
    38095     # var type/edx: (payload type-tree) = literal
    38096     68/push 0/imm32/right:null
    38097     68/push 0/imm32/right:null
    38098     68/push 0/imm32/left:unused
    38099     68/push 0/imm32/value:literal
    38100     68/push 1/imm32/is-atom?:true
    38101     68/push 0x11/imm32/alloc-id:fake:payload
    38102     89/<- %edx 4/r32/esp
    38103 $test-compare-eax-with-literal:initialize-literal:
    38104     # var l/edx: (payload var)
    38105     68/push 0/imm32/register
    38106     68/push 0/imm32/register
    38107     68/push 0/imm32/no-stack-offset
    38108     68/push 1/imm32/block-depth
    38109     52/push-edx
    38110     68/push 0x11/imm32/alloc-id:fake
    38111     68/push 0/imm32/name
    38112     68/push 0/imm32/name
    38113     68/push 0x11/imm32/alloc-id:fake:payload
    38114     89/<- %edx 4/r32/esp
    38115 $test-compare-eax-with-literal:initialize-literal-value:
    38116     # l->name = "0x34"
    38117     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
    38118     (copy-array Heap "0x34" %eax)
    38119 $test-compare-eax-with-literal:initialize-inouts:
    38120     # var inouts/esi: (payload stmt-var) = [l]
    38121     68/push 0/imm32/is-deref:false
    38122     68/push 0/imm32/next
    38123     68/push 0/imm32/next
    38124     52/push-edx/l
    38125     68/push 0x11/imm32/alloc-id:fake
    38126     68/push 0x11/imm32/alloc-id:fake:payload
    38127     89/<- %esi 4/r32/esp
    38128     # var inouts = (handle stmt-var) = [var1, var2]
    38129     68/push 0/imm32/is-deref:false
    38130     56/push-esi/next
    38131     68/push 0x11/imm32/alloc-id:fake
    38132     51/push-ecx/var1
    38133     68/push 0x11/imm32/alloc-id:fake
    38134     68/push 0x11/imm32/alloc-id:fake:payload
    38135     89/<- %esi 4/r32/esp
    38136 $test-compare-eax-with-literal:initialize-stmt:
    38137     # var stmt/esi: (addr statement)
    38138     68/push 0/imm32/next
    38139     68/push 0/imm32/next
    38140     68/push 0/imm32/outputs
    38141     68/push 0/imm32/outputs
    38142     56/push-esi/inouts
    38143     68/push 0x11/imm32/alloc-id:fake
    38144     68/push 0/imm32/operation
    38145     68/push 0/imm32/operation
    38146     68/push 1/imm32/tag:stmt1
    38147     89/<- %esi 4/r32/esp
    38148 $test-compare-eax-with-literal:initialize-stmt-operation:
    38149     # stmt->operation = "compare"
    38150     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
    38151     (copy-array Heap "compare" %eax)
    38152     # convert
    38153     c7 0/subop/copy *Curr-block-depth 0/imm32
    38154     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
    38155     (flush _test-output-buffered-file)
    38156 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
    38162     # check output
    38163     (check-next-stream-line-equal _test-output-stream "3d/compare-eax-with 0x34/imm32" "F - test-compare-eax-with-literal")
    38164     # . epilogue
    38165     89/<- %esp 5/r32/ebp
    38166     5d/pop-to-ebp
    38167     c3/return
    38168
    38169 test-compare-reg-with-literal:
    38170     #   compare var1/ecx 0x34
    38171     # =>
    38172     #   81 7/subop/compare %ecx 0x34/imm32
    38173     #
    38174     # . prologue
    38175     55/push-ebp
    38176     89/<- %ebp 4/r32/esp
    38177     # setup
    38178     (clear-stream _test-output-stream)
    38179     (clear-stream $_test-output-buffered-file->buffer)
    38180 $test-compare-reg-with-literal:initialize-type:
    38181     # var type/ecx: (payload type-tree) = int
    38182     68/push 0/imm32/right:null
    38183     68/push 0/imm32/right:null
    38184     68/push 0/imm32/left:unused
    38185     68/push 1/imm32/value:int
    38186     68/push 1/imm32/is-atom?:true
    38187     68/push 0x11/imm32/alloc-id:fake:payload
    38188     89/<- %ecx 4/r32/esp
    38189 $test-compare-reg-with-literal:initialize-var1:
    38190     # var var1/ecx: (payload var)
    38191     68/push 0/imm32/register
    38192     68/push 0/imm32/register
    38193     68/push 0/imm32/no-stack-offset
    38194     68/push 1/imm32/block-depth
    38195     51/push-ecx
    38196     68/push 0x11/imm32/alloc-id:fake
    38197     68/push 0/imm32/name
    38198     68/push 0/imm32/name
    38199     68/push 0x11/imm32/alloc-id:fake:payload
    38200     89/<- %ecx 4/r32/esp
    38201 $test-compare-reg-with-literal:initialize-var1-name:
    38202     # var1->name = "var1"
    38203     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
    38204     (copy-array Heap "var1" %eax)
    38205 $test-compare-reg-with-literal:initialize-var1-register:
    38206     # v->register = "ecx"
    38207     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
    38208     (copy-array Heap "ecx" %eax)
    38209 $test-compare-reg-with-literal:initialize-literal-type:
    38210     # var type/edx: (payload type-tree) = literal
    38211     68/push 0/imm32/right:null
    38212     68/push 0/imm32/right:null
    38213     68/push 0/imm32/left:unused
    38214     68/push 0/imm32/value:literal
    38215     68/push 1/imm32/is-atom?:true
    38216     68/push 0x11/imm32/alloc-id:fake:payload
    38217     89/<- %edx 4/r32/esp
    38218 $test-compare-reg-with-literal:initialize-literal:
    38219     # var l/edx: (payload var)
    38220     68/push 0/imm32/register
    38221     68/push 0/imm32/register
    38222     68/push 0/imm32/no-stack-offset
    38223     68/push 1/imm32/block-depth
    38224     52/push-edx
    38225     68/push 0x11/imm32/alloc-id:fake
    38226     68/push 0/imm32/name
    38227     68/push 0/imm32/name
    38228     68/push 0x11/imm32/alloc-id:fake:payload
    38229     89/<- %edx 4/r32/esp
    38230 $test-compare-reg-with-literal:initialize-literal-value:
    38231     # l->name = "0x34"
    38232     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
    38233     (copy-array Heap "0x34" %eax)
    38234 $test-compare-reg-with-literal:initialize-inouts:
    38235     # var inouts/esi: (payload stmt-var) = [l]
    38236     68/push 0/imm32/is-deref:false
    38237     68/push 0/imm32/next
    38238     68/push 0/imm32/next
    38239     52/push-edx/l
    38240     68/push 0x11/imm32/alloc-id:fake
    38241     68/push 0x11/imm32/alloc-id:fake:payload
    38242     89/<- %esi 4/r32/esp
    38243     # var inouts = (handle stmt-var) = [var1, var2]
    38244     68/push 0/imm32/is-deref:false
    38245     56/push-esi/next
    38246     68/push 0x11/imm32/alloc-id:fake
    38247     51/push-ecx/var1
    38248     68/push 0x11/imm32/alloc-id:fake
    38249     68/push 0x11/imm32/alloc-id:fake:payload
    38250     89/<- %esi 4/r32/esp
    38251 $test-compare-reg-with-literal:initialize-stmt:
    38252     # var stmt/esi: (addr statement)
    38253     68/push 0/imm32/next
    38254     68/push 0/imm32/next
    38255     68/push 0/imm32/outputs
    38256     68/push 0/imm32/outputs
    38257     56/push-esi/inouts
    38258     68/push 0x11/imm32/alloc-id:fake
    38259     68/push 0/imm32/operation
    38260     68/push 0/imm32/operation
    38261     68/push 1/imm32/tag:stmt1
    38262     89/<- %esi 4/r32/esp
    38263 $test-compare-reg-with-literal:initialize-stmt-operation:
    38264     # stmt->operation = "compare"
    38265     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
    38266     (copy-array Heap "compare" %eax)
    38267     # convert
    38268     c7 0/subop/copy *Curr-block-depth 0/imm32
    38269     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
    38270     (flush _test-output-buffered-file)
    38271 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
    38277     # check output
    38278     (check-next-stream-line-equal _test-output-stream "81 7/subop/compare %ecx 0x34/imm32" "F - test-compare-reg-with-literal")
    38279     # . epilogue
    38280     89/<- %esp 5/r32/ebp
    38281     5d/pop-to-ebp
    38282     c3/return
    38283
    38284 test-emit-subx-stmt-function-call:
    38285     # Call a function on a variable on the stack.
    38286     #   f foo
    38287     # =>
    38288     #   (f *(ebp-8))
    38289     # (Changing the function name supports overloading in general, but here it
    38290     # just serves to help disambiguate things.)
    38291     #
    38292     # There's a variable on the var stack as follows:
    38293     #   name: 'foo'
    38294     #   type: int
    38295     #   stack-offset: -8
    38296     #
    38297     # There's nothing in primitives.
    38298     #
    38299     # We don't perform any checking here on the type of 'f'.
    38300     #
    38301     # . prologue
    38302     55/push-ebp
    38303     89/<- %ebp 4/r32/esp
    38304     # setup
    38305     (clear-stream _test-output-stream)
    38306     (clear-stream $_test-output-buffered-file->buffer)
    38307 $test-emit-subx-function-call:initialize-type:
    38308     # var type/ecx: (payload type-tree) = int
    38309     68/push 0/imm32/right:null
    38310     68/push 0/imm32/right:null
    38311     68/push 0/imm32/left:unused
    38312     68/push 1/imm32/value:int
    38313     68/push 1/imm32/is-atom?:true
    38314     68/push 0x11/imm32/alloc-id:fake:payload
    38315     89/<- %ecx 4/r32/esp
    38316 $test-emit-subx-function-call:initialize-var:
    38317     # var var-foo/ecx: (payload var) = var(type)
    38318     68/push 0/imm32/no-register
    38319     68/push 0/imm32/no-register
    38320     68/push -8/imm32/stack-offset
    38321     68/push 1/imm32/block-depth
    38322     51/push-ecx/type
    38323     68/push 0x11/imm32/alloc-id:fake
    38324     68/push 0/imm32/name
    38325     68/push 0/imm32/name
    38326     68/push 0x11/imm32/alloc-id:fake:payload
    38327     89/<- %ecx 4/r32/esp
    38328 $test-emit-subx-function-call:initialize-var-name:
    38329     # var-foo->name = "foo"
    38330     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
    38331     (copy-array Heap "foo" %eax)
    38332 $test-emit-subx-function-call:initialize-stmt-var:
    38333     # var operand/ebx: (payload stmt-var) = stmt-var(var-foo)
    38334     68/push 0/imm32/is-deref:false
    38335     68/push 0/imm32/next
    38336     68/push 0/imm32/next
    38337     51/push-ecx/var-foo
    38338     68/push 0x11/imm32/alloc-id:fake
    38339     68/push 0x11/imm32/alloc-id:fake:payload
    38340     89/<- %ebx 4/r32/esp
    38341 $test-emit-subx-function-call:initialize-stmt:
    38342     # var stmt/esi: (addr statement)
    38343     68/push 0/imm32/no-outputs
    38344     68/push 0/imm32/no-outputs
    38345     53/push-ebx/inouts
    38346     68/push 0x11/imm32/alloc-id:fake
    38347     68/push 0/imm32/operation
    38348     68/push 0/imm32/operation
    38349     68/push 1/imm32/tag
    38350     89/<- %esi 4/r32/esp
    38351 $test-emit-subx-function-call:initialize-stmt-operation:
    38352     # stmt->operation = "f"
    38353     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
    38354     (copy-array Heap "f" %eax)
    38355     # convert
    38356     c7 0/subop/copy *Curr-block-depth 0/imm32
    38357     (emit-subx-stmt _test-output-buffered-file %esi 0 0 Stderr 0)
    38358     (flush _test-output-buffered-file)
    38359 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
    38365     # check output
    38366     (check-next-stream-line-equal _test-output-stream "(f *(ebp+0xfffffff8))" "F - test-emit-subx-stmt-function-call")
    38367     # . epilogue
    38368     89/<- %esp 5/r32/ebp
    38369     5d/pop-to-ebp
    38370     c3/return
    38371
    38372 test-emit-subx-stmt-function-call-with-literal-arg:
    38373     # Call a function on a literal.
    38374     #   f 0x34
    38375     # =>
    38376     #   (f2 0x34)
    38377     #
    38378     # . prologue
    38379     55/push-ebp
    38380     89/<- %ebp 4/r32/esp
    38381     # setup
    38382     (clear-stream _test-output-stream)
    38383     (clear-stream $_test-output-buffered-file->buffer)
    38384 $test-emit-subx-function-call-with-literal-arg:initialize-type:
    38385     # var type/ecx: (payload type-tree) = int
    38386     68/push 0/imm32/right:null
    38387     68/push 0/imm32/right:null
    38388     68/push 0/imm32/left:unused
    38389     68/push 0/imm32/value:literal
    38390     68/push 1/imm32/is-atom?:true
    38391     68/push 0x11/imm32/alloc-id:fake:payload
    38392     89/<- %ecx 4/r32/esp
    38393 $test-emit-subx-function-call-with-literal-arg:initialize-var:
    38394     # var var-foo/ecx: (payload var) = var(lit)
    38395     68/push 0/imm32/no-register
    38396     68/push 0/imm32/no-register
    38397     68/push 0/imm32/no-stack-offset
    38398     68/push 1/imm32/block-depth
    38399     51/push-ecx/type
    38400     68/push 0x11/imm32/alloc-id:fake
    38401     68/push 0/imm32/name
    38402     68/push 0/imm32/name
    38403     68/push 0x11/imm32/alloc-id:fake:payload
    38404     89/<- %ecx 4/r32/esp
    38405 $test-emit-subx-function-call-with-literal-arg:initialize-var-name:
    38406     # var-foo->name = "0x34"
    38407     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
    38408     (copy-array Heap "0x34" %eax)
    38409 $test-emit-subx-function-call-with-literal-arg:initialize-stmt-var:
    38410     # var operand/ebx: (payload stmt-var) = stmt-var(var-foo)
    38411     68/push 0/imm32/is-deref:false
    38412     68/push 0/imm32/next
    38413     68/push 0/imm32/next
    38414     51/push-ecx/var-foo
    38415     68/push 0x11/imm32/alloc-id:fake
    38416     68/push 0x11/imm32/alloc-id:fake:payload
    38417     89/<- %ebx 4/r32/esp
    38418 $test-emit-subx-function-call-with-literal-arg:initialize-stmt:
    38419     # var stmt/esi: (addr statement)
    38420     68/push 0/imm32/no-outputs
    38421     68/push 0/imm32/no-outputs
    38422     53/push-ebx/inouts
    38423     68/push 0x11/imm32/alloc-id:fake
    38424     68/push 0/imm32/operation
    38425     68/push 0/imm32/operation
    38426     68/push 1/imm32/tag
    38427     89/<- %esi 4/r32/esp
    38428 $test-emit-subx-function-call-with-literal-arg:initialize-stmt-operation:
    38429     # stmt->operation = "f"
    38430     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
    38431     (copy-array Heap "f" %eax)
    38432     # convert
    38433     c7 0/subop/copy *Curr-block-depth 0/imm32
    38434     (emit-subx-stmt _test-output-buffered-file %esi 0 %ebx 0 Stderr 0)
    38435     (flush _test-output-buffered-file)
    38436 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
    38442     # check output
    38443     (check-next-stream-line-equal _test-output-stream "(f 0x34)" "F - test-emit-subx-stmt-function-call-with-literal-arg")
    38444     # . epilogue
    38445     89/<- %esp 5/r32/ebp
    38446     5d/pop-to-ebp
    38447     c3/return
    38448
    38449 emit-indent:  # out: (addr buffered-file), n: int
    38450     # . prologue
    38451     55/push-ebp
    38452     89/<- %ebp 4/r32/esp
    38453     # . save registers
    38454     50/push-eax
    38455     # var i/eax: int = n
    38456     8b/-> *(ebp+0xc) 0/r32/eax
    38457     {
    38458       # if (i <= 0) break
    38459       3d/compare-eax-with 0/imm32
    38460       7e/jump-if-<= break/disp8
    38461       (write-buffered *(ebp+8) "  ")
    38462       48/decrement-eax
    38463       eb/jump loop/disp8
    38464     }
    38465 $emit-indent:end:
    38466     # . restore registers
    38467     58/pop-to-eax
    38468     # . epilogue
    38469     89/<- %esp 5/r32/ebp
    38470     5d/pop-to-ebp
    38471     c3/return
    38472
    38473 emit-subx-prologue:  # out: (addr buffered-file)
    38474     # . prologue
    38475     55/push-ebp
    38476     89/<- %ebp 4/r32/esp
    38477     #
    38478     (write-buffered *(ebp+8) "  # . prologue\n")
    38479     (write-buffered *(ebp+8) "  55/push-ebp\n")
    38480     (write-buffered *(ebp+8) "  89/<- %ebp 4/r32/esp\n")
    38481 $emit-subx-prologue:end:
    38482     # . epilogue
    38483     89/<- %esp 5/r32/ebp
    38484     5d/pop-to-ebp
    38485     c3/return
    38486
    38487 emit-subx-epilogue:  # out: (addr buffered-file)
    38488     # . prologue
    38489     55/push-ebp
    38490     89/<- %ebp 4/r32/esp
    38491     #
    38492     (write-buffered *(ebp+8) "  # . epilogue\n")
    38493     (write-buffered *(ebp+8) "  89/<- %esp 5/r32/ebp\n")
    38494     (write-buffered *(ebp+8) "  5d/pop-to-ebp\n")
    38495     (write-buffered *(ebp+8) "  c3/return\n")
    38496 $emit-subx-epilogue:end:
    38497     # . epilogue
    38498     89/<- %esp 5/r32/ebp
    38499     5d/pop-to-ebp
    38500     c3/return