# 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 "    81 7/subop/compare %eax 0/imm32"  "F - test-convert-index-into-array/11")
     6313     (check-next-stream-line-equal _test-output-stream "    0f 84/jump-if-= __mu-abort-null-index-base-address/disp32"  "F - test-convert-index-into-array/12")
     6314     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + ecx<<0x00000002 + 4) 0x00000000/r32"  "F - test-convert-index-into-array/13")
     6315     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-index-into-array/14")
     6316     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array/15")
     6317     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array/16")
     6318     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array/17")
     6319     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array/18")
     6320     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array/19")
     6321     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array/20")
     6322     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array/21")
     6323     # . epilogue
     6324     89/<- %esp 5/r32/ebp
     6325     5d/pop-to-ebp
     6326     c3/return
     6327
     6328 test-convert-index-into-array-of-bytes:
     6329     # . prologue
     6330     55/push-ebp
     6331     89/<- %ebp 4/r32/esp
     6332     # setup
     6333     (clear-stream _test-input-stream)
     6334     (clear-stream $_test-input-buffered-file->buffer)
     6335     (clear-stream _test-output-stream)
     6336     (clear-stream $_test-output-buffered-file->buffer)
     6337     #
     6338     (write _test-input-stream "fn foo {\n")
     6339     (write _test-input-stream "  var arr/eax: (addr array byte) <- copy 0\n")
     6340     (write _test-input-stream "  var idx/ecx: int <- copy 3\n")
     6341     (write _test-input-stream "  var x/eax: (addr byte) <- index arr, idx\n")
     6342     (write _test-input-stream "}\n")
     6343     # convert
     6344     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     6345     (flush _test-output-buffered-file)
     6346 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     6352     # check output
     6353     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-of-bytes/0")
     6354     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-of-bytes/1")
     6355     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-of-bytes/2")
     6356     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-of-bytes/3")
     6357     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-of-bytes/4")
     6358     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-of-bytes/5")
     6359     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-of-bytes/6")
     6360     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-index-into-array-of-bytes/7")
     6361     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-index-into-array-of-bytes/8")
     6362     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"                  "F - test-convert-index-into-array-of-bytes/9")
     6363     (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")
     6364     (check-next-stream-line-equal _test-output-stream "    81 7/subop/compare %eax 0/imm32"  "F - test-convert-index-into-array-of-bytes/11")
     6365     (check-next-stream-line-equal _test-output-stream "    0f 84/jump-if-= __mu-abort-null-index-base-address/disp32"  "F - test-convert-index-into-array-of-bytes/12")
     6366     (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/13")
     6367     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-index-into-array-of-bytes/14")
     6368     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-of-bytes/15")
     6369     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-of-bytes/16")
     6370     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-of-bytes/17")
     6371     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-of-bytes/18")
     6372     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-of-bytes/19")
     6373     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-of-bytes/20")
     6374     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-of-bytes/21")
     6375     # . epilogue
     6376     89/<- %esp 5/r32/ebp
     6377     5d/pop-to-ebp
     6378     c3/return
     6379
     6380 test-convert-index-into-array-with-literal:
     6381     # . prologue
     6382     55/push-ebp
     6383     89/<- %ebp 4/r32/esp
     6384     # setup
     6385     (clear-stream _test-input-stream)
     6386     (clear-stream $_test-input-buffered-file->buffer)
     6387     (clear-stream _test-output-stream)
     6388     (clear-stream $_test-output-buffered-file->buffer)
     6389     #
     6390     (write _test-input-stream "fn foo {\n")
     6391     (write _test-input-stream "  var arr/eax: (addr array int) <- copy 0\n")
     6392     (write _test-input-stream "  var x/eax: (addr int) <- index arr, 2\n")
     6393     (write _test-input-stream "}\n")
     6394     # convert
     6395     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     6396     (flush _test-output-buffered-file)
     6397 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     6403     # check output
     6404     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-with-literal/0")
     6405     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-with-literal/1")
     6406     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-with-literal/2")
     6407     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-with-literal/3")
     6408     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-with-literal/4")
     6409     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-with-literal/5")
     6410     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-with-literal/6")
     6411     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-index-into-array-with-literal/7")
     6412     (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")
     6413     (check-next-stream-line-equal _test-output-stream "    81 7/subop/compare %eax 0/imm32"  "F - test-convert-index-into-array-with-literal/9")
     6414     (check-next-stream-line-equal _test-output-stream "    0f 84/jump-if-= __mu-abort-null-index-base-address/disp32"  "F - test-convert-index-into-array-with-literal/10")
     6415                                                                                  # 2 * 4 bytes/elem + 4 bytes for size = offset 12
     6416     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + 0x0000000c) 0x00000000/r32"  "F - test-convert-index-into-array-with-literal/11")
     6417     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-with-literal/12")
     6418     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-with-literal/13")
     6419     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-with-literal/14")
     6420     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-with-literal/15")
     6421     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-with-literal/16")
     6422     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-with-literal/17")
     6423     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-with-literal/18")
     6424     # . epilogue
     6425     89/<- %esp 5/r32/ebp
     6426     5d/pop-to-ebp
     6427     c3/return
     6428
     6429 test-convert-index-into-array-of-bytes-with-literal:
     6430     # . prologue
     6431     55/push-ebp
     6432     89/<- %ebp 4/r32/esp
     6433     # setup
     6434     (clear-stream _test-input-stream)
     6435     (clear-stream $_test-input-buffered-file->buffer)
     6436     (clear-stream _test-output-stream)
     6437     (clear-stream $_test-output-buffered-file->buffer)
     6438     #
     6439     (write _test-input-stream "fn foo {\n")
     6440     (write _test-input-stream "  var arr/eax: (addr array byte) <- copy 0\n")
     6441     (write _test-input-stream "  var x/eax: (addr byte) <- index arr, 2\n")
     6442     (write _test-input-stream "}\n")
     6443     # convert
     6444     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     6445     (flush _test-output-buffered-file)
     6446 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     6452     # check output
     6453     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-of-bytes-with-literal/0")
     6454     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-of-bytes-with-literal/1")
     6455     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-of-bytes-with-literal/2")
     6456     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-of-bytes-with-literal/3")
     6457     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-of-bytes-with-literal/4")
     6458     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-of-bytes-with-literal/5")
     6459     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-of-bytes-with-literal/6")
     6460     (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")
     6461     (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")
     6462     (check-next-stream-line-equal _test-output-stream "    81 7/subop/compare %eax 0/imm32"  "F - test-convert-index-into-array-of-bytes-with-literal/9")
     6463     (check-next-stream-line-equal _test-output-stream "    0f 84/jump-if-= __mu-abort-null-index-base-address/disp32"  "F - test-convert-index-into-array-of-bytes-with-literal/10")
     6464                                                                                  # 2 * 1 byte/elem + 4 bytes for size = offset 6
     6465     (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/11")
     6466     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-of-bytes-with-literal/12")
     6467     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-of-bytes-with-literal/13")
     6468     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-of-bytes-with-literal/14")
     6469     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-of-bytes-with-literal/15")
     6470     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-of-bytes-with-literal/16")
     6471     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-of-bytes-with-literal/17")
     6472     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-of-bytes-with-literal/18")
     6473     # . epilogue
     6474     89/<- %esp 5/r32/ebp
     6475     5d/pop-to-ebp
     6476     c3/return
     6477
     6478 test-convert-index-into-array-on-stack:
     6479     # . prologue
     6480     55/push-ebp
     6481     89/<- %ebp 4/r32/esp
     6482     # setup
     6483     (clear-stream _test-input-stream)
     6484     (clear-stream $_test-input-buffered-file->buffer)
     6485     (clear-stream _test-output-stream)
     6486     (clear-stream $_test-output-buffered-file->buffer)
     6487     #
     6488     (write _test-input-stream "fn foo {\n")
     6489     (write _test-input-stream "  var arr: (array int 3)\n")
     6490     (write _test-input-stream "  var idx/eax: int <- copy 2\n")
     6491     (write _test-input-stream "  var x/eax: (addr int) <- index arr, idx\n")
     6492     (write _test-input-stream "}\n")
     6493     # convert
     6494     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     6495     (flush _test-output-buffered-file)
     6496 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     6502     # check output
     6503     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-on-stack/0")
     6504     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-on-stack/1")
     6505     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-on-stack/2")
     6506     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-on-stack/3")
     6507     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-on-stack/4")
     6508     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-on-stack/5")
     6509     # var arr
     6510     (check-next-stream-line-equal _test-output-stream "    (push-n-zero-bytes 0x0000000c)"          "F - test-convert-index-into-array-on-stack/6")
     6511     (check-next-stream-line-equal _test-output-stream "    68/push 0x0000000c/imm32"                "F - test-convert-index-into-array-on-stack/7")
     6512     # var idx
     6513     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-on-stack/8")
     6514     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 2/imm32"                  "F - test-convert-index-into-array-on-stack/9")
     6515     (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")
     6516     # var x is at (ebp-0x10) + idx<<2 + 4 = ebp + idx<<2 - 0xc
     6517     (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")
     6518     # reclaim idx
     6519     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-on-stack/12")
     6520     # reclaim arr
     6521     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000010/imm32"    "F - test-convert-index-into-array-on-stack/13")
     6522     #
     6523     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-on-stack/14")
     6524     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-on-stack/15")
     6525     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-on-stack/16")
     6526     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-on-stack/17")
     6527     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-on-stack/18")
     6528     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-on-stack/19")
     6529     # . epilogue
     6530     89/<- %esp 5/r32/ebp
     6531     5d/pop-to-ebp
     6532     c3/return
     6533
     6534 test-convert-index-into-array-on-stack-with-literal:
     6535     # . prologue
     6536     55/push-ebp
     6537     89/<- %ebp 4/r32/esp
     6538     # setup
     6539     (clear-stream _test-input-stream)
     6540     (clear-stream $_test-input-buffered-file->buffer)
     6541     (clear-stream _test-output-stream)
     6542     (clear-stream $_test-output-buffered-file->buffer)
     6543     #
     6544     (write _test-input-stream "fn foo {\n")
     6545     (write _test-input-stream "  var arr: (array int 3)\n")
     6546     (write _test-input-stream "  var x/eax: (addr int) <- index arr, 2\n")
     6547     (write _test-input-stream "}\n")
     6548     # convert
     6549     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     6550     (flush _test-output-buffered-file)
     6551 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     6557     # check output
     6558     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-on-stack-with-literal/0")
     6559     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-on-stack-with-literal/1")
     6560     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-on-stack-with-literal/2")
     6561     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-on-stack-with-literal/3")
     6562     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-on-stack-with-literal/4")
     6563     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-on-stack-with-literal/5")
     6564     # var arr
     6565     (check-next-stream-line-equal _test-output-stream "    (push-n-zero-bytes 0x0000000c)"          "F - test-convert-index-into-array-on-stack-with-literal/6")
     6566     (check-next-stream-line-equal _test-output-stream "    68/push 0x0000000c/imm32"                "F - test-convert-index-into-array-on-stack-with-literal/7")
     6567     # var x
     6568     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-on-stack-with-literal/8")
     6569     (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")
     6570     # x is at (ebp-0x10) + 4 + 2*4 = ebp-4
     6571     (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")
     6572     # reclaim x
     6573     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-on-stack-with-literal/11")
     6574     # reclaim arr
     6575     (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")
     6576     #
     6577     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-on-stack-with-literal/13")
     6578     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-on-stack-with-literal/14")
     6579     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-on-stack-with-literal/15")
     6580     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-on-stack-with-literal/16")
     6581     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-on-stack-with-literal/17")
     6582     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-on-stack-with-literal/18")
     6583     # . epilogue
     6584     89/<- %esp 5/r32/ebp
     6585     5d/pop-to-ebp
     6586     c3/return
     6587
     6588 test-convert-index-into-array-of-bytes-on-stack-with-literal:
     6589     # . prologue
     6590     55/push-ebp
     6591     89/<- %ebp 4/r32/esp
     6592     # setup
     6593     (clear-stream _test-input-stream)
     6594     (clear-stream $_test-input-buffered-file->buffer)
     6595     (clear-stream _test-output-stream)
     6596     (clear-stream $_test-output-buffered-file->buffer)
     6597     #
     6598     (write _test-input-stream "fn foo {\n")
     6599     (write _test-input-stream "  var arr: (array byte 3)\n")
     6600     (write _test-input-stream "  var x/eax: (addr byte) <- index arr, 2\n")
     6601     (write _test-input-stream "}\n")
     6602     # convert
     6603     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     6604     (flush _test-output-buffered-file)
     6605 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     6611     # check output
     6612     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/0")
     6613     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/1")
     6614     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/2")
     6615     (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")
     6616     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/4")
     6617     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/5")
     6618     # var arr
     6619     (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")
     6620     (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")
     6621     # var x
     6622     (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")
     6623     (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")
     6624     # x is at (ebp-7) + 4 + 2 = ebp-1
     6625     (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")
     6626     # reclaim x
     6627     (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")
     6628     # reclaim arr
     6629     (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")
     6630     #
     6631     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/13")
     6632     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/14")
     6633     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/15")
     6634     (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")
     6635     (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")
     6636     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/18")
     6637     # . epilogue
     6638     89/<- %esp 5/r32/ebp
     6639     5d/pop-to-ebp
     6640     c3/return
     6641
     6642 test-convert-index-into-array-using-offset:
     6643     # . prologue
     6644     55/push-ebp
     6645     89/<- %ebp 4/r32/esp
     6646     # setup
     6647     (clear-stream _test-input-stream)
     6648     (clear-stream $_test-input-buffered-file->buffer)
     6649     (clear-stream _test-output-stream)
     6650     (clear-stream $_test-output-buffered-file->buffer)
     6651     #
     6652     (write _test-input-stream "fn foo {\n")
     6653     (write _test-input-stream "  var arr/eax: (addr array int) <- copy 0\n")
     6654     (write _test-input-stream "  var idx/ecx: int <- copy 3\n")
     6655     (write _test-input-stream "  var off/ecx: (offset int) <- compute-offset arr, idx\n")
     6656     (write _test-input-stream "  var x/eax: (addr int) <- index arr, off\n")
     6657     (write _test-input-stream "}\n")
     6658     # convert
     6659     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     6660     (flush _test-output-buffered-file)
     6661 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     6667     # check output
     6668     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-using-offset/0")
     6669     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-using-offset/1")
     6670     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-using-offset/2")
     6671     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-using-offset/3")
     6672     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-using-offset/4")
     6673     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-using-offset/5")
     6674     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-using-offset/6")
     6675     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-index-into-array-using-offset/7")
     6676     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-index-into-array-using-offset/8")
     6677     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"                  "F - test-convert-index-into-array-using-offset/9")
     6678     (check-next-stream-line-equal _test-output-stream "    69/multiply %ecx 0x00000004/imm32 0x00000001/r32"  "F - test-convert-index-into-array-using-offset/10")
     6679     (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")
     6680     (check-next-stream-line-equal _test-output-stream "    81 7/subop/compare %eax 0/imm32"  "F - test-convert-index-into-array-using-offset/12")
     6681     (check-next-stream-line-equal _test-output-stream "    0f 84/jump-if-= __mu-abort-null-index-base-address/disp32"  "F - test-convert-index-into-array-using-offset/13")
     6682     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + ecx + 4) 0x00000000/r32"  "F - test-convert-index-into-array-using-offset/15")
     6683     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-index-into-array-using-offset/16")
     6684     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-using-offset/17")
     6685     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-using-offset/18")
     6686     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-using-offset/19")
     6687     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-using-offset/20")
     6688     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-using-offset/21")
     6689     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-using-offset/22")
     6690     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-using-offset/23")
     6691     # . epilogue
     6692     89/<- %esp 5/r32/ebp
     6693     5d/pop-to-ebp
     6694     c3/return
     6695
     6696 test-convert-index-into-array-of-bytes-using-offset:
     6697     # . prologue
     6698     55/push-ebp
     6699     89/<- %ebp 4/r32/esp
     6700     # setup
     6701     (clear-stream _test-input-stream)
     6702     (clear-stream $_test-input-buffered-file->buffer)
     6703     (clear-stream _test-output-stream)
     6704     (clear-stream $_test-output-buffered-file->buffer)
     6705     #
     6706     (write _test-input-stream "fn foo {\n")
     6707     (write _test-input-stream "  var arr/eax: (addr array byte) <- copy 0\n")
     6708     (write _test-input-stream "  var idx/ecx: int <- copy 3\n")
     6709     (write _test-input-stream "  var off/ecx: (offset byte) <- compute-offset arr, idx\n")
     6710     (write _test-input-stream "  var x/eax: (addr byte) <- index arr, off\n")
     6711     (write _test-input-stream "}\n")
     6712     # convert
     6713     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     6714     (flush _test-output-buffered-file)
     6715 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     6721     # check output
     6722     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-of-bytes-using-offset/0")
     6723     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-of-bytes-using-offset/1")
     6724     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-of-bytes-using-offset/2")
     6725     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-of-bytes-using-offset/3")
     6726     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-of-bytes-using-offset/4")
     6727     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-of-bytes-using-offset/5")
     6728     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-of-bytes-using-offset/6")
     6729     (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")
     6730     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-index-into-array-of-bytes-using-offset/8")
     6731     (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")
     6732     (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")
     6733     (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")
     6734     (check-next-stream-line-equal _test-output-stream "    81 7/subop/compare %eax 0/imm32"  "F - test-convert-index-into-array-of-bytes-using-offset/12")
     6735     (check-next-stream-line-equal _test-output-stream "    0f 84/jump-if-= __mu-abort-null-index-base-address/disp32"  "F - test-convert-index-into-array-of-bytes-using-offset/13")
     6736     (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/14")
     6737     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-index-into-array-of-bytes-using-offset/15")
     6738     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-of-bytes-using-offset/16")
     6739     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-of-bytes-using-offset/17")
     6740     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-of-bytes-using-offset/18")
     6741     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-of-bytes-using-offset/19")
     6742     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-of-bytes-using-offset/20")
     6743     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-of-bytes-using-offset/21")
     6744     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-of-bytes-using-offset/22")
     6745     # . epilogue
     6746     89/<- %esp 5/r32/ebp
     6747     5d/pop-to-ebp
     6748     c3/return
     6749
     6750 test-convert-index-into-array-using-offset-on-stack:
     6751     # . prologue
     6752     55/push-ebp
     6753     89/<- %ebp 4/r32/esp
     6754     # setup
     6755     (clear-stream _test-input-stream)
     6756     (clear-stream $_test-input-buffered-file->buffer)
     6757     (clear-stream _test-output-stream)
     6758     (clear-stream $_test-output-buffered-file->buffer)
     6759     #
     6760     (write _test-input-stream "fn foo {\n")
     6761     (write _test-input-stream "  var arr/eax: (addr array int) <- copy 0\n")
     6762     (write _test-input-stream "  var idx: int\n")
     6763     (write _test-input-stream "  var off/ecx: (offset int) <- compute-offset arr, idx\n")
     6764     (write _test-input-stream "  var x/eax: (addr int) <- index arr, off\n")
     6765     (write _test-input-stream "}\n")
     6766     # convert
     6767     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     6768     (flush _test-output-buffered-file)
     6769 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     6775     # check output
     6776     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-using-offset-on-stack/0")
     6777     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-using-offset-on-stack/1")
     6778     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-using-offset-on-stack/2")
     6779     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-using-offset-on-stack/3")
     6780     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-using-offset-on-stack/4")
     6781     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-using-offset-on-stack/5")
     6782     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-using-offset-on-stack/6")
     6783     (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")
     6784     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"                         "F - test-convert-index-into-array-using-offset-on-stack/8")
     6785     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-index-into-array-using-offset-on-stack/9")
     6786     (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")
     6787     (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")
     6788     (check-next-stream-line-equal _test-output-stream "    81 7/subop/compare %eax 0/imm32"  "F - test-convert-index-into-array-using-offset-on-stack/12")
     6789     (check-next-stream-line-equal _test-output-stream "    0f 84/jump-if-= __mu-abort-null-index-base-address/disp32"  "F - test-convert-index-into-array-using-offset-on-stack/13")
     6790     (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/14")
     6791     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-index-into-array-using-offset-on-stack/15")
     6792     (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/16")
     6793     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-using-offset-on-stack/17")
     6794     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-using-offset-on-stack/18")
     6795     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-using-offset-on-stack/19")
     6796     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-using-offset-on-stack/20")
     6797     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-using-offset-on-stack/21")
     6798     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-using-offset-on-stack/22")
     6799     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-using-offset-on-stack/23")
     6800     # . epilogue
     6801     89/<- %esp 5/r32/ebp
     6802     5d/pop-to-ebp
     6803     c3/return
     6804
     6805 test-convert-index-into-array-of-bytes-using-offset-on-stack:
     6806     # . prologue
     6807     55/push-ebp
     6808     89/<- %ebp 4/r32/esp
     6809     # setup
     6810     (clear-stream _test-input-stream)
     6811     (clear-stream $_test-input-buffered-file->buffer)
     6812     (clear-stream _test-output-stream)
     6813     (clear-stream $_test-output-buffered-file->buffer)
     6814     #
     6815     (write _test-input-stream "fn foo {\n")
     6816     (write _test-input-stream "  var arr/eax: (addr array byte) <- copy 0\n")
     6817     (write _test-input-stream "  var idx: int\n")
     6818     (write _test-input-stream "  var off/ecx: (offset byte) <- compute-offset arr, idx\n")
     6819     (write _test-input-stream "  var x/eax: (addr byte) <- index arr, off\n")
     6820     (write _test-input-stream "}\n")
     6821     # convert
     6822     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     6823     (flush _test-output-buffered-file)
     6824 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     6830     # check output
     6831     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/0")
     6832     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/1")
     6833     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/2")
     6834     (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")
     6835     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/4")
     6836     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/5")
     6837     (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")
     6838     (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")
     6839     (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")
     6840     (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")
     6841     (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")
     6842     (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")
     6843     (check-next-stream-line-equal _test-output-stream "    81 7/subop/compare %eax 0/imm32"  "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/12")
     6844     (check-next-stream-line-equal _test-output-stream "    0f 84/jump-if-= __mu-abort-null-index-base-address/disp32"  "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/13")
     6845     (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/14")
     6846     (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/15")
     6847     (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/16")
     6848     (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/17")
     6849     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/18")
     6850     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/19")
     6851     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/20")
     6852     (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/21")
     6853     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/22")
     6854     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/23")
     6855     # . epilogue
     6856     89/<- %esp 5/r32/ebp
     6857     5d/pop-to-ebp
     6858     c3/return
     6859
     6860 test-convert-function-and-type-definition:
     6861     # . prologue
     6862     55/push-ebp
     6863     89/<- %ebp 4/r32/esp
     6864     # setup
     6865     (clear-stream _test-input-stream)
     6866     (clear-stream $_test-input-buffered-file->buffer)
     6867     (clear-stream _test-output-stream)
     6868     (clear-stream $_test-output-buffered-file->buffer)
     6869     #
     6870     (write _test-input-stream "fn foo a: (addr t) {\n")
     6871     (write _test-input-stream "  var _a/eax: (addr t) <- copy a\n")
     6872     (write _test-input-stream "  var b/ecx: (addr int) <- get _a, x\n")
     6873     (write _test-input-stream "  var c/ecx: (addr int) <- get _a, y\n")
     6874     (write _test-input-stream "}\n")
     6875     (write _test-input-stream "type t {\n")
     6876     (write _test-input-stream "  x: int\n")
     6877     (write _test-input-stream "  y: int\n")
     6878     (write _test-input-stream "}\n")
     6879     # convert
     6880     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     6881     (flush _test-output-buffered-file)
     6882 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     6888     # check output
     6889     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-and-type-definition/0")
     6890     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-and-type-definition/1")
     6891     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-and-type-definition/2")
     6892     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-and-type-definition/3")
     6893     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-and-type-definition/4")
     6894     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-and-type-definition/5")
     6895     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-and-type-definition/6")
     6896     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000000/r32"  "F - test-convert-function-and-type-definition/7")
     6897     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-and-type-definition/8")
     6898     (check-next-stream-line-equal _test-output-stream "    81 7/subop/compare %eax 0/imm32"  "F - test-convert-function-and-type-definition/9")
     6899     (check-next-stream-line-equal _test-output-stream "    0f 84/jump-if-= __mu-abort-null-get-base-address/disp32"  "F - test-convert-function-and-type-definition/10")
     6900     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + 0x00000000) 0x00000001/r32"  "F - test-convert-function-and-type-definition/11")
     6901     (check-next-stream-line-equal _test-output-stream "    81 7/subop/compare %eax 0/imm32"  "F - test-convert-function-and-type-definition/12")
     6902     (check-next-stream-line-equal _test-output-stream "    0f 84/jump-if-= __mu-abort-null-get-base-address/disp32"  "F - test-convert-function-and-type-definition/13")
     6903     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + 0x00000004) 0x00000001/r32"  "F - test-convert-function-and-type-definition/14")
     6904     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-function-and-type-definition/15")
     6905     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax" "F - test-convert-function-and-type-definition/16")
     6906     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-and-type-definition/17")
     6907     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-and-type-definition/18")
     6908     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-and-type-definition/19")
     6909     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-and-type-definition/20")
     6910     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-and-type-definition/21")
     6911     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-and-type-definition/22")
     6912     # . epilogue
     6913     89/<- %esp 5/r32/ebp
     6914     5d/pop-to-ebp
     6915     c3/return
     6916
     6917 test-type-definition-with-array:
     6918     # . prologue
     6919     55/push-ebp
     6920     89/<- %ebp 4/r32/esp
     6921     # setup
     6922     (clear-stream _test-input-stream)
     6923     (clear-stream $_test-input-buffered-file->buffer)
     6924     (clear-stream _test-output-stream)
     6925     (clear-stream $_test-output-buffered-file->buffer)
     6926     (clear-stream _test-error-stream)
     6927     (clear-stream $_test-error-buffered-file->buffer)
     6928     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     6929     68/push 0/imm32
     6930     68/push 0/imm32
     6931     89/<- %edx 4/r32/esp
     6932     (tailor-exit-descriptor %edx 0x10)
     6933     #
     6934     (write _test-input-stream "type t {\n")
     6935     (write _test-input-stream "  a: (array int 3)\n")
     6936     (write _test-input-stream "}\n")
     6937     # convert
     6938     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     6939     # registers except esp clobbered at this point
     6940     # restore ed
     6941     89/<- %edx 4/r32/esp
     6942     (flush _test-output-buffered-file)
     6943     (flush _test-error-buffered-file)
     6944 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     6950     # check output
     6951     (check-stream-equal _test-output-stream  ""  "F - test-type-definition-with-array: output should be empty")
     6952     (check-next-stream-line-equal _test-error-stream  "type t: 'array' elements not allowed for now"  "F - test-type-definition-with-array: error message")
     6953     # check that stop(1) was called
     6954     (check-ints-equal *(edx+4) 2 "F - test-type-definition-with-array: exit status")
     6955     # don't restore from ebp
     6956     81 0/subop/add %esp 8/imm32
     6957     # . epilogue
     6958     5d/pop-to-ebp
     6959     c3/return
     6960
     6961 test-type-definition-with-addr:
     6962     # . prologue
     6963     55/push-ebp
     6964     89/<- %ebp 4/r32/esp
     6965     # setup
     6966     (clear-stream _test-input-stream)
     6967     (clear-stream $_test-input-buffered-file->buffer)
     6968     (clear-stream _test-output-stream)
     6969     (clear-stream $_test-output-buffered-file->buffer)
     6970     (clear-stream _test-error-stream)
     6971     (clear-stream $_test-error-buffered-file->buffer)
     6972     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     6973     68/push 0/imm32
     6974     68/push 0/imm32
     6975     89/<- %edx 4/r32/esp
     6976     (tailor-exit-descriptor %edx 0x10)
     6977     #
     6978     (write _test-input-stream "type t {\n")
     6979     (write _test-input-stream "  a: (addr int)\n")
     6980     (write _test-input-stream "}\n")
     6981     # convert
     6982     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     6983     # registers except esp clobbered at this point
     6984     # restore ed
     6985     89/<- %edx 4/r32/esp
     6986     (flush _test-output-buffered-file)
     6987     (flush _test-error-buffered-file)
     6988 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     6994     # check output
     6995     (check-stream-equal _test-output-stream  ""  "F - test-type-definition-with-addr: output should be empty")
     6996     (check-next-stream-line-equal _test-error-stream  "type t: 'addr' elements not allowed"  "F - test-type-definition-with-addr: error message")
     6997     # check that stop(1) was called
     6998     (check-ints-equal *(edx+4) 2 "F - test-type-definition-with-addr: exit status")
     6999     # don't restore from ebp
     7000     81 0/subop/add %esp 8/imm32
     7001     # . epilogue
     7002     5d/pop-to-ebp
     7003     c3/return
     7004
     7005 test-convert-function-with-local-var-with-user-defined-type:
     7006     # . prologue
     7007     55/push-ebp
     7008     89/<- %ebp 4/r32/esp
     7009     # setup
     7010     (clear-stream _test-input-stream)
     7011     (clear-stream $_test-input-buffered-file->buffer)
     7012     (clear-stream _test-output-stream)
     7013     (clear-stream $_test-output-buffered-file->buffer)
     7014     #
     7015     (write _test-input-stream "fn foo {\n")
     7016     (write _test-input-stream "  var a: t\n")
     7017     (write _test-input-stream "}\n")
     7018     (write _test-input-stream "type t {\n")
     7019     (write _test-input-stream "  x: int\n")
     7020     (write _test-input-stream "  y: int\n")
     7021     (write _test-input-stream "}\n")
     7022     # convert
     7023     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     7024     (flush _test-output-buffered-file)
     7025 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     7031     # check output
     7032     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-with-user-defined-type/0")
     7033     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-with-user-defined-type/1")
     7034     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-with-user-defined-type/2")
     7035     (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")
     7036     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-with-user-defined-type/4")
     7037     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-with-user-defined-type/5")
     7038     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-with-local-var-with-user-defined-type/6")
     7039     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-with-local-var-with-user-defined-type/7")
     7040     (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")
     7041     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-with-user-defined-type/9")
     7042     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-with-user-defined-type/10")
     7043     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-with-user-defined-type/11")
     7044     (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")
     7045     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-with-user-defined-type/13")
     7046     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-with-user-defined-type/14")
     7047     # . epilogue
     7048     89/<- %esp 5/r32/ebp
     7049     5d/pop-to-ebp
     7050     c3/return
     7051
     7052 test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type:
     7053     # . prologue
     7054     55/push-ebp
     7055     89/<- %ebp 4/r32/esp
     7056     # setup
     7057     (clear-stream _test-input-stream)
     7058     (clear-stream $_test-input-buffered-file->buffer)
     7059     (clear-stream _test-output-stream)
     7060     (clear-stream $_test-output-buffered-file->buffer)
     7061     #
     7062     (write _test-input-stream "fn foo {\n")
     7063     (write _test-input-stream "  var a: t\n")
     7064     (write _test-input-stream "}\n")
     7065     (write _test-input-stream "type t {\n")
     7066     (write _test-input-stream "  x: s\n")
     7067     (write _test-input-stream "}\n")
     7068     (write _test-input-stream "type s {\n")
     7069     (write _test-input-stream "  z: int\n")
     7070     (write _test-input-stream "}\n")
     7071     # convert
     7072     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     7073     (flush _test-output-buffered-file)
     7074 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     7080     # check output
     7081     (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")
     7082     (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")
     7083     (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")
     7084     (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")
     7085     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type/4")
     7086     (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")
     7087     (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")
     7088     (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")
     7089     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type/9")
     7090     (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")
     7091     (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")
     7092     (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")
     7093     (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")
     7094     (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")
     7095     # . epilogue
     7096     89/<- %esp 5/r32/ebp
     7097     5d/pop-to-ebp
     7098     c3/return
     7099
     7100 test-convert-function-call-with-arg-of-user-defined-type:
     7101     # . prologue
     7102     55/push-ebp
     7103     89/<- %ebp 4/r32/esp
     7104     # setup
     7105     (clear-stream _test-input-stream)
     7106     (clear-stream $_test-input-buffered-file->buffer)
     7107     (clear-stream _test-output-stream)
     7108     (clear-stream $_test-output-buffered-file->buffer)
     7109     #
     7110     (write _test-input-stream "fn f {\n")
     7111     (write _test-input-stream "  var a: t\n")
     7112     (write _test-input-stream "  foo a\n")
     7113     (write _test-input-stream "}\n")
     7114     (write _test-input-stream "fn foo x: t {\n")
     7115     (write _test-input-stream "}\n")
     7116     (write _test-input-stream "type t {\n")
     7117     (write _test-input-stream "  x: int\n")
     7118     (write _test-input-stream "  y: int\n")
     7119     (write _test-input-stream "}\n")
     7120     # convert
     7121     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     7122     (flush _test-output-buffered-file)
     7123 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     7129     # check output
     7130     (check-next-stream-line-equal _test-output-stream "f:"                      "F - test-convert-function-call-with-arg-of-user-defined-type/0")
     7131     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-arg-of-user-defined-type/1")
     7132     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-arg-of-user-defined-type/2")
     7133     (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")
     7134     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-arg-of-user-defined-type/4")
     7135     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:loop:"     "F - test-convert-function-call-with-arg-of-user-defined-type/5")
     7136     # var a: t
     7137     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-call-with-arg-of-user-defined-type/6")
     7138     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-call-with-arg-of-user-defined-type/7")
     7139     # foo a
     7140     (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")
     7141     #
     7142     (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")
     7143     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-arg-of-user-defined-type/10")
     7144     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:break:"    "F - test-convert-function-call-with-arg-of-user-defined-type/11")
     7145     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-arg-of-user-defined-type/12")
     7146     (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")
     7147     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-arg-of-user-defined-type/14")
     7148     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-arg-of-user-defined-type/15")
     7149     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-call-with-arg-of-user-defined-type/16")
     7150     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-arg-of-user-defined-type/17")
     7151     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-arg-of-user-defined-type/18")
     7152     (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")
     7153     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-arg-of-user-defined-type/20")
     7154     (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")
     7155     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-arg-of-user-defined-type/22")
     7156     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-arg-of-user-defined-type/23")
     7157     # . epilogue
     7158     89/<- %esp 5/r32/ebp
     7159     5d/pop-to-ebp
     7160     c3/return
     7161
     7162 test-convert-function-call-with-arg-of-user-defined-type-register-indirect:
     7163     # . prologue
     7164     55/push-ebp
     7165     89/<- %ebp 4/r32/esp
     7166     # setup
     7167     (clear-stream _test-input-stream)
     7168     (clear-stream $_test-input-buffered-file->buffer)
     7169     (clear-stream _test-output-stream)
     7170     (clear-stream $_test-output-buffered-file->buffer)
     7171     #
     7172     (write _test-input-stream "fn f {\n")
     7173     (write _test-input-stream "  var a/eax: (addr t) <- copy 0\n")
     7174     (write _test-input-stream "  foo *a\n")
     7175     (write _test-input-stream "}\n")
     7176     (write _test-input-stream "fn foo x: t {\n")
     7177     (write _test-input-stream "}\n")
     7178     (write _test-input-stream "type t {\n")
     7179     (write _test-input-stream "  x: int\n")
     7180     (write _test-input-stream "  y: int\n")
     7181     (write _test-input-stream "}\n")
     7182     # convert
     7183     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     7184     (flush _test-output-buffered-file)
     7185 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     7191     # check output
     7192     (check-next-stream-line-equal _test-output-stream "f:"                      "F - test-convert-function-call-with-arg-of-user-defined-type/0")
     7193     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-arg-of-user-defined-type/1")
     7194     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-arg-of-user-defined-type/2")
     7195     (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")
     7196     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-arg-of-user-defined-type/4")
     7197     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:loop:"     "F - test-convert-function-call-with-arg-of-user-defined-type/5")
     7198     # var a
     7199     (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")
     7200     (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")
     7201     # foo a
     7202     (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")
     7203     #
     7204     (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")
     7205     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-arg-of-user-defined-type/10")
     7206     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:break:"    "F - test-convert-function-call-with-arg-of-user-defined-type/11")
     7207     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-arg-of-user-defined-type/12")
     7208     (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")
     7209     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-arg-of-user-defined-type/14")
     7210     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-arg-of-user-defined-type/15")
     7211     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-call-with-arg-of-user-defined-type/16")
     7212     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-arg-of-user-defined-type/17")
     7213     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-arg-of-user-defined-type/18")
     7214     (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")
     7215     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-arg-of-user-defined-type/20")
     7216     (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")
     7217     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-arg-of-user-defined-type/22")
     7218     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-arg-of-user-defined-type/23")
     7219     # . epilogue
     7220     89/<- %esp 5/r32/ebp
     7221     5d/pop-to-ebp
     7222     c3/return
     7223
     7224 # we don't have special support for call-by-reference; just explicitly create
     7225 # a new variable with the address of the arg
     7226 test-convert-function-call-with-arg-of-user-defined-type-by-reference:
     7227     # . prologue
     7228     55/push-ebp
     7229     89/<- %ebp 4/r32/esp
     7230     # setup
     7231     (clear-stream _test-input-stream)
     7232     (clear-stream $_test-input-buffered-file->buffer)
     7233     (clear-stream _test-output-stream)
     7234     (clear-stream $_test-output-buffered-file->buffer)
     7235     #
     7236     (write _test-input-stream "fn f {\n")
     7237     (write _test-input-stream "  var a: t\n")
     7238     (write _test-input-stream "  var b/eax: (addr t) <- address a\n")
     7239     (write _test-input-stream "  foo b\n")
     7240     (write _test-input-stream "}\n")
     7241     (write _test-input-stream "fn foo x: (addr t) {\n")
     7242     (write _test-input-stream "  var x/ecx: (addr t) <- copy x\n")
     7243     (write _test-input-stream "}\n")
     7244     (write _test-input-stream "type t {\n")
     7245     (write _test-input-stream "  x: int\n")
     7246     (write _test-input-stream "  y: int\n")
     7247     (write _test-input-stream "}\n")
     7248     # convert
     7249     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     7250     (flush _test-output-buffered-file)
     7251 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     7257     # check output
     7258     (check-next-stream-line-equal _test-output-stream "f:"                      "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/0")
     7259     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/1")
     7260     (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")
     7261     (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")
     7262     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/4")
     7263     (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")
     7264     # var a: t
     7265     (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")
     7266     (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")
     7267     # var b/eax: (addr t)
     7268     (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")
     7269     (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")
     7270     # foo a
     7271     (check-next-stream-line-equal _test-output-stream "    (foo %eax)"          "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/10")
     7272     #
     7273     (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")
     7274     (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")
     7275     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/13")
     7276     (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")
     7277     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/15")
     7278     (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")
     7279     (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")
     7280     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/18")
     7281     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/19")
     7282     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/20")
     7283     (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")
     7284     (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")
     7285     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/23")
     7286     (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")
     7287     (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")
     7288     (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")
     7289     (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")
     7290     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/28")
     7291     (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")
     7292     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/30")
     7293     (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")
     7294     (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")
     7295     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/33")
     7296     # . epilogue
     7297     89/<- %esp 5/r32/ebp
     7298     5d/pop-to-ebp
     7299     c3/return
     7300
     7301 test-convert-get-on-local-variable:
     7302     # . prologue
     7303     55/push-ebp
     7304     89/<- %ebp 4/r32/esp
     7305     # setup
     7306     (clear-stream _test-input-stream)
     7307     (clear-stream $_test-input-buffered-file->buffer)
     7308     (clear-stream _test-output-stream)
     7309     (clear-stream $_test-output-buffered-file->buffer)
     7310     #
     7311     (write _test-input-stream "fn foo {\n")
     7312     (write _test-input-stream "  var a: t\n")
     7313     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
     7314     (write _test-input-stream "}\n")
     7315     (write _test-input-stream "type t {\n")
     7316     (write _test-input-stream "  x: int\n")
     7317     (write _test-input-stream "  y: int\n")
     7318     (write _test-input-stream "}\n")
     7319     # convert
     7320     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     7321     (flush _test-output-buffered-file)
     7322 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     7328     # check output
     7329     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-get-on-local-variable/0")
     7330     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-get-on-local-variable/1")
     7331     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-get-on-local-variable/2")
     7332     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-get-on-local-variable/3")
     7333     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-get-on-local-variable/4")
     7334     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-get-on-local-variable/5")
     7335     # var a
     7336     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-get-on-local-variable/6")
     7337     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-get-on-local-variable/7")
     7338     # var c
     7339     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-get-on-local-variable/8")
     7340     # get
     7341     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(ebp+0xfffffffc) 0x00000001/r32"  "F - test-convert-get-on-local-variable/9")
     7342     # reclaim c
     7343     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-get-on-local-variable/10")
     7344     # reclaim a
     7345     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000008/imm32"  "F - test-convert-get-on-local-variable/11")
     7346     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-get-on-local-variable/12")
     7347     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-get-on-local-variable/13")
     7348     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-get-on-local-variable/14")
     7349     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-get-on-local-variable/15")
     7350     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-get-on-local-variable/16")
     7351     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-get-on-local-variable/17")
     7352     # . epilogue
     7353     89/<- %esp 5/r32/ebp
     7354     5d/pop-to-ebp
     7355     c3/return
     7356
     7357 test-convert-get-on-function-argument:
     7358     # . prologue
     7359     55/push-ebp
     7360     89/<- %ebp 4/r32/esp
     7361     # setup
     7362     (clear-stream _test-input-stream)
     7363     (clear-stream $_test-input-buffered-file->buffer)
     7364     (clear-stream _test-output-stream)
     7365     (clear-stream $_test-output-buffered-file->buffer)
     7366     #
     7367     (write _test-input-stream "fn foo a: t {\n")
     7368     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
     7369     (write _test-input-stream "}\n")
     7370     (write _test-input-stream "type t {\n")
     7371     (write _test-input-stream "  x: int\n")
     7372     (write _test-input-stream "  y: int\n")
     7373     (write _test-input-stream "}\n")
     7374     # convert
     7375     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     7376     (flush _test-output-buffered-file)
     7377 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     7383     # check output
     7384     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-get-on-function-argument/0")
     7385     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-get-on-function-argument/1")
     7386     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-get-on-function-argument/2")
     7387     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-get-on-function-argument/3")
     7388     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-get-on-function-argument/4")
     7389     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-get-on-function-argument/5")
     7390     # var c
     7391     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-get-on-function-argument/6")
     7392     # get
     7393     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(ebp+0x0000000c) 0x00000001/r32"  "F - test-convert-get-on-function-argument/7")
     7394     # reclaim c
     7395     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-get-on-function-argument/8")
     7396     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-get-on-function-argument/9")
     7397     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-get-on-function-argument/10")
     7398     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-get-on-function-argument/11")
     7399     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-get-on-function-argument/12")
     7400     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-get-on-function-argument/13")
     7401     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-get-on-function-argument/14")
     7402     # . epilogue
     7403     89/<- %esp 5/r32/ebp
     7404     5d/pop-to-ebp
     7405     c3/return
     7406
     7407 test-convert-get-on-function-argument-with-known-type:
     7408     # . prologue
     7409     55/push-ebp
     7410     89/<- %ebp 4/r32/esp
     7411     # setup
     7412     (clear-stream _test-input-stream)
     7413     (clear-stream $_test-input-buffered-file->buffer)
     7414     (clear-stream _test-output-stream)
     7415     (clear-stream $_test-output-buffered-file->buffer)
     7416     #
     7417     (write _test-input-stream "type t {\n")
     7418     (write _test-input-stream "  x: int\n")
     7419     (write _test-input-stream "  y: int\n")
     7420     (write _test-input-stream "}\n")
     7421     (write _test-input-stream "fn foo a: t {\n")
     7422     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
     7423     (write _test-input-stream "}\n")
     7424     # convert
     7425     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     7426     (flush _test-output-buffered-file)
     7427 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
     7433     # check output
     7434     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-get-on-function-argument-with-known-type/0")
     7435     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-get-on-function-argument-with-known-type/1")
     7436     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-get-on-function-argument-with-known-type/2")
     7437     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-get-on-function-argument-with-known-type/3")
     7438     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-get-on-function-argument-with-known-type/4")
     7439     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-get-on-function-argument-with-known-type/5")
     7440     # var c
     7441     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-get-on-function-argument-with-known-type/6")
     7442     # get
     7443     (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")
     7444     # reclaim c
     7445     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-get-on-function-argument-with-known-type/8")
     7446     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-get-on-function-argument-with-known-type/9")
     7447     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-get-on-function-argument-with-known-type/10")
     7448     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-get-on-function-argument-with-known-type/11")
     7449     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-get-on-function-argument-with-known-type/12")
     7450     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-get-on-function-argument-with-known-type/13")
     7451     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-get-on-function-argument-with-known-type/14")
     7452     # . epilogue
     7453     89/<- %esp 5/r32/ebp
     7454     5d/pop-to-ebp
     7455     c3/return
     7456
     7457 test-add-with-too-many-inouts:
     7458     # . prologue
     7459     55/push-ebp
     7460     89/<- %ebp 4/r32/esp
     7461     # setup
     7462     (clear-stream _test-input-stream)
     7463     (clear-stream $_test-input-buffered-file->buffer)
     7464     (clear-stream _test-output-stream)
     7465     (clear-stream $_test-output-buffered-file->buffer)
     7466     (clear-stream _test-error-stream)
     7467     (clear-stream $_test-error-buffered-file->buffer)
     7468     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     7469     68/push 0/imm32
     7470     68/push 0/imm32
     7471     89/<- %edx 4/r32/esp
     7472     (tailor-exit-descriptor %edx 0x10)
     7473     #
     7474     (write _test-input-stream "fn foo {\n")
     7475     (write _test-input-stream "  var a: int\n")
     7476     (write _test-input-stream "  var b/ecx: int <- add a, 0\n")
     7477     (write _test-input-stream "}\n")
     7478     # convert
     7479     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     7480     # registers except esp clobbered at this point
     7481     # restore ed
     7482     89/<- %edx 4/r32/esp
     7483     (flush _test-output-buffered-file)
     7484     (flush _test-error-buffered-file)
     7485 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     7491     # check output
     7492     (check-stream-equal _test-output-stream  ""  "F - test-add-with-too-many-inouts: output should be empty")
     7493     (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")
     7494     # check that stop(1) was called
     7495     (check-ints-equal *(edx+4) 2 "F - test-add-with-too-many-inouts: exit status")
     7496     # don't restore from ebp
     7497     81 0/subop/add %esp 8/imm32
     7498     # . epilogue
     7499     5d/pop-to-ebp
     7500     c3/return
     7501
     7502 test-add-with-too-many-inouts-2:
     7503     # . prologue
     7504     55/push-ebp
     7505     89/<- %ebp 4/r32/esp
     7506     # setup
     7507     (clear-stream _test-input-stream)
     7508     (clear-stream $_test-input-buffered-file->buffer)
     7509     (clear-stream _test-output-stream)
     7510     (clear-stream $_test-output-buffered-file->buffer)
     7511     (clear-stream _test-error-stream)
     7512     (clear-stream $_test-error-buffered-file->buffer)
     7513     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     7514     68/push 0/imm32
     7515     68/push 0/imm32
     7516     89/<- %edx 4/r32/esp
     7517     (tailor-exit-descriptor %edx 0x10)
     7518     #
     7519     (write _test-input-stream "fn foo {\n")
     7520     (write _test-input-stream "  var a: int\n")
     7521     (write _test-input-stream "  add-to a, 0, 1\n")
     7522     (write _test-input-stream "}\n")
     7523     # convert
     7524     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     7525     # registers except esp clobbered at this point
     7526     # restore ed
     7527     89/<- %edx 4/r32/esp
     7528     (flush _test-output-buffered-file)
     7529     (flush _test-error-buffered-file)
     7530 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     7536     # check output
     7537     (check-stream-equal _test-output-stream  ""  "F - test-add-with-too-many-inouts-2: output should be empty")
     7538     (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")
     7539     # check that stop(1) was called
     7540     (check-ints-equal *(edx+4) 2 "F - test-add-with-too-many-inouts-2: exit status")
     7541     # don't restore from ebp
     7542     81 0/subop/add %esp 8/imm32
     7543     # . epilogue
     7544     5d/pop-to-ebp
     7545     c3/return
     7546
     7547 test-add-with-too-many-outputs:
     7548     # . prologue
     7549     55/push-ebp
     7550     89/<- %ebp 4/r32/esp
     7551     # setup
     7552     (clear-stream _test-input-stream)
     7553     (clear-stream $_test-input-buffered-file->buffer)
     7554     (clear-stream _test-output-stream)
     7555     (clear-stream $_test-output-buffered-file->buffer)
     7556     (clear-stream _test-error-stream)
     7557     (clear-stream $_test-error-buffered-file->buffer)
     7558     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     7559     68/push 0/imm32
     7560     68/push 0/imm32
     7561     89/<- %edx 4/r32/esp
     7562     (tailor-exit-descriptor %edx 0x10)
     7563     #
     7564     (write _test-input-stream "fn foo {\n")
     7565     (write _test-input-stream "  var a/eax: int <- copy 0\n")
     7566     (write _test-input-stream "  var b/ebx: int <- copy 0\n")
     7567     (write _test-input-stream "  var c/ecx: int <- copy 0\n")
     7568     (write _test-input-stream "  c, b <- add a\n")
     7569     (write _test-input-stream "}\n")
     7570     # convert
     7571     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     7572     # registers except esp clobbered at this point
     7573     # restore ed
     7574     89/<- %edx 4/r32/esp
     7575     (flush _test-output-buffered-file)
     7576     (flush _test-error-buffered-file)
     7577 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     7583     # check output
     7584     (check-stream-equal _test-output-stream  ""  "F - test-add-with-too-many-outputs: output should be empty")
     7585     (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")
     7586     # check that stop(1) was called
     7587     (check-ints-equal *(edx+4) 2 "F - test-add-with-too-many-outputs: exit status")
     7588     # don't restore from ebp
     7589     81 0/subop/add %esp 8/imm32
     7590     # . epilogue
     7591     5d/pop-to-ebp
     7592     c3/return
     7593
     7594 test-add-with-non-number:
     7595     # . prologue
     7596     55/push-ebp
     7597     89/<- %ebp 4/r32/esp
     7598     # setup
     7599     (clear-stream _test-input-stream)
     7600     (clear-stream $_test-input-buffered-file->buffer)
     7601     (clear-stream _test-output-stream)
     7602     (clear-stream $_test-output-buffered-file->buffer)
     7603     (clear-stream _test-error-stream)
     7604     (clear-stream $_test-error-buffered-file->buffer)
     7605     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     7606     68/push 0/imm32
     7607     68/push 0/imm32
     7608     89/<- %edx 4/r32/esp
     7609     (tailor-exit-descriptor %edx 0x10)
     7610     #
     7611     (write _test-input-stream "fn foo {\n")
     7612     (write _test-input-stream "  var a: int\n")
     7613     (write _test-input-stream "  var b/ecx: (addr int) <- add a\n")
     7614     (write _test-input-stream "}\n")
     7615     # convert
     7616     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     7617     # registers except esp clobbered at this point
     7618     # restore ed
     7619     89/<- %edx 4/r32/esp
     7620     (flush _test-output-buffered-file)
     7621     (flush _test-error-buffered-file)
     7622 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     7628     # check output
     7629     (check-stream-equal _test-output-stream  ""  "F - test-add-with-non-number: output should be empty")
     7630     (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")
     7631     # check that stop(1) was called
     7632     (check-ints-equal *(edx+4) 2 "F - test-add-with-non-number: exit status")
     7633     # don't restore from ebp
     7634     81 0/subop/add %esp 8/imm32
     7635     # . epilogue
     7636     5d/pop-to-ebp
     7637     c3/return
     7638
     7639 test-add-with-addr-dereferenced:
     7640     # . prologue
     7641     55/push-ebp
     7642     89/<- %ebp 4/r32/esp
     7643     # setup
     7644     (clear-stream _test-input-stream)
     7645     (clear-stream $_test-input-buffered-file->buffer)
     7646     (clear-stream _test-output-stream)
     7647     (clear-stream $_test-output-buffered-file->buffer)
     7648     #
     7649     (write _test-input-stream "fn foo {\n")
     7650     (write _test-input-stream "  var a/eax: (addr int) <- copy 0\n")
     7651     (write _test-input-stream "  add-to *a, 1\n")
     7652     (write _test-input-stream "}\n")
     7653     # convert
     7654     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     7655     (flush _test-output-buffered-file)
     7656     # no error
     7657     # . epilogue
     7658     89/<- %esp 5/r32/ebp
     7659     5d/pop-to-ebp
     7660     c3/return
     7661
     7662 test-copy-with-no-inout:
     7663     # . prologue
     7664     55/push-ebp
     7665     89/<- %ebp 4/r32/esp
     7666     # setup
     7667     (clear-stream _test-input-stream)
     7668     (clear-stream $_test-input-buffered-file->buffer)
     7669     (clear-stream _test-output-stream)
     7670     (clear-stream $_test-output-buffered-file->buffer)
     7671     (clear-stream _test-error-stream)
     7672     (clear-stream $_test-error-buffered-file->buffer)
     7673     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     7674     68/push 0/imm32
     7675     68/push 0/imm32
     7676     89/<- %edx 4/r32/esp
     7677     (tailor-exit-descriptor %edx 0x10)
     7678     #
     7679     (write _test-input-stream "fn foo {\n")
     7680     (write _test-input-stream "  var x/eax: boolean <- copy\n")
     7681     (write _test-input-stream "}\n")
     7682     # convert
     7683     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     7684     # registers except esp clobbered at this point
     7685     # restore ed
     7686     89/<- %edx 4/r32/esp
     7687     (flush _test-output-buffered-file)
     7688     (flush _test-error-buffered-file)
     7689 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     7695     # check output
     7696     (check-stream-equal _test-output-stream  ""  "F - test-copy-with-no-inout: output should be empty")
     7697     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy' expects an inout"  "F - test-copy-with-no-inout: error message")
     7698     # check that stop(1) was called
     7699     (check-ints-equal *(edx+4) 2 "F - test-copy-with-no-inout: exit status")
     7700     # don't restore from ebp
     7701     81 0/subop/add %esp 8/imm32
     7702     # . epilogue
     7703     5d/pop-to-ebp
     7704     c3/return
     7705
     7706 test-copy-with-multiple-inouts:
     7707     # . prologue
     7708     55/push-ebp
     7709     89/<- %ebp 4/r32/esp
     7710     # setup
     7711     (clear-stream _test-input-stream)
     7712     (clear-stream $_test-input-buffered-file->buffer)
     7713     (clear-stream _test-output-stream)
     7714     (clear-stream $_test-output-buffered-file->buffer)
     7715     (clear-stream _test-error-stream)
     7716     (clear-stream $_test-error-buffered-file->buffer)
     7717     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     7718     68/push 0/imm32
     7719     68/push 0/imm32
     7720     89/<- %edx 4/r32/esp
     7721     (tailor-exit-descriptor %edx 0x10)
     7722     #
     7723     (write _test-input-stream "fn foo {\n")
     7724     (write _test-input-stream "  var x/eax: boolean <- copy 0, 0\n")
     7725     (write _test-input-stream "}\n")
     7726     # convert
     7727     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     7728     # registers except esp clobbered at this point
     7729     # restore ed
     7730     89/<- %edx 4/r32/esp
     7731     (flush _test-output-buffered-file)
     7732     (flush _test-error-buffered-file)
     7733 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     7739     # check output
     7740     (check-stream-equal _test-output-stream  ""  "F - test-copy-with-multiple-inouts: output should be empty")
     7741     (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")
     7742     # check that stop(1) was called
     7743     (check-ints-equal *(edx+4) 2 "F - test-copy-with-multiple-inouts: exit status")
     7744     # don't restore from ebp
     7745     81 0/subop/add %esp 8/imm32
     7746     # . epilogue
     7747     5d/pop-to-ebp
     7748     c3/return
     7749
     7750 test-copy-with-no-output:
     7751     # . prologue
     7752     55/push-ebp
     7753     89/<- %ebp 4/r32/esp
     7754     # setup
     7755     (clear-stream _test-input-stream)
     7756     (clear-stream $_test-input-buffered-file->buffer)
     7757     (clear-stream _test-output-stream)
     7758     (clear-stream $_test-output-buffered-file->buffer)
     7759     (clear-stream _test-error-stream)
     7760     (clear-stream $_test-error-buffered-file->buffer)
     7761     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     7762     68/push 0/imm32
     7763     68/push 0/imm32
     7764     89/<- %edx 4/r32/esp
     7765     (tailor-exit-descriptor %edx 0x10)
     7766     #
     7767     (write _test-input-stream "fn foo {\n")
     7768     (write _test-input-stream "  copy 0\n")
     7769     (write _test-input-stream "}\n")
     7770     # convert
     7771     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     7772     # registers except esp clobbered at this point
     7773     # restore ed
     7774     89/<- %edx 4/r32/esp
     7775     (flush _test-output-buffered-file)
     7776     (flush _test-error-buffered-file)
     7777 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     7783     # check output
     7784     (check-stream-equal _test-output-stream  ""  "F - test-copy-with-no-output: output should be empty")
     7785     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy' expects an output"  "F - test-copy-with-no-output: error message")
     7786     # check that stop(1) was called
     7787     (check-ints-equal *(edx+4) 2 "F - test-copy-with-no-output: exit status")
     7788     # don't restore from ebp
     7789     81 0/subop/add %esp 8/imm32
     7790     # . epilogue
     7791     5d/pop-to-ebp
     7792     c3/return
     7793
     7794 test-copy-with-multiple-outputs:
     7795     # . prologue
     7796     55/push-ebp
     7797     89/<- %ebp 4/r32/esp
     7798     # setup
     7799     (clear-stream _test-input-stream)
     7800     (clear-stream $_test-input-buffered-file->buffer)
     7801     (clear-stream _test-output-stream)
     7802     (clear-stream $_test-output-buffered-file->buffer)
     7803     (clear-stream _test-error-stream)
     7804     (clear-stream $_test-error-buffered-file->buffer)
     7805     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     7806     68/push 0/imm32
     7807     68/push 0/imm32
     7808     89/<- %edx 4/r32/esp
     7809     (tailor-exit-descriptor %edx 0x10)
     7810     #
     7811     (write _test-input-stream "fn foo {\n")
     7812     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
     7813     (write _test-input-stream "  var y/ecx: boolean <- copy 0\n")
     7814     (write _test-input-stream "  x, y <- copy 0\n")
     7815     (write _test-input-stream "}\n")
     7816     # convert
     7817     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     7818     # registers except esp clobbered at this point
     7819     # restore ed
     7820     89/<- %edx 4/r32/esp
     7821     (flush _test-output-buffered-file)
     7822     (flush _test-error-buffered-file)
     7823 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     7829     # check output
     7830     (check-stream-equal _test-output-stream  ""  "F - test-copy-with-multiple-outputs: output should be empty")
     7831     (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")
     7832     # check that stop(1) was called
     7833     (check-ints-equal *(edx+4) 2 "F - test-copy-with-multiple-outputs: exit status")
     7834     # don't restore from ebp
     7835     81 0/subop/add %esp 8/imm32
     7836     # . epilogue
     7837     5d/pop-to-ebp
     7838     c3/return
     7839
     7840 test-copy-invalid-value-to-address:
     7841     # . prologue
     7842     55/push-ebp
     7843     89/<- %ebp 4/r32/esp
     7844     # setup
     7845     (clear-stream _test-input-stream)
     7846     (clear-stream $_test-input-buffered-file->buffer)
     7847     (clear-stream _test-output-stream)
     7848     (clear-stream $_test-output-buffered-file->buffer)
     7849     (clear-stream _test-error-stream)
     7850     (clear-stream $_test-error-buffered-file->buffer)
     7851     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     7852     68/push 0/imm32
     7853     68/push 0/imm32
     7854     89/<- %edx 4/r32/esp
     7855     (tailor-exit-descriptor %edx 0x10)
     7856     #
     7857     (write _test-input-stream "fn foo {\n")
     7858     (write _test-input-stream "  var x/eax: int <- copy 0\n")
     7859     (write _test-input-stream "  var y/ecx: (addr int) <- copy x\n")
     7860     (write _test-input-stream "}\n")
     7861     # convert
     7862     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     7863     # registers except esp clobbered at this point
     7864     # restore ed
     7865     89/<- %edx 4/r32/esp
     7866     (flush _test-output-buffered-file)
     7867     (flush _test-error-buffered-file)
     7868 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     7874     # check output
     7875     (check-stream-equal _test-output-stream  ""  "F - test-copy-invalid-value-to-address: output should be empty")
     7876     (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")
     7877     # check that stop(1) was called
     7878     (check-ints-equal *(edx+4) 2 "F - test-copy-invalid-value-to-address: exit status")
     7879     # don't restore from ebp
     7880     81 0/subop/add %esp 8/imm32
     7881     # . epilogue
     7882     5d/pop-to-ebp
     7883     c3/return
     7884
     7885 test-copy-null-value-to-address:
     7886     # . prologue
     7887     55/push-ebp
     7888     89/<- %ebp 4/r32/esp
     7889     # setup
     7890     (clear-stream _test-input-stream)
     7891     (clear-stream $_test-input-buffered-file->buffer)
     7892     (clear-stream _test-output-stream)
     7893     (clear-stream $_test-output-buffered-file->buffer)
     7894     #
     7895     (write _test-input-stream "fn foo {\n")
     7896     (write _test-input-stream "  var y/ecx: (addr int) <- copy 0\n")
     7897     (write _test-input-stream "}\n")
     7898     # convert
     7899     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     7900     (flush _test-output-buffered-file)
     7901     # no errors
     7902     # . epilogue
     7903     89/<- %esp 5/r32/ebp
     7904     5d/pop-to-ebp
     7905     c3/return
     7906
     7907 test-copy-invalid-value-to-offset:
     7908     # . prologue
     7909     55/push-ebp
     7910     89/<- %ebp 4/r32/esp
     7911     # setup
     7912     (clear-stream _test-input-stream)
     7913     (clear-stream $_test-input-buffered-file->buffer)
     7914     (clear-stream _test-output-stream)
     7915     (clear-stream $_test-output-buffered-file->buffer)
     7916     (clear-stream _test-error-stream)
     7917     (clear-stream $_test-error-buffered-file->buffer)
     7918     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     7919     68/push 0/imm32
     7920     68/push 0/imm32
     7921     89/<- %edx 4/r32/esp
     7922     (tailor-exit-descriptor %edx 0x10)
     7923     #
     7924     (write _test-input-stream "fn foo {\n")
     7925     (write _test-input-stream "  var x/eax: int <- copy 0\n")
     7926     (write _test-input-stream "  var y/ecx: (offset int) <- copy x\n")
     7927     (write _test-input-stream "}\n")
     7928     # convert
     7929     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     7930     # registers except esp clobbered at this point
     7931     # restore ed
     7932     89/<- %edx 4/r32/esp
     7933     (flush _test-output-buffered-file)
     7934     (flush _test-error-buffered-file)
     7935 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     7941     # check output
     7942     (check-stream-equal _test-output-stream  ""  "F - test-copy-invalid-value-to-address: output should be empty")
     7943     (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")
     7944     # check that stop(1) was called
     7945     (check-ints-equal *(edx+4) 2 "F - test-copy-invalid-value-to-offset: exit status")
     7946     # don't restore from ebp
     7947     81 0/subop/add %esp 8/imm32
     7948     # . epilogue
     7949     5d/pop-to-ebp
     7950     c3/return
     7951
     7952 test-copy-null-value-to-offset:
     7953     # . prologue
     7954     55/push-ebp
     7955     89/<- %ebp 4/r32/esp
     7956     # setup
     7957     (clear-stream _test-input-stream)
     7958     (clear-stream $_test-input-buffered-file->buffer)
     7959     (clear-stream _test-output-stream)
     7960     (clear-stream $_test-output-buffered-file->buffer)
     7961     #
     7962     (write _test-input-stream "fn foo {\n")
     7963     (write _test-input-stream "  var y/ecx: (offset int) <- copy 0\n")
     7964     (write _test-input-stream "}\n")
     7965     # convert
     7966     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     7967     (flush _test-output-buffered-file)
     7968 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     7974     # no errors
     7975     # . epilogue
     7976     89/<- %esp 5/r32/ebp
     7977     5d/pop-to-ebp
     7978     c3/return
     7979
     7980 test-copy-non-literal-to-byte:
     7981     # . prologue
     7982     55/push-ebp
     7983     89/<- %ebp 4/r32/esp
     7984     # setup
     7985     (clear-stream _test-input-stream)
     7986     (clear-stream $_test-input-buffered-file->buffer)
     7987     (clear-stream _test-output-stream)
     7988     (clear-stream $_test-output-buffered-file->buffer)
     7989     (clear-stream _test-error-stream)
     7990     (clear-stream $_test-error-buffered-file->buffer)
     7991     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     7992     68/push 0/imm32
     7993     68/push 0/imm32
     7994     89/<- %edx 4/r32/esp
     7995     (tailor-exit-descriptor %edx 0x10)
     7996     #
     7997     (write _test-input-stream "fn foo {\n")
     7998     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
     7999     (write _test-input-stream "  var y/ecx: byte <- copy x\n")
     8000     (write _test-input-stream "}\n")
     8001     # convert
     8002     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     8003     # registers except esp clobbered at this point
     8004     # restore ed
     8005     89/<- %edx 4/r32/esp
     8006     (flush _test-output-buffered-file)
     8007     (flush _test-error-buffered-file)
     8008 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     8014     # check output
     8015     (check-stream-equal _test-output-stream  ""  "F - test-copy-non-literal-to-byte: output should be empty")
     8016     (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")
     8017     # check that stop(1) was called
     8018     (check-ints-equal *(edx+4) 2 "F - test-copy-non-literal-to-byte: exit status")
     8019     # don't restore from ebp
     8020     81 0/subop/add %esp 8/imm32
     8021     # . epilogue
     8022     5d/pop-to-ebp
     8023     c3/return
     8024
     8025 test-copy-deref-address:
     8026     # . prologue
     8027     55/push-ebp
     8028     89/<- %ebp 4/r32/esp
     8029     # setup
     8030     (clear-stream _test-input-stream)
     8031     (clear-stream $_test-input-buffered-file->buffer)
     8032     (clear-stream _test-output-stream)
     8033     (clear-stream $_test-output-buffered-file->buffer)
     8034     #
     8035     (write _test-input-stream "fn foo {\n")
     8036     (write _test-input-stream "  var x/eax: (addr addr int) <- copy 0\n")
     8037     (write _test-input-stream "  var y/ecx: (addr int) <- copy *x\n")
     8038     (write _test-input-stream "}\n")
     8039     # convert
     8040     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     8041     (flush _test-output-buffered-file)
     8042     # no errors
     8043     # . epilogue
     8044     5d/pop-to-ebp
     8045     c3/return
     8046
     8047 test-copy-to-non-register:
     8048     # . prologue
     8049     55/push-ebp
     8050     89/<- %ebp 4/r32/esp
     8051     # setup
     8052     (clear-stream _test-input-stream)
     8053     (clear-stream $_test-input-buffered-file->buffer)
     8054     (clear-stream _test-output-stream)
     8055     (clear-stream $_test-output-buffered-file->buffer)
     8056     (clear-stream _test-error-stream)
     8057     (clear-stream $_test-error-buffered-file->buffer)
     8058     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     8059     68/push 0/imm32
     8060     68/push 0/imm32
     8061     89/<- %edx 4/r32/esp
     8062     (tailor-exit-descriptor %edx 0x10)
     8063     #
     8064     (write _test-input-stream "fn foo {\n")
     8065     (write _test-input-stream "  var x: int\n")
     8066     (write _test-input-stream "  x <- copy 0\n")
     8067     (write _test-input-stream "}\n")
     8068     # convert
     8069     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     8070     # registers except esp clobbered at this point
     8071     # restore ed
     8072     89/<- %edx 4/r32/esp
     8073     (flush _test-output-buffered-file)
     8074     (flush _test-error-buffered-file)
     8075 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     8081     # check output
     8082     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-non-register: output should be empty")
     8083     (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")
     8084     # check that stop(1) was called
     8085     (check-ints-equal *(edx+4) 2 "F - test-copy-to-non-register: exit status")
     8086     # don't restore from ebp
     8087     81 0/subop/add %esp 8/imm32
     8088     # . epilogue
     8089     5d/pop-to-ebp
     8090     c3/return
     8091
     8092 test-copy-from-non-scalar-inout:
     8093     # . prologue
     8094     55/push-ebp
     8095     89/<- %ebp 4/r32/esp
     8096     # setup
     8097     (clear-stream _test-input-stream)
     8098     (clear-stream $_test-input-buffered-file->buffer)
     8099     (clear-stream _test-output-stream)
     8100     (clear-stream $_test-output-buffered-file->buffer)
     8101     (clear-stream _test-error-stream)
     8102     (clear-stream $_test-error-buffered-file->buffer)
     8103     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     8104     68/push 0/imm32
     8105     68/push 0/imm32
     8106     89/<- %edx 4/r32/esp
     8107     (tailor-exit-descriptor %edx 0x10)
     8108     #
     8109     (write _test-input-stream "fn foo {\n")
     8110     (write _test-input-stream "  var x: (handle int)\n")
     8111     (write _test-input-stream "  var y/eax: int <- copy x\n")
     8112     (write _test-input-stream "}\n")
     8113     # convert
     8114     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     8115     # registers except esp clobbered at this point
     8116     # restore ed
     8117     89/<- %edx 4/r32/esp
     8118     (flush _test-output-buffered-file)
     8119     (flush _test-error-buffered-file)
     8120 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     8126     # check output
     8127     (check-stream-equal _test-output-stream  ""  "F - test-copy-from-non-scalar-inout: output should be empty")
     8128     (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")
     8129     # check that stop(1) was called
     8130     (check-ints-equal *(edx+4) 2 "F - test-copy-from-non-scalar-inout: exit status")
     8131     # don't restore from ebp
     8132     81 0/subop/add %esp 8/imm32
     8133     # . epilogue
     8134     5d/pop-to-ebp
     8135     c3/return
     8136
     8137 test-copy-to-with-no-inout:
     8138     # . prologue
     8139     55/push-ebp
     8140     89/<- %ebp 4/r32/esp
     8141     # setup
     8142     (clear-stream _test-input-stream)
     8143     (clear-stream $_test-input-buffered-file->buffer)
     8144     (clear-stream _test-output-stream)
     8145     (clear-stream $_test-output-buffered-file->buffer)
     8146     (clear-stream _test-error-stream)
     8147     (clear-stream $_test-error-buffered-file->buffer)
     8148     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     8149     68/push 0/imm32
     8150     68/push 0/imm32
     8151     89/<- %edx 4/r32/esp
     8152     (tailor-exit-descriptor %edx 0x10)
     8153     #
     8154     (write _test-input-stream "fn foo {\n")
     8155     (write _test-input-stream "  copy-to\n")
     8156     (write _test-input-stream "}\n")
     8157     # convert
     8158     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     8159     # registers except esp clobbered at this point
     8160     # restore ed
     8161     89/<- %edx 4/r32/esp
     8162     (flush _test-output-buffered-file)
     8163     (flush _test-error-buffered-file)
     8164 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     8170     # check output
     8171     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-with-no-inout: output should be empty")
     8172     (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")
     8173     # check that stop(1) was called
     8174     (check-ints-equal *(edx+4) 2 "F - test-copy-to-with-no-inout: exit status")
     8175     # don't restore from ebp
     8176     81 0/subop/add %esp 8/imm32
     8177     # . epilogue
     8178     5d/pop-to-ebp
     8179     c3/return
     8180
     8181 test-copy-to-with-no-source:
     8182     # . prologue
     8183     55/push-ebp
     8184     89/<- %ebp 4/r32/esp
     8185     # setup
     8186     (clear-stream _test-input-stream)
     8187     (clear-stream $_test-input-buffered-file->buffer)
     8188     (clear-stream _test-output-stream)
     8189     (clear-stream $_test-output-buffered-file->buffer)
     8190     (clear-stream _test-error-stream)
     8191     (clear-stream $_test-error-buffered-file->buffer)
     8192     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     8193     68/push 0/imm32
     8194     68/push 0/imm32
     8195     89/<- %edx 4/r32/esp
     8196     (tailor-exit-descriptor %edx 0x10)
     8197     #
     8198     (write _test-input-stream "fn foo {\n")
     8199     (write _test-input-stream "  var x: boolean\n")
     8200     (write _test-input-stream "  copy-to x\n")
     8201     (write _test-input-stream "}\n")
     8202     # convert
     8203     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     8204     # registers except esp clobbered at this point
     8205     # restore ed
     8206     89/<- %edx 4/r32/esp
     8207     (flush _test-output-buffered-file)
     8208     (flush _test-error-buffered-file)
     8209 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     8215     # check output
     8216     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-with-no-source: output should be empty")
     8217     (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")
     8218     # check that stop(1) was called
     8219     (check-ints-equal *(edx+4) 2 "F - test-copy-to-with-no-source: exit status")
     8220     # don't restore from ebp
     8221     81 0/subop/add %esp 8/imm32
     8222     # . epilogue
     8223     5d/pop-to-ebp
     8224     c3/return
     8225
     8226 test-copy-to-with-no-register:
     8227     # . prologue
     8228     55/push-ebp
     8229     89/<- %ebp 4/r32/esp
     8230     # setup
     8231     (clear-stream _test-input-stream)
     8232     (clear-stream $_test-input-buffered-file->buffer)
     8233     (clear-stream _test-output-stream)
     8234     (clear-stream $_test-output-buffered-file->buffer)
     8235     (clear-stream _test-error-stream)
     8236     (clear-stream $_test-error-buffered-file->buffer)
     8237     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     8238     68/push 0/imm32
     8239     68/push 0/imm32
     8240     89/<- %edx 4/r32/esp
     8241     (tailor-exit-descriptor %edx 0x10)
     8242     #
     8243     (write _test-input-stream "fn foo {\n")
     8244     (write _test-input-stream "  var x: boolean\n")
     8245     (write _test-input-stream "  copy-to x, x\n")
     8246     (write _test-input-stream "}\n")
     8247     # convert
     8248     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     8249     # registers except esp clobbered at this point
     8250     # restore ed
     8251     89/<- %edx 4/r32/esp
     8252     (flush _test-output-buffered-file)
     8253     (flush _test-error-buffered-file)
     8254 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     8260     # check output
     8261     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-with-no-register: output should be empty")
     8262     (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")
     8263     # check that stop(1) was called
     8264     (check-ints-equal *(edx+4) 2 "F - test-copy-to-with-no-register: exit status")
     8265     # don't restore from ebp
     8266     81 0/subop/add %esp 8/imm32
     8267     # . epilogue
     8268     5d/pop-to-ebp
     8269     c3/return
     8270
     8271 test-copy-to-with-too-many-inouts:
     8272     # . prologue
     8273     55/push-ebp
     8274     89/<- %ebp 4/r32/esp
     8275     # setup
     8276     (clear-stream _test-input-stream)
     8277     (clear-stream $_test-input-buffered-file->buffer)
     8278     (clear-stream _test-output-stream)
     8279     (clear-stream $_test-output-buffered-file->buffer)
     8280     (clear-stream _test-error-stream)
     8281     (clear-stream $_test-error-buffered-file->buffer)
     8282     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     8283     68/push 0/imm32
     8284     68/push 0/imm32
     8285     89/<- %edx 4/r32/esp
     8286     (tailor-exit-descriptor %edx 0x10)
     8287     #
     8288     (write _test-input-stream "fn foo {\n")
     8289     (write _test-input-stream "  var x: boolean\n")
     8290     (write _test-input-stream "  copy-to x, 0, 0\n")
     8291     (write _test-input-stream "}\n")
     8292     # convert
     8293     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     8294     # registers except esp clobbered at this point
     8295     # restore ed
     8296     89/<- %edx 4/r32/esp
     8297     (flush _test-output-buffered-file)
     8298     (flush _test-error-buffered-file)
     8299 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     8305     # check output
     8306     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-with-too-many-inouts: output should be empty")
     8307     (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")
     8308     # check that stop(1) was called
     8309     (check-ints-equal *(edx+4) 2 "F - test-copy-to-with-too-many-inouts: exit status")
     8310     # don't restore from ebp
     8311     81 0/subop/add %esp 8/imm32
     8312     # . epilogue
     8313     5d/pop-to-ebp
     8314     c3/return
     8315
     8316 test-copy-to-with-output:
     8317     # . prologue
     8318     55/push-ebp
     8319     89/<- %ebp 4/r32/esp
     8320     # setup
     8321     (clear-stream _test-input-stream)
     8322     (clear-stream $_test-input-buffered-file->buffer)
     8323     (clear-stream _test-output-stream)
     8324     (clear-stream $_test-output-buffered-file->buffer)
     8325     (clear-stream _test-error-stream)
     8326     (clear-stream $_test-error-buffered-file->buffer)
     8327     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     8328     68/push 0/imm32
     8329     68/push 0/imm32
     8330     89/<- %edx 4/r32/esp
     8331     (tailor-exit-descriptor %edx 0x10)
     8332     #
     8333     (write _test-input-stream "fn foo {\n")
     8334     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
     8335     (write _test-input-stream "  var y/ecx: boolean <- copy 0\n")
     8336     (write _test-input-stream "  x <- copy-to y, 0\n")
     8337     (write _test-input-stream "}\n")
     8338     # convert
     8339     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     8340     # registers except esp clobbered at this point
     8341     # restore ed
     8342     89/<- %edx 4/r32/esp
     8343     (flush _test-output-buffered-file)
     8344     (flush _test-error-buffered-file)
     8345 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     8351     # check output
     8352     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-with-output: output should be empty")
     8353     (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")
     8354     # check that stop(1) was called
     8355     (check-ints-equal *(edx+4) 2 "F - test-copy-to-with-output: exit status")
     8356     # don't restore from ebp
     8357     81 0/subop/add %esp 8/imm32
     8358     # . epilogue
     8359     5d/pop-to-ebp
     8360     c3/return
     8361
     8362 test-copy-to-invalid-value-to-address:
     8363     # . prologue
     8364     55/push-ebp
     8365     89/<- %ebp 4/r32/esp
     8366     # setup
     8367     (clear-stream _test-input-stream)
     8368     (clear-stream $_test-input-buffered-file->buffer)
     8369     (clear-stream _test-output-stream)
     8370     (clear-stream $_test-output-buffered-file->buffer)
     8371     (clear-stream _test-error-stream)
     8372     (clear-stream $_test-error-buffered-file->buffer)
     8373     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     8374     68/push 0/imm32
     8375     68/push 0/imm32
     8376     89/<- %edx 4/r32/esp
     8377     (tailor-exit-descriptor %edx 0x10)
     8378     #
     8379     (write _test-input-stream "fn foo {\n")
     8380     (write _test-input-stream "  var x/eax: int <- copy 0\n")
     8381     (write _test-input-stream "  var y: (addr int)\n")
     8382     (write _test-input-stream "  copy-to y, x\n")
     8383     (write _test-input-stream "}\n")
     8384     # convert
     8385     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     8386     # registers except esp clobbered at this point
     8387     # restore ed
     8388     89/<- %edx 4/r32/esp
     8389     (flush _test-output-buffered-file)
     8390     (flush _test-error-buffered-file)
     8391 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     8397     # check output
     8398     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-invalid-value-to-address: output should be empty")
     8399     (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")
     8400     # check that stop(1) was called
     8401     (check-ints-equal *(edx+4) 2 "F - test-copy-to-invalid-value-to-address: exit status")
     8402     # don't restore from ebp
     8403     81 0/subop/add %esp 8/imm32
     8404     # . epilogue
     8405     5d/pop-to-ebp
     8406     c3/return
     8407
     8408 test-copy-to-null-value-to-address:
     8409     # . prologue
     8410     55/push-ebp
     8411     89/<- %ebp 4/r32/esp
     8412     # setup
     8413     (clear-stream _test-input-stream)
     8414     (clear-stream $_test-input-buffered-file->buffer)
     8415     (clear-stream _test-output-stream)
     8416     (clear-stream $_test-output-buffered-file->buffer)
     8417     #
     8418     (write _test-input-stream "fn foo {\n")
     8419     (write _test-input-stream "  var y: (addr int)\n")
     8420     (write _test-input-stream "  copy-to y, 0\n")
     8421     (write _test-input-stream "}\n")
     8422     # convert
     8423     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     8424     (flush _test-output-buffered-file)
     8425     # no errors
     8426     # . epilogue
     8427     89/<- %esp 5/r32/ebp
     8428     5d/pop-to-ebp
     8429     c3/return
     8430
     8431 test-copy-to-invalid-value-to-offset:
     8432     # . prologue
     8433     55/push-ebp
     8434     89/<- %ebp 4/r32/esp
     8435     # setup
     8436     (clear-stream _test-input-stream)
     8437     (clear-stream $_test-input-buffered-file->buffer)
     8438     (clear-stream _test-output-stream)
     8439     (clear-stream $_test-output-buffered-file->buffer)
     8440     (clear-stream _test-error-stream)
     8441     (clear-stream $_test-error-buffered-file->buffer)
     8442     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     8443     68/push 0/imm32
     8444     68/push 0/imm32
     8445     89/<- %edx 4/r32/esp
     8446     (tailor-exit-descriptor %edx 0x10)
     8447     #
     8448     (write _test-input-stream "fn foo {\n")
     8449     (write _test-input-stream "  var x/eax: int <- copy 0\n")
     8450     (write _test-input-stream "  var y: (offset int)\n")
     8451     (write _test-input-stream "  copy-to y, x\n")
     8452     (write _test-input-stream "}\n")
     8453     # convert
     8454     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     8455     # registers except esp clobbered at this point
     8456     # restore ed
     8457     89/<- %edx 4/r32/esp
     8458     (flush _test-output-buffered-file)
     8459     (flush _test-error-buffered-file)
     8460 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     8466     # check output
     8467     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-invalid-value-to-offset: output should be empty")
     8468     (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")
     8469     # check that stop(1) was called
     8470     (check-ints-equal *(edx+4) 2 "F - test-copy-to-invalid-value-to-offset: exit status")
     8471     # don't restore from ebp
     8472     81 0/subop/add %esp 8/imm32
     8473     # . epilogue
     8474     5d/pop-to-ebp
     8475     c3/return
     8476
     8477 test-copy-to-null-value-to-offset:
     8478     # . prologue
     8479     55/push-ebp
     8480     89/<- %ebp 4/r32/esp
     8481     # setup
     8482     (clear-stream _test-input-stream)
     8483     (clear-stream $_test-input-buffered-file->buffer)
     8484     (clear-stream _test-output-stream)
     8485     (clear-stream $_test-output-buffered-file->buffer)
     8486     #
     8487     (write _test-input-stream "fn foo {\n")
     8488     (write _test-input-stream "  var y: (offset int)\n")
     8489     (write _test-input-stream "  copy-to y, 0\n")
     8490     (write _test-input-stream "}\n")
     8491     # convert
     8492     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     8493     (flush _test-output-buffered-file)
     8494     # no errors
     8495     # . epilogue
     8496     89/<- %esp 5/r32/ebp
     8497     5d/pop-to-ebp
     8498     c3/return
     8499
     8500 test-copy-to-non-literal-to-byte:
     8501     # . prologue
     8502     55/push-ebp
     8503     89/<- %ebp 4/r32/esp
     8504     # setup
     8505     (clear-stream _test-input-stream)
     8506     (clear-stream $_test-input-buffered-file->buffer)
     8507     (clear-stream _test-output-stream)
     8508     (clear-stream $_test-output-buffered-file->buffer)
     8509     (clear-stream _test-error-stream)
     8510     (clear-stream $_test-error-buffered-file->buffer)
     8511     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     8512     68/push 0/imm32
     8513     68/push 0/imm32
     8514     89/<- %edx 4/r32/esp
     8515     (tailor-exit-descriptor %edx 0x10)
     8516     #
     8517     (write _test-input-stream "fn foo {\n")
     8518     (write _test-input-stream "  var x/ecx: byte <- copy 3\n")
     8519     (write _test-input-stream "  var y/eax: (addr byte) <- copy 0\n")
     8520     (write _test-input-stream "  copy-to *y, x\n")
     8521     (write _test-input-stream "}\n")
     8522     # convert
     8523     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     8524     # registers except esp clobbered at this point
     8525     # restore ed
     8526     89/<- %edx 4/r32/esp
     8527     (flush _test-output-buffered-file)
     8528     (flush _test-error-buffered-file)
     8529 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     8535     # check output
     8536     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-non-literal-to-byte: output should be empty")
     8537     (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")
     8538     # check that stop(1) was called
     8539     (check-ints-equal *(edx+4) 2 "F - test-copy-to-non-literal-to-byte: exit status")
     8540     # don't restore from ebp
     8541     81 0/subop/add %esp 8/imm32
     8542     # . epilogue
     8543     5d/pop-to-ebp
     8544     c3/return
     8545
     8546 test-copy-to-deref-address:
     8547     # . prologue
     8548     55/push-ebp
     8549     89/<- %ebp 4/r32/esp
     8550     # setup
     8551     (clear-stream _test-input-stream)
     8552     (clear-stream $_test-input-buffered-file->buffer)
     8553     (clear-stream _test-output-stream)
     8554     (clear-stream $_test-output-buffered-file->buffer)
     8555     #
     8556     (write _test-input-stream "fn foo {\n")
     8557     (write _test-input-stream "  var x/eax: (addr int) <- copy 0\n")
     8558     (write _test-input-stream "  var y/ecx: (addr addr int) <- copy 0\n")
     8559     (write _test-input-stream "  copy-to *y, x\n")
     8560     (write _test-input-stream "}\n")
     8561     # convert
     8562     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     8563     (flush _test-output-buffered-file)
     8564     # no errors
     8565     # . epilogue
     8566     5d/pop-to-ebp
     8567     c3/return
     8568
     8569 test-copy-to-from-non-scalar-inout:
     8570     # . prologue
     8571     55/push-ebp
     8572     89/<- %ebp 4/r32/esp
     8573     # setup
     8574     (clear-stream _test-input-stream)
     8575     (clear-stream $_test-input-buffered-file->buffer)
     8576     (clear-stream _test-output-stream)
     8577     (clear-stream $_test-output-buffered-file->buffer)
     8578     (clear-stream _test-error-stream)
     8579     (clear-stream $_test-error-buffered-file->buffer)
     8580     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     8581     68/push 0/imm32
     8582     68/push 0/imm32
     8583     89/<- %edx 4/r32/esp
     8584     (tailor-exit-descriptor %edx 0x10)
     8585     #
     8586     (write _test-input-stream "fn foo {\n")
     8587     (write _test-input-stream "  var x: (handle int)\n")
     8588     (write _test-input-stream "  var y: int\n")
     8589     (write _test-input-stream "  copy-to y, x\n")
     8590     (write _test-input-stream "}\n")
     8591     # convert
     8592     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     8593     # registers except esp clobbered at this point
     8594     # restore ed
     8595     89/<- %edx 4/r32/esp
     8596     (flush _test-output-buffered-file)
     8597     (flush _test-error-buffered-file)
     8598 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     8604     # check output
     8605     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-from-non-scalar-inout: output should be empty")
     8606     (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")
     8607     # check that stop(1) was called
     8608     (check-ints-equal *(edx+4) 2 "F - test-copy-to-from-non-scalar-inout: exit status")
     8609     # don't restore from ebp
     8610     81 0/subop/add %esp 8/imm32
     8611     # . epilogue
     8612     5d/pop-to-ebp
     8613     c3/return
     8614
     8615 test-copy-byte-with-no-inout:
     8616     # . prologue
     8617     55/push-ebp
     8618     89/<- %ebp 4/r32/esp
     8619     # setup
     8620     (clear-stream _test-input-stream)
     8621     (clear-stream $_test-input-buffered-file->buffer)
     8622     (clear-stream _test-output-stream)
     8623     (clear-stream $_test-output-buffered-file->buffer)
     8624     (clear-stream _test-error-stream)
     8625     (clear-stream $_test-error-buffered-file->buffer)
     8626     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     8627     68/push 0/imm32
     8628     68/push 0/imm32
     8629     89/<- %edx 4/r32/esp
     8630     (tailor-exit-descriptor %edx 0x10)
     8631     #
     8632     (write _test-input-stream "fn foo {\n")
     8633     (write _test-input-stream "  var x/eax: byte <- copy-byte\n")
     8634     (write _test-input-stream "}\n")
     8635     # convert
     8636     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     8637     # registers except esp clobbered at this point
     8638     # restore ed
     8639     89/<- %edx 4/r32/esp
     8640     (flush _test-output-buffered-file)
     8641     (flush _test-error-buffered-file)
     8642 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     8648     # check output
     8649     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-with-no-inout: output should be empty")
     8650     (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")
     8651     # check that stop(1) was called
     8652     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-with-no-inout: exit status")
     8653     # don't restore from ebp
     8654     81 0/subop/add %esp 8/imm32
     8655     # . epilogue
     8656     5d/pop-to-ebp
     8657     c3/return
     8658
     8659 test-copy-byte-with-multiple-inouts:
     8660     # . prologue
     8661     55/push-ebp
     8662     89/<- %ebp 4/r32/esp
     8663     # setup
     8664     (clear-stream _test-input-stream)
     8665     (clear-stream $_test-input-buffered-file->buffer)
     8666     (clear-stream _test-output-stream)
     8667     (clear-stream $_test-output-buffered-file->buffer)
     8668     (clear-stream _test-error-stream)
     8669     (clear-stream $_test-error-buffered-file->buffer)
     8670     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     8671     68/push 0/imm32
     8672     68/push 0/imm32
     8673     89/<- %edx 4/r32/esp
     8674     (tailor-exit-descriptor %edx 0x10)
     8675     #
     8676     (write _test-input-stream "fn foo {\n")
     8677     (write _test-input-stream "  var x/eax: byte <- copy-byte 0, 0\n")
     8678     (write _test-input-stream "}\n")
     8679     # convert
     8680     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     8681     # registers except esp clobbered at this point
     8682     # restore ed
     8683     89/<- %edx 4/r32/esp
     8684     (flush _test-output-buffered-file)
     8685     (flush _test-error-buffered-file)
     8686 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     8692     # check output
     8693     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-with-multiple-inouts: output should be empty")
     8694     (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")
     8695     # check that stop(1) was called
     8696     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-with-multiple-inouts: exit status")
     8697     # don't restore from ebp
     8698     81 0/subop/add %esp 8/imm32
     8699     # . epilogue
     8700     5d/pop-to-ebp
     8701     c3/return
     8702
     8703 test-copy-byte-with-no-output:
     8704     # . prologue
     8705     55/push-ebp
     8706     89/<- %ebp 4/r32/esp
     8707     # setup
     8708     (clear-stream _test-input-stream)
     8709     (clear-stream $_test-input-buffered-file->buffer)
     8710     (clear-stream _test-output-stream)
     8711     (clear-stream $_test-output-buffered-file->buffer)
     8712     (clear-stream _test-error-stream)
     8713     (clear-stream $_test-error-buffered-file->buffer)
     8714     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     8715     68/push 0/imm32
     8716     68/push 0/imm32
     8717     89/<- %edx 4/r32/esp
     8718     (tailor-exit-descriptor %edx 0x10)
     8719     #
     8720     (write _test-input-stream "fn foo {\n")
     8721     (write _test-input-stream "  copy-byte 0\n")
     8722     (write _test-input-stream "}\n")
     8723     # convert
     8724     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     8725     # registers except esp clobbered at this point
     8726     # restore ed
     8727     89/<- %edx 4/r32/esp
     8728     (flush _test-output-buffered-file)
     8729     (flush _test-error-buffered-file)
     8730 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     8736     # check output
     8737     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-with-no-output: output should be empty")
     8738     (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")
     8739     # check that stop(1) was called
     8740     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-with-no-output: exit status")
     8741     # don't restore from ebp
     8742     81 0/subop/add %esp 8/imm32
     8743     # . epilogue
     8744     5d/pop-to-ebp
     8745     c3/return
     8746
     8747 test-copy-byte-with-multiple-outputs:
     8748     # . prologue
     8749     55/push-ebp
     8750     89/<- %ebp 4/r32/esp
     8751     # setup
     8752     (clear-stream _test-input-stream)
     8753     (clear-stream $_test-input-buffered-file->buffer)
     8754     (clear-stream _test-output-stream)
     8755     (clear-stream $_test-output-buffered-file->buffer)
     8756     (clear-stream _test-error-stream)
     8757     (clear-stream $_test-error-buffered-file->buffer)
     8758     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     8759     68/push 0/imm32
     8760     68/push 0/imm32
     8761     89/<- %edx 4/r32/esp
     8762     (tailor-exit-descriptor %edx 0x10)
     8763     #
     8764     (write _test-input-stream "fn foo {\n")
     8765     (write _test-input-stream "  var x/eax: byte <- copy 0\n")
     8766     (write _test-input-stream "  var y/ecx: byte <- copy 0\n")
     8767     (write _test-input-stream "  x, y <- copy-byte 0\n")
     8768     (write _test-input-stream "}\n")
     8769     # convert
     8770     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     8771     # registers except esp clobbered at this point
     8772     # restore ed
     8773     89/<- %edx 4/r32/esp
     8774     (flush _test-output-buffered-file)
     8775     (flush _test-error-buffered-file)
     8776 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     8782     # check output
     8783     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-with-multiple-outputs: output should be empty")
     8784     (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")
     8785     # check that stop(1) was called
     8786     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-with-multiple-outputs: exit status")
     8787     # don't restore from ebp
     8788     81 0/subop/add %esp 8/imm32
     8789     # . epilogue
     8790     5d/pop-to-ebp
     8791     c3/return
     8792
     8793 test-copy-byte-deref-address:
     8794     # . prologue
     8795     55/push-ebp
     8796     89/<- %ebp 4/r32/esp
     8797     # setup
     8798     (clear-stream _test-input-stream)
     8799     (clear-stream $_test-input-buffered-file->buffer)
     8800     (clear-stream _test-output-stream)
     8801     (clear-stream $_test-output-buffered-file->buffer)
     8802     #
     8803     (write _test-input-stream "fn foo {\n")
     8804     (write _test-input-stream "  var x/eax: (addr byte) <- copy 0\n")
     8805     (write _test-input-stream "  var y/ecx: byte <- copy-byte *x\n")
     8806     (write _test-input-stream "}\n")
     8807     # convert
     8808     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     8809     (flush _test-output-buffered-file)
     8810 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     8816     # not bothering checking output
     8817     (check-next-stream-line-equal _test-error-stream  ""  "F - test-copy-byte-deref-address: error message")
     8818     # . epilogue
     8819     5d/pop-to-ebp
     8820     c3/return
     8821
     8822 test-copy-byte-with-invalid-output-type:
     8823     # . prologue
     8824     55/push-ebp
     8825     89/<- %ebp 4/r32/esp
     8826     # setup
     8827     (clear-stream _test-input-stream)
     8828     (clear-stream $_test-input-buffered-file->buffer)
     8829     (clear-stream _test-output-stream)
     8830     (clear-stream $_test-output-buffered-file->buffer)
     8831     (clear-stream _test-error-stream)
     8832     (clear-stream $_test-error-buffered-file->buffer)
     8833     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     8834     68/push 0/imm32
     8835     68/push 0/imm32
     8836     89/<- %edx 4/r32/esp
     8837     (tailor-exit-descriptor %edx 0x10)
     8838     #
     8839     (write _test-input-stream "fn foo {\n")
     8840     (write _test-input-stream "  var x/eax: (addr byte) <- copy 0\n")
     8841     (write _test-input-stream "  var y/eax: int <- copy-byte *x\n")
     8842     (write _test-input-stream "}\n")
     8843     # convert
     8844     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     8845     # registers except esp clobbered at this point
     8846     # restore ed
     8847     89/<- %edx 4/r32/esp
     8848     (flush _test-output-buffered-file)
     8849     (flush _test-error-buffered-file)
     8850 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     8856     # check output
     8857     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-with-invalid-output-type: output should be empty")
     8858     (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")
     8859     # check that stop(1) was called
     8860     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-with-invalid-output-type: exit status")
     8861     # don't restore from ebp
     8862     81 0/subop/add %esp 8/imm32
     8863     # . epilogue
     8864     5d/pop-to-ebp
     8865     c3/return
     8866
     8867 test-copy-byte-from-non-scalar-inout:
     8868     # . prologue
     8869     55/push-ebp
     8870     89/<- %ebp 4/r32/esp
     8871     # setup
     8872     (clear-stream _test-input-stream)
     8873     (clear-stream $_test-input-buffered-file->buffer)
     8874     (clear-stream _test-output-stream)
     8875     (clear-stream $_test-output-buffered-file->buffer)
     8876     (clear-stream _test-error-stream)
     8877     (clear-stream $_test-error-buffered-file->buffer)
     8878     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     8879     68/push 0/imm32
     8880     68/push 0/imm32
     8881     89/<- %edx 4/r32/esp
     8882     (tailor-exit-descriptor %edx 0x10)
     8883     #
     8884     (write _test-input-stream "fn foo {\n")
     8885     (write _test-input-stream "  var x: (handle int)\n")
     8886     (write _test-input-stream "  var y/eax: byte <- copy-byte x\n")
     8887     (write _test-input-stream "}\n")
     8888     # convert
     8889     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     8890     # registers except esp clobbered at this point
     8891     # restore ed
     8892     89/<- %edx 4/r32/esp
     8893     (flush _test-output-buffered-file)
     8894     (flush _test-error-buffered-file)
     8895 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     8901     # check output
     8902     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-from-non-scalar-inout: output should be empty")
     8903     (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")
     8904     # check that stop(1) was called
     8905     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-from-non-scalar-inout: exit status")
     8906     # don't restore from ebp
     8907     81 0/subop/add %esp 8/imm32
     8908     # . epilogue
     8909     5d/pop-to-ebp
     8910     c3/return
     8911
     8912 test-copy-byte-to-with-no-inout:
     8913     # . prologue
     8914     55/push-ebp
     8915     89/<- %ebp 4/r32/esp
     8916     # setup
     8917     (clear-stream _test-input-stream)
     8918     (clear-stream $_test-input-buffered-file->buffer)
     8919     (clear-stream _test-output-stream)
     8920     (clear-stream $_test-output-buffered-file->buffer)
     8921     (clear-stream _test-error-stream)
     8922     (clear-stream $_test-error-buffered-file->buffer)
     8923     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     8924     68/push 0/imm32
     8925     68/push 0/imm32
     8926     89/<- %edx 4/r32/esp
     8927     (tailor-exit-descriptor %edx 0x10)
     8928     #
     8929     (write _test-input-stream "fn foo {\n")
     8930     (write _test-input-stream "  copy-byte-to\n")
     8931     (write _test-input-stream "}\n")
     8932     # convert
     8933     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     8934     # registers except esp clobbered at this point
     8935     # restore ed
     8936     89/<- %edx 4/r32/esp
     8937     (flush _test-output-buffered-file)
     8938     (flush _test-error-buffered-file)
     8939 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     8945     # check output
     8946     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-to-with-no-inout: output should be empty")
     8947     (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")
     8948     # check that stop(1) was called
     8949     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-to-with-no-inout: exit status")
     8950     # don't restore from ebp
     8951     81 0/subop/add %esp 8/imm32
     8952     # . epilogue
     8953     5d/pop-to-ebp
     8954     c3/return
     8955
     8956 test-copy-byte-to-with-no-source:
     8957     # . prologue
     8958     55/push-ebp
     8959     89/<- %ebp 4/r32/esp
     8960     # setup
     8961     (clear-stream _test-input-stream)
     8962     (clear-stream $_test-input-buffered-file->buffer)
     8963     (clear-stream _test-output-stream)
     8964     (clear-stream $_test-output-buffered-file->buffer)
     8965     (clear-stream _test-error-stream)
     8966     (clear-stream $_test-error-buffered-file->buffer)
     8967     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     8968     68/push 0/imm32
     8969     68/push 0/imm32
     8970     89/<- %edx 4/r32/esp
     8971     (tailor-exit-descriptor %edx 0x10)
     8972     #
     8973     (write _test-input-stream "fn foo {\n")
     8974     (write _test-input-stream "  var x/eax: (addr byte) <- copy 0\n")
     8975     (write _test-input-stream "  copy-byte-to *x\n")
     8976     (write _test-input-stream "}\n")
     8977     # convert
     8978     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     8979     # registers except esp clobbered at this point
     8980     # restore ed
     8981     89/<- %edx 4/r32/esp
     8982     (flush _test-output-buffered-file)
     8983     (flush _test-error-buffered-file)
     8984 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     8990     # check output
     8991     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-to-with-no-source: output should be empty")
     8992     (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")
     8993     # check that stop(1) was called
     8994     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-to-with-no-source: exit status")
     8995     # don't restore from ebp
     8996     81 0/subop/add %esp 8/imm32
     8997     # . epilogue
     8998     5d/pop-to-ebp
     8999     c3/return
     9000
     9001 test-copy-byte-to-with-too-many-inouts:
     9002     # . prologue
     9003     55/push-ebp
     9004     89/<- %ebp 4/r32/esp
     9005     # setup
     9006     (clear-stream _test-input-stream)
     9007     (clear-stream $_test-input-buffered-file->buffer)
     9008     (clear-stream _test-output-stream)
     9009     (clear-stream $_test-output-buffered-file->buffer)
     9010     (clear-stream _test-error-stream)
     9011     (clear-stream $_test-error-buffered-file->buffer)
     9012     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     9013     68/push 0/imm32
     9014     68/push 0/imm32
     9015     89/<- %edx 4/r32/esp
     9016     (tailor-exit-descriptor %edx 0x10)
     9017     #
     9018     (write _test-input-stream "fn foo {\n")
     9019     (write _test-input-stream "  var x/eax: (addr byte) <- copy 0\n")
     9020     (write _test-input-stream "  copy-byte-to *x, 0, 0\n")
     9021     (write _test-input-stream "}\n")
     9022     # convert
     9023     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     9024     # registers except esp clobbered at this point
     9025     # restore ed
     9026     89/<- %edx 4/r32/esp
     9027     (flush _test-output-buffered-file)
     9028     (flush _test-error-buffered-file)
     9029 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     9035     # check output
     9036     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-to-with-too-many-inouts: output should be empty")
     9037     (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")
     9038     # check that stop(1) was called
     9039     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-to-with-too-many-inouts: exit status")
     9040     # don't restore from ebp
     9041     81 0/subop/add %esp 8/imm32
     9042     # . epilogue
     9043     5d/pop-to-ebp
     9044     c3/return
     9045
     9046 test-copy-byte-to-with-output:
     9047     # . prologue
     9048     55/push-ebp
     9049     89/<- %ebp 4/r32/esp
     9050     # setup
     9051     (clear-stream _test-input-stream)
     9052     (clear-stream $_test-input-buffered-file->buffer)
     9053     (clear-stream _test-output-stream)
     9054     (clear-stream $_test-output-buffered-file->buffer)
     9055     (clear-stream _test-error-stream)
     9056     (clear-stream $_test-error-buffered-file->buffer)
     9057     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     9058     68/push 0/imm32
     9059     68/push 0/imm32
     9060     89/<- %edx 4/r32/esp
     9061     (tailor-exit-descriptor %edx 0x10)
     9062     #
     9063     (write _test-input-stream "fn foo {\n")
     9064     (write _test-input-stream "  var x/eax: byte <- copy 0\n")
     9065     (write _test-input-stream "  var y/ecx: (addr byte) <- copy 0\n")
     9066     (write _test-input-stream "  x <- copy-byte-to *y, 0\n")
     9067     (write _test-input-stream "}\n")
     9068     # convert
     9069     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     9070     # registers except esp clobbered at this point
     9071     # restore ed
     9072     89/<- %edx 4/r32/esp
     9073     (flush _test-output-buffered-file)
     9074     (flush _test-error-buffered-file)
     9075 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     9081     # check output
     9082     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-to-with-output: output should be empty")
     9083     (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")
     9084     # check that stop(1) was called
     9085     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-to-with-output: exit status")
     9086     # don't restore from ebp
     9087     81 0/subop/add %esp 8/imm32
     9088     # . epilogue
     9089     5d/pop-to-ebp
     9090     c3/return
     9091
     9092 test-copy-byte-to-with-invalid-output-type:
     9093     # . prologue
     9094     55/push-ebp
     9095     89/<- %ebp 4/r32/esp
     9096     # setup
     9097     (clear-stream _test-input-stream)
     9098     (clear-stream $_test-input-buffered-file->buffer)
     9099     (clear-stream _test-output-stream)
     9100     (clear-stream $_test-output-buffered-file->buffer)
     9101     (clear-stream _test-error-stream)
     9102     (clear-stream $_test-error-buffered-file->buffer)
     9103     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     9104     68/push 0/imm32
     9105     68/push 0/imm32
     9106     89/<- %edx 4/r32/esp
     9107     (tailor-exit-descriptor %edx 0x10)
     9108     #
     9109     (write _test-input-stream "fn foo {\n")
     9110     (write _test-input-stream "  var x/eax: byte <- copy 0\n")
     9111     (write _test-input-stream "  var y: int\n")
     9112     (write _test-input-stream "  copy-byte-to y, x\n")
     9113     (write _test-input-stream "}\n")
     9114     # convert
     9115     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     9116     # registers except esp clobbered at this point
     9117     # restore ed
     9118     89/<- %edx 4/r32/esp
     9119     (flush _test-output-buffered-file)
     9120     (flush _test-error-buffered-file)
     9121 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     9127     # check output
     9128     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-to-with-invalid-output-type: output should be empty")
     9129     (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")
     9130     # check that stop(1) was called
     9131     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-to-with-invalid-output-type: exit status")
     9132     # don't restore from ebp
     9133     81 0/subop/add %esp 8/imm32
     9134     # . epilogue
     9135     5d/pop-to-ebp
     9136     c3/return
     9137
     9138 test-copy-byte-to-with-literal-inout:
     9139     # . prologue
     9140     55/push-ebp
     9141     89/<- %ebp 4/r32/esp
     9142     # setup
     9143     (clear-stream _test-input-stream)
     9144     (clear-stream $_test-input-buffered-file->buffer)
     9145     (clear-stream _test-output-stream)
     9146     (clear-stream $_test-output-buffered-file->buffer)
     9147     (clear-stream _test-error-stream)
     9148     (clear-stream $_test-error-buffered-file->buffer)
     9149     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     9150     68/push 0/imm32
     9151     68/push 0/imm32
     9152     89/<- %edx 4/r32/esp
     9153     (tailor-exit-descriptor %edx 0x10)
     9154     #
     9155     (write _test-input-stream "fn foo {\n")
     9156     (write _test-input-stream "  var x/eax: (addr byte) <- copy 0\n")
     9157     (write _test-input-stream "  copy-byte-to *x, 0\n")
     9158     (write _test-input-stream "}\n")
     9159     # convert
     9160     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     9161     # registers except esp clobbered at this point
     9162     # restore ed
     9163     89/<- %edx 4/r32/esp
     9164     (flush _test-output-buffered-file)
     9165     (flush _test-error-buffered-file)
     9166 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     9172     # check output
     9173     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-to-with-literal-inout: output should be empty")
     9174     (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")
     9175     # check that stop(1) was called
     9176     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-to-with-literal-inout: exit status")
     9177     # don't restore from ebp
     9178     81 0/subop/add %esp 8/imm32
     9179     # . epilogue
     9180     5d/pop-to-ebp
     9181     c3/return
     9182
     9183 test-copy-byte-to-deref-address:
     9184     # . prologue
     9185     55/push-ebp
     9186     89/<- %ebp 4/r32/esp
     9187     # setup
     9188     (clear-stream _test-input-stream)
     9189     (clear-stream $_test-input-buffered-file->buffer)
     9190     (clear-stream _test-output-stream)
     9191     (clear-stream $_test-output-buffered-file->buffer)
     9192     #
     9193     (write _test-input-stream "fn foo {\n")
     9194     (write _test-input-stream "  var x/eax: byte <- copy 0\n")
     9195     (write _test-input-stream "  var y/ecx: (addr byte) <- copy 0\n")
     9196     (write _test-input-stream "  copy-byte-to *y, x\n")
     9197     (write _test-input-stream "}\n")
     9198     # convert
     9199     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     9200     (flush _test-output-buffered-file)
     9201     # no errors
     9202     # . epilogue
     9203     5d/pop-to-ebp
     9204     c3/return
     9205
     9206 test-copy-byte-to-from-non-scalar-inout:
     9207     # . prologue
     9208     55/push-ebp
     9209     89/<- %ebp 4/r32/esp
     9210     # setup
     9211     (clear-stream _test-input-stream)
     9212     (clear-stream $_test-input-buffered-file->buffer)
     9213     (clear-stream _test-output-stream)
     9214     (clear-stream $_test-output-buffered-file->buffer)
     9215     (clear-stream _test-error-stream)
     9216     (clear-stream $_test-error-buffered-file->buffer)
     9217     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     9218     68/push 0/imm32
     9219     68/push 0/imm32
     9220     89/<- %edx 4/r32/esp
     9221     (tailor-exit-descriptor %edx 0x10)
     9222     #
     9223     (write _test-input-stream "fn foo {\n")
     9224     (write _test-input-stream "  var x: (handle int)\n")
     9225     (write _test-input-stream "  var y/eax: (addr byte) <- copy 0\n")
     9226     (write _test-input-stream "  copy-byte-to *y, x\n")
     9227     (write _test-input-stream "}\n")
     9228     # convert
     9229     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     9230     # registers except esp clobbered at this point
     9231     # restore ed
     9232     89/<- %edx 4/r32/esp
     9233     (flush _test-output-buffered-file)
     9234     (flush _test-error-buffered-file)
     9235 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     9241     # check output
     9242     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-to-from-non-scalar-inout: output should be empty")
     9243     (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")
     9244     # check that stop(1) was called
     9245     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-to-from-non-scalar-inout: exit status")
     9246     # don't restore from ebp
     9247     81 0/subop/add %esp 8/imm32
     9248     # . epilogue
     9249     5d/pop-to-ebp
     9250     c3/return
     9251
     9252 test-compare-with-no-inout:
     9253     # . prologue
     9254     55/push-ebp
     9255     89/<- %ebp 4/r32/esp
     9256     # setup
     9257     (clear-stream _test-input-stream)
     9258     (clear-stream $_test-input-buffered-file->buffer)
     9259     (clear-stream _test-output-stream)
     9260     (clear-stream $_test-output-buffered-file->buffer)
     9261     (clear-stream _test-error-stream)
     9262     (clear-stream $_test-error-buffered-file->buffer)
     9263     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     9264     68/push 0/imm32
     9265     68/push 0/imm32
     9266     89/<- %edx 4/r32/esp
     9267     (tailor-exit-descriptor %edx 0x10)
     9268     #
     9269     (write _test-input-stream "fn foo {\n")
     9270     (write _test-input-stream "  var x: boolean\n")
     9271     (write _test-input-stream "  compare\n")
     9272     (write _test-input-stream "}\n")
     9273     # convert
     9274     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     9275     # registers except esp clobbered at this point
     9276     # restore ed
     9277     89/<- %edx 4/r32/esp
     9278     (flush _test-output-buffered-file)
     9279     (flush _test-error-buffered-file)
     9280 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     9286     # check output
     9287     (check-stream-equal _test-output-stream  ""  "F - test-compare-with-no-inout: output should be empty")
     9288     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'compare' must have two inouts"  "F - test-compare-with-no-inout: error message")
     9289     # check that stop(1) was called
     9290     (check-ints-equal *(edx+4) 2 "F - test-compare-with-no-inout: exit status")
     9291     # don't restore from ebp
     9292     81 0/subop/add %esp 8/imm32
     9293     # . epilogue
     9294     5d/pop-to-ebp
     9295     c3/return
     9296
     9297 test-compare-with-just-one-inout:
     9298     # . prologue
     9299     55/push-ebp
     9300     89/<- %ebp 4/r32/esp
     9301     # setup
     9302     (clear-stream _test-input-stream)
     9303     (clear-stream $_test-input-buffered-file->buffer)
     9304     (clear-stream _test-output-stream)
     9305     (clear-stream $_test-output-buffered-file->buffer)
     9306     (clear-stream _test-error-stream)
     9307     (clear-stream $_test-error-buffered-file->buffer)
     9308     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     9309     68/push 0/imm32
     9310     68/push 0/imm32
     9311     89/<- %edx 4/r32/esp
     9312     (tailor-exit-descriptor %edx 0x10)
     9313     #
     9314     (write _test-input-stream "fn foo {\n")
     9315     (write _test-input-stream "  var x: boolean\n")
     9316     (write _test-input-stream "  compare x\n")
     9317     (write _test-input-stream "}\n")
     9318     # convert
     9319     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     9320     # registers except esp clobbered at this point
     9321     # restore ed
     9322     89/<- %edx 4/r32/esp
     9323     (flush _test-output-buffered-file)
     9324     (flush _test-error-buffered-file)
     9325 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     9331     # check output
     9332     (check-stream-equal _test-output-stream  ""  "F - test-compare-with-just-one-inout: output should be empty")
     9333     (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")
     9334     # check that stop(1) was called
     9335     (check-ints-equal *(edx+4) 2 "F - test-compare-with-just-one-inout: exit status")
     9336     # don't restore from ebp
     9337     81 0/subop/add %esp 8/imm32
     9338     # . epilogue
     9339     5d/pop-to-ebp
     9340     c3/return
     9341
     9342 test-compare-with-too-many-inouts:
     9343     # . prologue
     9344     55/push-ebp
     9345     89/<- %ebp 4/r32/esp
     9346     # setup
     9347     (clear-stream _test-input-stream)
     9348     (clear-stream $_test-input-buffered-file->buffer)
     9349     (clear-stream _test-output-stream)
     9350     (clear-stream $_test-output-buffered-file->buffer)
     9351     (clear-stream _test-error-stream)
     9352     (clear-stream $_test-error-buffered-file->buffer)
     9353     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     9354     68/push 0/imm32
     9355     68/push 0/imm32
     9356     89/<- %edx 4/r32/esp
     9357     (tailor-exit-descriptor %edx 0x10)
     9358     #
     9359     (write _test-input-stream "fn foo {\n")
     9360     (write _test-input-stream "  var x: boolean\n")
     9361     (write _test-input-stream "  compare x, 0, 0\n")
     9362     (write _test-input-stream "}\n")
     9363     # convert
     9364     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     9365     # registers except esp clobbered at this point
     9366     # restore ed
     9367     89/<- %edx 4/r32/esp
     9368     (flush _test-output-buffered-file)
     9369     (flush _test-error-buffered-file)
     9370 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     9376     # check output
     9377     (check-stream-equal _test-output-stream  ""  "F - test-compare-with-too-many-inouts: output should be empty")
     9378     (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")
     9379     # check that stop(1) was called
     9380     (check-ints-equal *(edx+4) 2 "F - test-compare-with-too-many-inouts: exit status")
     9381     # don't restore from ebp
     9382     81 0/subop/add %esp 8/imm32
     9383     # . epilogue
     9384     5d/pop-to-ebp
     9385     c3/return
     9386
     9387 test-compare-with-output:
     9388     # . prologue
     9389     55/push-ebp
     9390     89/<- %ebp 4/r32/esp
     9391     # setup
     9392     (clear-stream _test-input-stream)
     9393     (clear-stream $_test-input-buffered-file->buffer)
     9394     (clear-stream _test-output-stream)
     9395     (clear-stream $_test-output-buffered-file->buffer)
     9396     (clear-stream _test-error-stream)
     9397     (clear-stream $_test-error-buffered-file->buffer)
     9398     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     9399     68/push 0/imm32
     9400     68/push 0/imm32
     9401     89/<- %edx 4/r32/esp
     9402     (tailor-exit-descriptor %edx 0x10)
     9403     #
     9404     (write _test-input-stream "fn foo {\n")
     9405     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
     9406     (write _test-input-stream "  var y/ecx: boolean <- copy 0\n")
     9407     (write _test-input-stream "  x <- compare y, 0\n")
     9408     (write _test-input-stream "}\n")
     9409     # convert
     9410     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     9411     # registers except esp clobbered at this point
     9412     # restore ed
     9413     89/<- %edx 4/r32/esp
     9414     (flush _test-output-buffered-file)
     9415     (flush _test-error-buffered-file)
     9416 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     9422     # check output
     9423     (check-stream-equal _test-output-stream  ""  "F - test-compare-with-output: output should be empty")
     9424     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'compare' must not have any outputs"  "F - test-compare-with-output: error message")
     9425     # check that stop(1) was called
     9426     (check-ints-equal *(edx+4) 2 "F - test-compare-with-output: exit status")
     9427     # don't restore from ebp
     9428     81 0/subop/add %esp 8/imm32
     9429     # . epilogue
     9430     5d/pop-to-ebp
     9431     c3/return
     9432
     9433 test-compare-invalid-value-to-address:
     9434     # . prologue
     9435     55/push-ebp
     9436     89/<- %ebp 4/r32/esp
     9437     # setup
     9438     (clear-stream _test-input-stream)
     9439     (clear-stream $_test-input-buffered-file->buffer)
     9440     (clear-stream _test-output-stream)
     9441     (clear-stream $_test-output-buffered-file->buffer)
     9442     (clear-stream _test-error-stream)
     9443     (clear-stream $_test-error-buffered-file->buffer)
     9444     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     9445     68/push 0/imm32
     9446     68/push 0/imm32
     9447     89/<- %edx 4/r32/esp
     9448     (tailor-exit-descriptor %edx 0x10)
     9449     #
     9450     (write _test-input-stream "fn foo {\n")
     9451     (write _test-input-stream "  var x/eax: int <- copy 0\n")
     9452     (write _test-input-stream "  var y: (addr int)\n")
     9453     (write _test-input-stream "  compare y, x\n")
     9454     (write _test-input-stream "}\n")
     9455     # convert
     9456     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     9457     # registers except esp clobbered at this point
     9458     # restore ed
     9459     89/<- %edx 4/r32/esp
     9460     (flush _test-output-buffered-file)
     9461     (flush _test-error-buffered-file)
     9462 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     9468     # check output
     9469     (check-stream-equal _test-output-stream  ""  "F - test-compare-invalid-value-to-address: output should be empty")
     9470     (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")
     9471     # check that stop(1) was called
     9472     (check-ints-equal *(edx+4) 2 "F - test-compare-invalid-value-to-address: exit status")
     9473     # don't restore from ebp
     9474     81 0/subop/add %esp 8/imm32
     9475     # . epilogue
     9476     5d/pop-to-ebp
     9477     c3/return
     9478
     9479 test-compare-address:
     9480     # . prologue
     9481     55/push-ebp
     9482     89/<- %ebp 4/r32/esp
     9483     # setup
     9484     (clear-stream _test-input-stream)
     9485     (clear-stream $_test-input-buffered-file->buffer)
     9486     (clear-stream _test-output-stream)
     9487     (clear-stream $_test-output-buffered-file->buffer)
     9488     #
     9489     (write _test-input-stream "fn foo {\n")
     9490     (write _test-input-stream "  var x/eax: (addr int) <- copy 0\n")
     9491     (write _test-input-stream "  var y/ecx: (addr int) <- copy 0\n")
     9492     (write _test-input-stream "  compare y, x\n")
     9493     (write _test-input-stream "}\n")
     9494     # convert
     9495     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     9496     (flush _test-output-buffered-file)
     9497     # no errors
     9498     # . epilogue
     9499     5d/pop-to-ebp
     9500     c3/return
     9501
     9502 test-compare-deref-address:
     9503     # . prologue
     9504     55/push-ebp
     9505     89/<- %ebp 4/r32/esp
     9506     # setup
     9507     (clear-stream _test-input-stream)
     9508     (clear-stream $_test-input-buffered-file->buffer)
     9509     (clear-stream _test-output-stream)
     9510     (clear-stream $_test-output-buffered-file->buffer)
     9511     #
     9512     (write _test-input-stream "fn foo {\n")
     9513     (write _test-input-stream "  var x/eax: (addr int) <- copy 0\n")
     9514     (write _test-input-stream "  var y/ecx: (addr addr int) <- copy 0\n")
     9515     (write _test-input-stream "  compare *y, x\n")
     9516     (write _test-input-stream "}\n")
     9517     # convert
     9518     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     9519     (flush _test-output-buffered-file)
     9520     # no errors
     9521     # . epilogue
     9522     5d/pop-to-ebp
     9523     c3/return
     9524
     9525 test-compare-two-vars-in-memory:
     9526     # . prologue
     9527     55/push-ebp
     9528     89/<- %ebp 4/r32/esp
     9529     # setup
     9530     (clear-stream _test-input-stream)
     9531     (clear-stream $_test-input-buffered-file->buffer)
     9532     (clear-stream _test-output-stream)
     9533     (clear-stream $_test-output-buffered-file->buffer)
     9534     (clear-stream _test-error-stream)
     9535     (clear-stream $_test-error-buffered-file->buffer)
     9536     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     9537     68/push 0/imm32
     9538     68/push 0/imm32
     9539     89/<- %edx 4/r32/esp
     9540     (tailor-exit-descriptor %edx 0x10)
     9541     #
     9542     (write _test-input-stream "fn foo {\n")
     9543     (write _test-input-stream "  var x: boolean\n")
     9544     (write _test-input-stream "  compare x, x\n")
     9545     (write _test-input-stream "}\n")
     9546     # convert
     9547     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     9548     # registers except esp clobbered at this point
     9549     # restore ed
     9550     89/<- %edx 4/r32/esp
     9551     (flush _test-output-buffered-file)
     9552     (flush _test-error-buffered-file)
     9553 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     9559     # check output
     9560     (check-stream-equal _test-output-stream  ""  "F - test-compare-two-vars-in-memory: output should be empty")
     9561     (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")
     9562     # check that stop(1) was called
     9563     (check-ints-equal *(edx+4) 2 "F - test-compare-two-vars-in-memory: exit status")
     9564     # don't restore from ebp
     9565     81 0/subop/add %esp 8/imm32
     9566     # . epilogue
     9567     5d/pop-to-ebp
     9568     c3/return
     9569
     9570 test-compare-non-scalar:
     9571     # . prologue
     9572     55/push-ebp
     9573     89/<- %ebp 4/r32/esp
     9574     # setup
     9575     (clear-stream _test-input-stream)
     9576     (clear-stream $_test-input-buffered-file->buffer)
     9577     (clear-stream _test-output-stream)
     9578     (clear-stream $_test-output-buffered-file->buffer)
     9579     (clear-stream _test-error-stream)
     9580     (clear-stream $_test-error-buffered-file->buffer)
     9581     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     9582     68/push 0/imm32
     9583     68/push 0/imm32
     9584     89/<- %edx 4/r32/esp
     9585     (tailor-exit-descriptor %edx 0x10)
     9586     #
     9587     (write _test-input-stream "fn foo {\n")
     9588     (write _test-input-stream "  var x: (handle int)\n")
     9589     (write _test-input-stream "  var y: int\n")
     9590     (write _test-input-stream "  compare y, x\n")
     9591     (write _test-input-stream "}\n")
     9592     # convert
     9593     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     9594     # registers except esp clobbered at this point
     9595     # restore ed
     9596     89/<- %edx 4/r32/esp
     9597     (flush _test-output-buffered-file)
     9598     (flush _test-error-buffered-file)
     9599 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     9605     # check output
     9606     (check-stream-equal _test-output-stream  ""  "F - test-compare-non-scalar: output should be empty")
     9607 #?     (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")
     9608     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt compare: both inouts are in memory"  "F - test-compare-non-scalar: error message")
     9609     # check that stop(1) was called
     9610     (check-ints-equal *(edx+4) 2 "F - test-compare-non-scalar: exit status")
     9611     # don't restore from ebp
     9612     81 0/subop/add %esp 8/imm32
     9613     # . epilogue
     9614     5d/pop-to-ebp
     9615     c3/return
     9616
     9617 test-compare-with-string-literal:
     9618     # . prologue
     9619     55/push-ebp
     9620     89/<- %ebp 4/r32/esp
     9621     # setup
     9622     (clear-stream _test-input-stream)
     9623     (clear-stream $_test-input-buffered-file->buffer)
     9624     (clear-stream _test-output-stream)
     9625     (clear-stream $_test-output-buffered-file->buffer)
     9626     (clear-stream _test-error-stream)
     9627     (clear-stream $_test-error-buffered-file->buffer)
     9628     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     9629     68/push 0/imm32
     9630     68/push 0/imm32
     9631     89/<- %edx 4/r32/esp
     9632     (tailor-exit-descriptor %edx 0x10)
     9633     #
     9634     (write _test-input-stream "fn foo {\n")
     9635     (write _test-input-stream "  var x/eax: (addr array byte) <- copy 0\n")
     9636     (write _test-input-stream "  compare x, \"abc\"\n")
     9637     (write _test-input-stream "}\n")
     9638     # convert
     9639     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     9640     # registers except esp clobbered at this point
     9641     # restore ed
     9642     89/<- %edx 4/r32/esp
     9643     (flush _test-output-buffered-file)
     9644     (flush _test-error-buffered-file)
     9645 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     9651     # check output
     9652     (check-stream-equal _test-output-stream  ""  "F - test-compare-with-string-literal: output should be empty")
     9653     (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")
     9654     # check that stop(1) was called
     9655     (check-ints-equal *(edx+4) 2 "F - test-compare-with-string-literal: exit status")
     9656     # don't restore from ebp
     9657     81 0/subop/add %esp 8/imm32
     9658     # . epilogue
     9659     5d/pop-to-ebp
     9660     c3/return
     9661
     9662 test-address-with-no-inout:
     9663     # . prologue
     9664     55/push-ebp
     9665     89/<- %ebp 4/r32/esp
     9666     # setup
     9667     (clear-stream _test-input-stream)
     9668     (clear-stream $_test-input-buffered-file->buffer)
     9669     (clear-stream _test-output-stream)
     9670     (clear-stream $_test-output-buffered-file->buffer)
     9671     (clear-stream _test-error-stream)
     9672     (clear-stream $_test-error-buffered-file->buffer)
     9673     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     9674     68/push 0/imm32
     9675     68/push 0/imm32
     9676     89/<- %edx 4/r32/esp
     9677     (tailor-exit-descriptor %edx 0x10)
     9678     #
     9679     (write _test-input-stream "fn foo {\n")
     9680     (write _test-input-stream "  var x/eax: boolean <- address\n")
     9681     (write _test-input-stream "}\n")
     9682     # convert
     9683     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     9684     # registers except esp clobbered at this point
     9685     # restore ed
     9686     89/<- %edx 4/r32/esp
     9687     (flush _test-output-buffered-file)
     9688     (flush _test-error-buffered-file)
     9689 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     9695     # check output
     9696     (check-stream-equal _test-output-stream  ""  "F - test-address-with-no-inout: output should be empty")
     9697     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'address' expects an inout"  "F - test-address-with-no-inout: error message")
     9698     # check that stop(1) was called
     9699     (check-ints-equal *(edx+4) 2 "F - test-address-with-no-inout: exit status")
     9700     # don't restore from ebp
     9701     81 0/subop/add %esp 8/imm32
     9702     # . epilogue
     9703     5d/pop-to-ebp
     9704     c3/return
     9705
     9706 test-address-with-multiple-inouts:
     9707     # . prologue
     9708     55/push-ebp
     9709     89/<- %ebp 4/r32/esp
     9710     # setup
     9711     (clear-stream _test-input-stream)
     9712     (clear-stream $_test-input-buffered-file->buffer)
     9713     (clear-stream _test-output-stream)
     9714     (clear-stream $_test-output-buffered-file->buffer)
     9715     (clear-stream _test-error-stream)
     9716     (clear-stream $_test-error-buffered-file->buffer)
     9717     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     9718     68/push 0/imm32
     9719     68/push 0/imm32
     9720     89/<- %edx 4/r32/esp
     9721     (tailor-exit-descriptor %edx 0x10)
     9722     #
     9723     (write _test-input-stream "fn foo {\n")
     9724     (write _test-input-stream "  var x/eax: boolean <- address 0, 0\n")
     9725     (write _test-input-stream "}\n")
     9726     # convert
     9727     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     9728     # registers except esp clobbered at this point
     9729     # restore ed
     9730     89/<- %edx 4/r32/esp
     9731     (flush _test-output-buffered-file)
     9732     (flush _test-error-buffered-file)
     9733 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     9739     # check output
     9740     (check-stream-equal _test-output-stream  ""  "F - test-address-with-multiple-inouts: output should be empty")
     9741     (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")
     9742     # check that stop(1) was called
     9743     (check-ints-equal *(edx+4) 2 "F - test-address-with-multiple-inouts: exit status")
     9744     # don't restore from ebp
     9745     81 0/subop/add %esp 8/imm32
     9746     # . epilogue
     9747     5d/pop-to-ebp
     9748     c3/return
     9749
     9750 test-address-with-no-output:
     9751     # . prologue
     9752     55/push-ebp
     9753     89/<- %ebp 4/r32/esp
     9754     # setup
     9755     (clear-stream _test-input-stream)
     9756     (clear-stream $_test-input-buffered-file->buffer)
     9757     (clear-stream _test-output-stream)
     9758     (clear-stream $_test-output-buffered-file->buffer)
     9759     (clear-stream _test-error-stream)
     9760     (clear-stream $_test-error-buffered-file->buffer)
     9761     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     9762     68/push 0/imm32
     9763     68/push 0/imm32
     9764     89/<- %edx 4/r32/esp
     9765     (tailor-exit-descriptor %edx 0x10)
     9766     #
     9767     (write _test-input-stream "fn foo {\n")
     9768     (write _test-input-stream "  address 0\n")
     9769     (write _test-input-stream "}\n")
     9770     # convert
     9771     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     9772     # registers except esp clobbered at this point
     9773     # restore ed
     9774     89/<- %edx 4/r32/esp
     9775     (flush _test-output-buffered-file)
     9776     (flush _test-error-buffered-file)
     9777 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     9783     # check output
     9784     (check-stream-equal _test-output-stream  ""  "F - test-address-with-no-output: output should be empty")
     9785     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'address' expects an output"  "F - test-address-with-no-output: error message")
     9786     # check that stop(1) was called
     9787     (check-ints-equal *(edx+4) 2 "F - test-address-with-no-output: exit status")
     9788     # don't restore from ebp
     9789     81 0/subop/add %esp 8/imm32
     9790     # . epilogue
     9791     5d/pop-to-ebp
     9792     c3/return
     9793
     9794 test-address-with-multiple-outputs:
     9795     # . prologue
     9796     55/push-ebp
     9797     89/<- %ebp 4/r32/esp
     9798     # setup
     9799     (clear-stream _test-input-stream)
     9800     (clear-stream $_test-input-buffered-file->buffer)
     9801     (clear-stream _test-output-stream)
     9802     (clear-stream $_test-output-buffered-file->buffer)
     9803     (clear-stream _test-error-stream)
     9804     (clear-stream $_test-error-buffered-file->buffer)
     9805     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     9806     68/push 0/imm32
     9807     68/push 0/imm32
     9808     89/<- %edx 4/r32/esp
     9809     (tailor-exit-descriptor %edx 0x10)
     9810     #
     9811     (write _test-input-stream "fn foo {\n")
     9812     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
     9813     (write _test-input-stream "  var y/ecx: boolean <- copy 0\n")
     9814     (write _test-input-stream "  x, y <- address 0\n")
     9815     (write _test-input-stream "}\n")
     9816     # convert
     9817     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     9818     # registers except esp clobbered at this point
     9819     # restore ed
     9820     89/<- %edx 4/r32/esp
     9821     (flush _test-output-buffered-file)
     9822     (flush _test-error-buffered-file)
     9823 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     9829     # check output
     9830     (check-stream-equal _test-output-stream  ""  "F - test-address-with-multiple-outputs: output should be empty")
     9831     (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")
     9832     # check that stop(1) was called
     9833     (check-ints-equal *(edx+4) 2 "F - test-address-with-multiple-outputs: exit status")
     9834     # don't restore from ebp
     9835     81 0/subop/add %esp 8/imm32
     9836     # . epilogue
     9837     5d/pop-to-ebp
     9838     c3/return
     9839
     9840 # silly but it works
     9841 test-address-of-deref:
     9842     # . prologue
     9843     55/push-ebp
     9844     89/<- %ebp 4/r32/esp
     9845     # setup
     9846     (clear-stream _test-input-stream)
     9847     (clear-stream $_test-input-buffered-file->buffer)
     9848     (clear-stream _test-output-stream)
     9849     (clear-stream $_test-output-buffered-file->buffer)
     9850     #
     9851     (write _test-input-stream "fn foo {\n")
     9852     (write _test-input-stream "  var x/eax: (addr int) <- copy 0\n")
     9853     (write _test-input-stream "  var y/ecx: (addr int) <- address *x\n")
     9854     (write _test-input-stream "}\n")
     9855     # convert
     9856     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     9857     (flush _test-output-buffered-file)
     9858     # no errors
     9859     # . epilogue
     9860     5d/pop-to-ebp
     9861     c3/return
     9862
     9863 test-address-to-non-register:
     9864     # . prologue
     9865     55/push-ebp
     9866     89/<- %ebp 4/r32/esp
     9867     # setup
     9868     (clear-stream _test-input-stream)
     9869     (clear-stream $_test-input-buffered-file->buffer)
     9870     (clear-stream _test-output-stream)
     9871     (clear-stream $_test-output-buffered-file->buffer)
     9872     (clear-stream _test-error-stream)
     9873     (clear-stream $_test-error-buffered-file->buffer)
     9874     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     9875     68/push 0/imm32
     9876     68/push 0/imm32
     9877     89/<- %edx 4/r32/esp
     9878     (tailor-exit-descriptor %edx 0x10)
     9879     #
     9880     (write _test-input-stream "fn foo {\n")
     9881     (write _test-input-stream "  var x: (addr int)\n")
     9882     (write _test-input-stream "  x <- address 0\n")
     9883     (write _test-input-stream "}\n")
     9884     # convert
     9885     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     9886     # registers except esp clobbered at this point
     9887     # restore ed
     9888     89/<- %edx 4/r32/esp
     9889     (flush _test-output-buffered-file)
     9890     (flush _test-error-buffered-file)
     9891 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     9897     # check output
     9898     (check-stream-equal _test-output-stream  ""  "F - test-address-to-non-register: output should be empty")
     9899     (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")
     9900     # check that stop(1) was called
     9901     (check-ints-equal *(edx+4) 2 "F - test-address-to-non-register: exit status")
     9902     # don't restore from ebp
     9903     81 0/subop/add %esp 8/imm32
     9904     # . epilogue
     9905     5d/pop-to-ebp
     9906     c3/return
     9907
     9908 test-address-with-wrong-type:
     9909     # . prologue
     9910     55/push-ebp
     9911     89/<- %ebp 4/r32/esp
     9912     # setup
     9913     (clear-stream _test-input-stream)
     9914     (clear-stream $_test-input-buffered-file->buffer)
     9915     (clear-stream _test-output-stream)
     9916     (clear-stream $_test-output-buffered-file->buffer)
     9917     (clear-stream _test-error-stream)
     9918     (clear-stream $_test-error-buffered-file->buffer)
     9919     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     9920     68/push 0/imm32
     9921     68/push 0/imm32
     9922     89/<- %edx 4/r32/esp
     9923     (tailor-exit-descriptor %edx 0x10)
     9924     #
     9925     (write _test-input-stream "fn foo {\n")
     9926     (write _test-input-stream "  var x: int\n")
     9927     (write _test-input-stream "  var y/eax: (addr boolean) <- address x\n")
     9928     (write _test-input-stream "}\n")
     9929     # convert
     9930     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     9931     # registers except esp clobbered at this point
     9932     # restore ed
     9933     89/<- %edx 4/r32/esp
     9934     (flush _test-output-buffered-file)
     9935     (flush _test-error-buffered-file)
     9936 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
     9942     # check output
     9943     (check-stream-equal _test-output-stream  ""  "F - test-address-with-wrong-type: output should be empty")
     9944     (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")
     9945     # check that stop(1) was called
     9946     (check-ints-equal *(edx+4) 2 "F - test-address-with-wrong-type: exit status")
     9947     # don't restore from ebp
     9948     81 0/subop/add %esp 8/imm32
     9949     # . epilogue
     9950     5d/pop-to-ebp
     9951     c3/return
     9952
     9953 test-address-with-right-type-for-array:
     9954     # . prologue
     9955     55/push-ebp
     9956     89/<- %ebp 4/r32/esp
     9957     # setup
     9958     (clear-stream _test-input-stream)
     9959     (clear-stream $_test-input-buffered-file->buffer)
     9960     (clear-stream _test-output-stream)
     9961     (clear-stream $_test-output-buffered-file->buffer)
     9962     #
     9963     (write _test-input-stream "fn foo {\n")
     9964     (write _test-input-stream "  var x: (array int 3)\n")
     9965     (write _test-input-stream "  var y/eax: (addr array int) <- address x\n")
     9966     (write _test-input-stream "}\n")
     9967     # convert
     9968     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     9969     (flush _test-output-buffered-file)
     9970     # no errors
     9971     # . epilogue
     9972     89/<- %esp 5/r32/ebp
     9973     5d/pop-to-ebp
     9974     c3/return
     9975
     9976 test-address-with-right-type-for-stream:
     9977     # . prologue
     9978     55/push-ebp
     9979     89/<- %ebp 4/r32/esp
     9980     # setup
     9981     (clear-stream _test-input-stream)
     9982     (clear-stream $_test-input-buffered-file->buffer)
     9983     (clear-stream _test-output-stream)
     9984     (clear-stream $_test-output-buffered-file->buffer)
     9985     #
     9986     (write _test-input-stream "fn foo {\n")
     9987     (write _test-input-stream "  var x: (stream int 3)\n")
     9988     (write _test-input-stream "  var y/eax: (addr stream int) <- address x\n")
     9989     (write _test-input-stream "}\n")
     9990     # convert
     9991     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     9992     (flush _test-output-buffered-file)
     9993     # no errors
     9994     # . epilogue
     9995     89/<- %esp 5/r32/ebp
     9996     5d/pop-to-ebp
     9997     c3/return
     9998
     9999 test-get-with-wrong-field:
    10000     # . prologue
    10001     55/push-ebp
    10002     89/<- %ebp 4/r32/esp
    10003     # setup
    10004     (clear-stream _test-input-stream)
    10005     (clear-stream $_test-input-buffered-file->buffer)
    10006     (clear-stream _test-output-stream)
    10007     (clear-stream $_test-output-buffered-file->buffer)
    10008     (clear-stream _test-error-stream)
    10009     (clear-stream $_test-error-buffered-file->buffer)
    10010     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    10011     68/push 0/imm32
    10012     68/push 0/imm32
    10013     89/<- %edx 4/r32/esp
    10014     (tailor-exit-descriptor %edx 0x10)
    10015     #
    10016     (write _test-input-stream "fn foo {\n")
    10017     (write _test-input-stream "  var a: t\n")
    10018     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
    10019     (write _test-input-stream "}\n")
    10020     (write _test-input-stream "type t {\n")
    10021     (write _test-input-stream "  x: int\n")
    10022     (write _test-input-stream "}\n")
    10023     # convert
    10024     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    10025     # registers except esp clobbered at this point
    10026     # restore ed
    10027     89/<- %edx 4/r32/esp
    10028     (flush _test-output-buffered-file)
    10029     (flush _test-error-buffered-file)
    10030 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    10036     # check output
    10037     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-field: output should be empty")
    10038     (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")
    10039     # check that stop(1) was called
    10040     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-field: exit status")
    10041     # don't restore from ebp
    10042     81 0/subop/add %esp 8/imm32
    10043     # . epilogue
    10044     5d/pop-to-ebp
    10045     c3/return
    10046
    10047 test-get-with-wrong-base-type:
    10048     # . prologue
    10049     55/push-ebp
    10050     89/<- %ebp 4/r32/esp
    10051     # setup
    10052     (clear-stream _test-input-stream)
    10053     (clear-stream $_test-input-buffered-file->buffer)
    10054     (clear-stream _test-output-stream)
    10055     (clear-stream $_test-output-buffered-file->buffer)
    10056     (clear-stream _test-error-stream)
    10057     (clear-stream $_test-error-buffered-file->buffer)
    10058     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    10059     68/push 0/imm32
    10060     68/push 0/imm32
    10061     89/<- %edx 4/r32/esp
    10062     (tailor-exit-descriptor %edx 0x10)
    10063     #
    10064     (write _test-input-stream "fn foo {\n")
    10065     (write _test-input-stream "  var a: int\n")
    10066     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
    10067     (write _test-input-stream "}\n")
    10068     # convert
    10069     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    10070     # registers except esp clobbered at this point
    10071     # restore ed
    10072     89/<- %edx 4/r32/esp
    10073     (flush _test-output-buffered-file)
    10074     (flush _test-error-buffered-file)
    10075 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    10081     # check output
    10082     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-base-type: output should be empty")
    10083     (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")
    10084     # check that stop(1) was called
    10085     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-base-type: exit status")
    10086     # don't restore from ebp
    10087     81 0/subop/add %esp 8/imm32
    10088     # . epilogue
    10089     5d/pop-to-ebp
    10090     c3/return
    10091
    10092 test-get-with-wrong-base-type-2:
    10093     # . prologue
    10094     55/push-ebp
    10095     89/<- %ebp 4/r32/esp
    10096     # setup
    10097     (clear-stream _test-input-stream)
    10098     (clear-stream $_test-input-buffered-file->buffer)
    10099     (clear-stream _test-output-stream)
    10100     (clear-stream $_test-output-buffered-file->buffer)
    10101     (clear-stream _test-error-stream)
    10102     (clear-stream $_test-error-buffered-file->buffer)
    10103     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    10104     68/push 0/imm32
    10105     68/push 0/imm32
    10106     89/<- %edx 4/r32/esp
    10107     (tailor-exit-descriptor %edx 0x10)
    10108     #
    10109     (write _test-input-stream "fn foo {\n")
    10110     (write _test-input-stream "  var a: (addr t)\n")
    10111     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
    10112     (write _test-input-stream "}\n")
    10113     (write _test-input-stream "type t {\n")
    10114     (write _test-input-stream "  x: int\n")
    10115     (write _test-input-stream "}\n")
    10116     # convert
    10117     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    10118     # registers except esp clobbered at this point
    10119     # restore ed
    10120     89/<- %edx 4/r32/esp
    10121     (flush _test-output-buffered-file)
    10122     (flush _test-error-buffered-file)
    10123 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    10129     # check output
    10130     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-base-type-2: output should be empty")
    10131     (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")
    10132     # check that stop(1) was called
    10133     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-base-type-2: exit status")
    10134     # don't restore from ebp
    10135     81 0/subop/add %esp 8/imm32
    10136     # . epilogue
    10137     5d/pop-to-ebp
    10138     c3/return
    10139
    10140 test-get-with-wrong-base-type-3:
    10141     # . prologue
    10142     55/push-ebp
    10143     89/<- %ebp 4/r32/esp
    10144     # setup
    10145     (clear-stream _test-input-stream)
    10146     (clear-stream $_test-input-buffered-file->buffer)
    10147     (clear-stream _test-output-stream)
    10148     (clear-stream $_test-output-buffered-file->buffer)
    10149     (clear-stream _test-error-stream)
    10150     (clear-stream $_test-error-buffered-file->buffer)
    10151     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    10152     68/push 0/imm32
    10153     68/push 0/imm32
    10154     89/<- %edx 4/r32/esp
    10155     (tailor-exit-descriptor %edx 0x10)
    10156     #
    10157     (write _test-input-stream "fn foo {\n")
    10158     (write _test-input-stream "  var a: (handle int)\n")
    10159     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
    10160     (write _test-input-stream "}\n")
    10161     # convert
    10162     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    10163     # registers except esp clobbered at this point
    10164     # restore ed
    10165     89/<- %edx 4/r32/esp
    10166     (flush _test-output-buffered-file)
    10167     (flush _test-error-buffered-file)
    10168 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    10174     # check output
    10175     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-base-type-3: output should be empty")
    10176     (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")
    10177     # check that stop(1) was called
    10178     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-base-type-3: exit status")
    10179     # don't restore from ebp
    10180     81 0/subop/add %esp 8/imm32
    10181     # . epilogue
    10182     5d/pop-to-ebp
    10183     c3/return
    10184
    10185 test-get-with-wrong-offset-type:
    10186     # . prologue
    10187     55/push-ebp
    10188     89/<- %ebp 4/r32/esp
    10189     # setup
    10190     (clear-stream _test-input-stream)
    10191     (clear-stream $_test-input-buffered-file->buffer)
    10192     (clear-stream _test-output-stream)
    10193     (clear-stream $_test-output-buffered-file->buffer)
    10194     (clear-stream _test-error-stream)
    10195     (clear-stream $_test-error-buffered-file->buffer)
    10196     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    10197     68/push 0/imm32
    10198     68/push 0/imm32
    10199     89/<- %edx 4/r32/esp
    10200     (tailor-exit-descriptor %edx 0x10)
    10201     #
    10202     (write _test-input-stream "fn foo {\n")
    10203     (write _test-input-stream "  var a: t\n")
    10204     (write _test-input-stream "  var b: int\n")
    10205     (write _test-input-stream "  var c/ecx: (addr int) <- get a, b\n")
    10206     (write _test-input-stream "}\n")
    10207     (write _test-input-stream "type t {\n")
    10208     (write _test-input-stream "  x: int\n")
    10209     (write _test-input-stream "}\n")
    10210     # convert
    10211     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    10212     # registers except esp clobbered at this point
    10213     # restore ed
    10214     89/<- %edx 4/r32/esp
    10215     (flush _test-output-buffered-file)
    10216     (flush _test-error-buffered-file)
    10217 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    10223     # check output
    10224     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-offset-type: output should be empty")
    10225     (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")
    10226     # check that stop(1) was called
    10227     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-offset-type: exit status")
    10228     # don't restore from ebp
    10229     81 0/subop/add %esp 8/imm32
    10230     # . epilogue
    10231     5d/pop-to-ebp
    10232     c3/return
    10233
    10234 test-get-with-wrong-output-type:
    10235     # . prologue
    10236     55/push-ebp
    10237     89/<- %ebp 4/r32/esp
    10238     # setup
    10239     (clear-stream _test-input-stream)
    10240     (clear-stream $_test-input-buffered-file->buffer)
    10241     (clear-stream _test-output-stream)
    10242     (clear-stream $_test-output-buffered-file->buffer)
    10243     (clear-stream _test-error-stream)
    10244     (clear-stream $_test-error-buffered-file->buffer)
    10245     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    10246     68/push 0/imm32
    10247     68/push 0/imm32
    10248     89/<- %edx 4/r32/esp
    10249     (tailor-exit-descriptor %edx 0x10)
    10250     #
    10251     (write _test-input-stream "fn foo {\n")
    10252     (write _test-input-stream "  var a: t\n")
    10253     (write _test-input-stream "  var c: (addr int)\n")
    10254     (write _test-input-stream "  c <- get a, x\n")
    10255     (write _test-input-stream "}\n")
    10256     (write _test-input-stream "type t {\n")
    10257     (write _test-input-stream "  x: int\n")
    10258     (write _test-input-stream "}\n")
    10259     # convert
    10260     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    10261     # registers except esp clobbered at this point
    10262     # restore ed
    10263     89/<- %edx 4/r32/esp
    10264     (flush _test-output-buffered-file)
    10265     (flush _test-error-buffered-file)
    10266 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    10272     # check output
    10273     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-output-type: output should be empty")
    10274     (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")
    10275     # check that stop(1) was called
    10276     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-output-type: exit status")
    10277     # don't restore from ebp
    10278     81 0/subop/add %esp 8/imm32
    10279     # . epilogue
    10280     5d/pop-to-ebp
    10281     c3/return
    10282
    10283 test-get-with-wrong-output-type-2:
    10284     # . prologue
    10285     55/push-ebp
    10286     89/<- %ebp 4/r32/esp
    10287     # setup
    10288     (clear-stream _test-input-stream)
    10289     (clear-stream $_test-input-buffered-file->buffer)
    10290     (clear-stream _test-output-stream)
    10291     (clear-stream $_test-output-buffered-file->buffer)
    10292     (clear-stream _test-error-stream)
    10293     (clear-stream $_test-error-buffered-file->buffer)
    10294     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    10295     68/push 0/imm32
    10296     68/push 0/imm32
    10297     89/<- %edx 4/r32/esp
    10298     (tailor-exit-descriptor %edx 0x10)
    10299     #
    10300     (write _test-input-stream "fn foo {\n")
    10301     (write _test-input-stream "  var a: t\n")
    10302     (write _test-input-stream "  var c/ecx: int <- get a, x\n")
    10303     (write _test-input-stream "}\n")
    10304     (write _test-input-stream "type t {\n")
    10305     (write _test-input-stream "  x: int\n")
    10306     (write _test-input-stream "}\n")
    10307     # convert
    10308     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    10309     # registers except esp clobbered at this point
    10310     # restore ed
    10311     89/<- %edx 4/r32/esp
    10312     (flush _test-output-buffered-file)
    10313     (flush _test-error-buffered-file)
    10314 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    10320     # check output
    10321     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-output-type-2: output should be empty")
    10322     (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")
    10323     # check that stop(1) was called
    10324     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-output-type-2: exit status")
    10325     # don't restore from ebp
    10326     81 0/subop/add %esp 8/imm32
    10327     # . epilogue
    10328     5d/pop-to-ebp
    10329     c3/return
    10330
    10331 test-get-with-wrong-output-type-3:
    10332     # . prologue
    10333     55/push-ebp
    10334     89/<- %ebp 4/r32/esp
    10335     # setup
    10336     (clear-stream _test-input-stream)
    10337     (clear-stream $_test-input-buffered-file->buffer)
    10338     (clear-stream _test-output-stream)
    10339     (clear-stream $_test-output-buffered-file->buffer)
    10340     (clear-stream _test-error-stream)
    10341     (clear-stream $_test-error-buffered-file->buffer)
    10342     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    10343     68/push 0/imm32
    10344     68/push 0/imm32
    10345     89/<- %edx 4/r32/esp
    10346     (tailor-exit-descriptor %edx 0x10)
    10347     #
    10348     (write _test-input-stream "fn foo {\n")
    10349     (write _test-input-stream "  var a: t\n")
    10350     (write _test-input-stream "  var c/ecx: (array int) <- get a, x\n")
    10351     (write _test-input-stream "}\n")
    10352     (write _test-input-stream "type t {\n")
    10353     (write _test-input-stream "  x: int\n")
    10354     (write _test-input-stream "}\n")
    10355     # convert
    10356     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    10357     # registers except esp clobbered at this point
    10358     # restore ed
    10359     89/<- %edx 4/r32/esp
    10360     (flush _test-output-buffered-file)
    10361     (flush _test-error-buffered-file)
    10362 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    10368     # check output
    10369     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-output-type-3: output should be empty")
    10370     (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")
    10371     # check that stop(1) was called
    10372     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-output-type-3: exit status")
    10373     # don't restore from ebp
    10374     81 0/subop/add %esp 8/imm32
    10375     # . epilogue
    10376     5d/pop-to-ebp
    10377     c3/return
    10378
    10379 test-get-with-wrong-output-type-4:
    10380     # . prologue
    10381     55/push-ebp
    10382     89/<- %ebp 4/r32/esp
    10383     # setup
    10384     (clear-stream _test-input-stream)
    10385     (clear-stream $_test-input-buffered-file->buffer)
    10386     (clear-stream _test-output-stream)
    10387     (clear-stream $_test-output-buffered-file->buffer)
    10388     (clear-stream _test-error-stream)
    10389     (clear-stream $_test-error-buffered-file->buffer)
    10390     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    10391     68/push 0/imm32
    10392     68/push 0/imm32
    10393     89/<- %edx 4/r32/esp
    10394     (tailor-exit-descriptor %edx 0x10)
    10395     #
    10396     (write _test-input-stream "fn foo {\n")
    10397     (write _test-input-stream "  var a: t\n")
    10398     (write _test-input-stream "  var c/ecx: (addr boolean) <- get a, x\n")
    10399     (write _test-input-stream "}\n")
    10400     (write _test-input-stream "type t {\n")
    10401     (write _test-input-stream "  x: int\n")
    10402     (write _test-input-stream "}\n")
    10403     # convert
    10404     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    10405     # registers except esp clobbered at this point
    10406     # restore ed
    10407     89/<- %edx 4/r32/esp
    10408     (flush _test-output-buffered-file)
    10409     (flush _test-error-buffered-file)
    10410 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    10416     # check output
    10417     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-output-type-4: output should be empty")
    10418     (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")
    10419     # check that stop(1) was called
    10420     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-output-type-4: exit status")
    10421     # don't restore from ebp
    10422     81 0/subop/add %esp 8/imm32
    10423     # . epilogue
    10424     5d/pop-to-ebp
    10425     c3/return
    10426
    10427 test-get-with-wrong-output-type-5:
    10428     # . prologue
    10429     55/push-ebp
    10430     89/<- %ebp 4/r32/esp
    10431     # setup
    10432     (clear-stream _test-input-stream)
    10433     (clear-stream $_test-input-buffered-file->buffer)
    10434     (clear-stream _test-output-stream)
    10435     (clear-stream $_test-output-buffered-file->buffer)
    10436     #
    10437     (write _test-input-stream "fn foo {\n")
    10438     (write _test-input-stream "  var a: t\n")
    10439     (write _test-input-stream "  var c/ecx: (addr handle int) <- get a, x\n")
    10440     (write _test-input-stream "}\n")
    10441     (write _test-input-stream "type t {\n")
    10442     (write _test-input-stream "  x: (handle int)\n")
    10443     (write _test-input-stream "}\n")
    10444     # convert
    10445     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
    10446     (flush _test-output-buffered-file)
    10447     # no errors
    10448     # . epilogue
    10449     89/<- %esp 5/r32/ebp
    10450     5d/pop-to-ebp
    10451     c3/return
    10452
    10453 test-get-with-too-few-inouts:
    10454     # . prologue
    10455     55/push-ebp
    10456     89/<- %ebp 4/r32/esp
    10457     # setup
    10458     (clear-stream _test-input-stream)
    10459     (clear-stream $_test-input-buffered-file->buffer)
    10460     (clear-stream _test-output-stream)
    10461     (clear-stream $_test-output-buffered-file->buffer)
    10462     (clear-stream _test-error-stream)
    10463     (clear-stream $_test-error-buffered-file->buffer)
    10464     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    10465     68/push 0/imm32
    10466     68/push 0/imm32
    10467     89/<- %edx 4/r32/esp
    10468     (tailor-exit-descriptor %edx 0x10)
    10469     #
    10470     (write _test-input-stream "fn foo {\n")
    10471     (write _test-input-stream "  var a: t\n")
    10472     (write _test-input-stream "  var c/ecx: (addr int) <- get a\n")
    10473     (write _test-input-stream "}\n")
    10474     (write _test-input-stream "type t {\n")
    10475     (write _test-input-stream "  x: int\n")
    10476     (write _test-input-stream "}\n")
    10477     # convert
    10478     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    10479     # registers except esp clobbered at this point
    10480     # restore ed
    10481     89/<- %edx 4/r32/esp
    10482     (flush _test-output-buffered-file)
    10483     (flush _test-error-buffered-file)
    10484 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    10490     # check output
    10491     (check-stream-equal _test-output-stream  ""  "F - test-get-with-too-few-inouts: output should be empty")
    10492     (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")
    10493     # check that stop(1) was called
    10494     (check-ints-equal *(edx+4) 2 "F - test-get-with-too-few-inouts: exit status")
    10495     # don't restore from ebp
    10496     81 0/subop/add %esp 8/imm32
    10497     # . epilogue
    10498     5d/pop-to-ebp
    10499     c3/return
    10500
    10501 test-get-with-too-many-inouts:
    10502     # . prologue
    10503     55/push-ebp
    10504     89/<- %ebp 4/r32/esp
    10505     # setup
    10506     (clear-stream _test-input-stream)
    10507     (clear-stream $_test-input-buffered-file->buffer)
    10508     (clear-stream _test-output-stream)
    10509     (clear-stream $_test-output-buffered-file->buffer)
    10510     (clear-stream _test-error-stream)
    10511     (clear-stream $_test-error-buffered-file->buffer)
    10512     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    10513     68/push 0/imm32
    10514     68/push 0/imm32
    10515     89/<- %edx 4/r32/esp
    10516     (tailor-exit-descriptor %edx 0x10)
    10517     #
    10518     (write _test-input-stream "fn foo {\n")
    10519     (write _test-input-stream "  var a: t\n")
    10520     (write _test-input-stream "  var c/ecx: (addr int) <- get a, x, 0\n")
    10521     (write _test-input-stream "}\n")
    10522     (write _test-input-stream "type t {\n")
    10523     (write _test-input-stream "  x: int\n")
    10524     (write _test-input-stream "}\n")
    10525     # convert
    10526     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    10527     # registers except esp clobbered at this point
    10528     # restore ed
    10529     89/<- %edx 4/r32/esp
    10530     (flush _test-output-buffered-file)
    10531     (flush _test-error-buffered-file)
    10532 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    10538     # check output
    10539     (check-stream-equal _test-output-stream  ""  "F - test-get-with-too-many-inouts: output should be empty")
    10540     (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")
    10541     # check that stop(1) was called
    10542     (check-ints-equal *(edx+4) 2 "F - test-get-with-too-many-inouts: exit status")
    10543     # don't restore from ebp
    10544     81 0/subop/add %esp 8/imm32
    10545     # . epilogue
    10546     5d/pop-to-ebp
    10547     c3/return
    10548
    10549 test-get-with-no-output:
    10550     # . prologue
    10551     55/push-ebp
    10552     89/<- %ebp 4/r32/esp
    10553     # setup
    10554     (clear-stream _test-input-stream)
    10555     (clear-stream $_test-input-buffered-file->buffer)
    10556     (clear-stream _test-output-stream)
    10557     (clear-stream $_test-output-buffered-file->buffer)
    10558     (clear-stream _test-error-stream)
    10559     (clear-stream $_test-error-buffered-file->buffer)
    10560     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    10561     68/push 0/imm32
    10562     68/push 0/imm32
    10563     89/<- %edx 4/r32/esp
    10564     (tailor-exit-descriptor %edx 0x10)
    10565     #
    10566     (write _test-input-stream "fn foo {\n")
    10567     (write _test-input-stream "  var a: t\n")
    10568     (write _test-input-stream "  get a, x\n")
    10569     (write _test-input-stream "}\n")
    10570     (write _test-input-stream "type t {\n")
    10571     (write _test-input-stream "  x: int\n")
    10572     (write _test-input-stream "}\n")
    10573     # convert
    10574     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    10575     # registers except esp clobbered at this point
    10576     # restore ed
    10577     89/<- %edx 4/r32/esp
    10578     (flush _test-output-buffered-file)
    10579     (flush _test-error-buffered-file)
    10580 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    10586     # check output
    10587     (check-stream-equal _test-output-stream  ""  "F - test-get-with-no-output: output should be empty")
    10588     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt get: must have an output"  "F - test-get-with-no-output: error message")
    10589     # check that stop(1) was called
    10590     (check-ints-equal *(edx+4) 2 "F - test-get-with-no-output: exit status")
    10591     # don't restore from ebp
    10592     81 0/subop/add %esp 8/imm32
    10593     # . epilogue
    10594     5d/pop-to-ebp
    10595     c3/return
    10596
    10597 test-get-with-too-many-outputs:
    10598     # . prologue
    10599     55/push-ebp
    10600     89/<- %ebp 4/r32/esp
    10601     # setup
    10602     (clear-stream _test-input-stream)
    10603     (clear-stream $_test-input-buffered-file->buffer)
    10604     (clear-stream _test-output-stream)
    10605     (clear-stream $_test-output-buffered-file->buffer)
    10606     (clear-stream _test-error-stream)
    10607     (clear-stream $_test-error-buffered-file->buffer)
    10608     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    10609     68/push 0/imm32
    10610     68/push 0/imm32
    10611     89/<- %edx 4/r32/esp
    10612     (tailor-exit-descriptor %edx 0x10)
    10613     #
    10614     (write _test-input-stream "fn foo {\n")
    10615     (write _test-input-stream "  var a: t\n")
    10616     (write _test-input-stream "  var b: int\n")
    10617     (write _test-input-stream "  var c/eax: (addr int) <- copy 0\n")
    10618     (write _test-input-stream "  c, b <- get a, x\n")
    10619     (write _test-input-stream "}\n")
    10620     (write _test-input-stream "type t {\n")
    10621     (write _test-input-stream "  x: int\n")
    10622     (write _test-input-stream "}\n")
    10623     # convert
    10624     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    10625     # registers except esp clobbered at this point
    10626     # restore ed
    10627     89/<- %edx 4/r32/esp
    10628     (flush _test-output-buffered-file)
    10629     (flush _test-error-buffered-file)
    10630 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    10636     # check output
    10637     (check-stream-equal _test-output-stream  ""  "F - test-get-with-too-many-outputs: output should be empty")
    10638     (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")
    10639     # check that stop(1) was called
    10640     (check-ints-equal *(edx+4) 2 "F - test-get-with-too-many-outputs: exit status")
    10641     # don't restore from ebp
    10642     81 0/subop/add %esp 8/imm32
    10643     # . epilogue
    10644     5d/pop-to-ebp
    10645     c3/return
    10646
    10647 test-convert-array-of-user-defined-types:
    10648     # . prologue
    10649     55/push-ebp
    10650     89/<- %ebp 4/r32/esp
    10651     # setup
    10652     (clear-stream _test-input-stream)
    10653     (clear-stream $_test-input-buffered-file->buffer)
    10654     (clear-stream _test-output-stream)
    10655     (clear-stream $_test-output-buffered-file->buffer)
    10656     #
    10657     (write _test-input-stream "type t {\n")  # each t is 8 bytes, which is a power of 2
    10658     (write _test-input-stream "  x: int\n")
    10659     (write _test-input-stream "  y: int\n")
    10660     (write _test-input-stream "}\n")
    10661     (write _test-input-stream "fn foo {\n")
    10662     (write _test-input-stream "  var arr/eax: (addr array t) <- copy 0\n")
    10663     (write _test-input-stream "  var idx/ecx: int <- copy 3\n")
    10664     (write _test-input-stream "  var x/eax: (addr t) <- index arr, idx\n")
    10665     (write _test-input-stream "}\n")
    10666     # convert
    10667     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
    10668     (flush _test-output-buffered-file)
    10669 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
    10675     # check output
    10676     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-array-of-user-defined-types/0")
    10677     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-array-of-user-defined-types/1")
    10678     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-array-of-user-defined-types/2")
    10679     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-array-of-user-defined-types/3")
    10680     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-array-of-user-defined-types/4")
    10681     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-array-of-user-defined-types/5")
    10682     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-array-of-user-defined-types/6")
    10683     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-array-of-user-defined-types/7")
    10684     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-array-of-user-defined-types/8")
    10685     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"                  "F - test-convert-array-of-user-defined-types/9")
    10686     (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")
    10687     (check-next-stream-line-equal _test-output-stream "    81 7/subop/compare %eax 0/imm32"  "F - test-convert-array-of-user-defined-types/12")
    10688     (check-next-stream-line-equal _test-output-stream "    0f 84/jump-if-= __mu-abort-null-index-base-address/disp32"  "F - test-convert-array-of-user-defined-types/13")
    10689     (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/14")
    10690     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-array-of-user-defined-types/15")
    10691     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-array-of-user-defined-types/16")
    10692     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-array-of-user-defined-types/17")
    10693     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-array-of-user-defined-types/18")
    10694     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-array-of-user-defined-types/19")
    10695     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-array-of-user-defined-types/20")
    10696     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-array-of-user-defined-types/21")
    10697     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-array-of-user-defined-types/22")
    10698     # . epilogue
    10699     89/<- %esp 5/r32/ebp
    10700     5d/pop-to-ebp
    10701     c3/return
    10702
    10703 test-convert-length-of-array-of-user-defined-types-to-eax:
    10704     # . prologue
    10705     55/push-ebp
    10706     89/<- %ebp 4/r32/esp
    10707     # setup
    10708     (clear-stream _test-input-stream)
    10709     (clear-stream $_test-input-buffered-file->buffer)
    10710     (clear-stream _test-output-stream)
    10711     (clear-stream $_test-output-buffered-file->buffer)
    10712     #
    10713     (write _test-input-stream "type t {\n")  # size = 12, which is not a power of 2
    10714     (write _test-input-stream "  x: int\n")
    10715     (write _test-input-stream "  y: int\n")
    10716     (write _test-input-stream "  z: int\n")
    10717     (write _test-input-stream "}\n")
    10718     (write _test-input-stream "fn foo {\n")
    10719     (write _test-input-stream "  var arr/eax: (addr array t) <- copy 0\n")
    10720     (write _test-input-stream "  var x/eax: int <- length arr\n")
    10721     (write _test-input-stream "}\n")
    10722     # convert
    10723     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
    10724     (flush _test-output-buffered-file)
    10725 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
    10731     # check output
    10732     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array-of-user-defined-types-to-eax/0")
    10733     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array-of-user-defined-types-to-eax/1")
    10734     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array-of-user-defined-types-to-eax/2")
    10735     (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")
    10736     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array-of-user-defined-types-to-eax/4")
    10737     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array-of-user-defined-types-to-eax/5")
    10738     # var arr
    10739     (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")
    10740     (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")
    10741     # length instruction
    10742     (check-next-stream-line-equal _test-output-stream "    51/push-ecx"         "F - test-convert-length-of-array-of-user-defined-types-to-eax/8")
    10743     (check-next-stream-line-equal _test-output-stream "    52/push-edx"         "F - test-convert-length-of-array-of-user-defined-types-to-eax/9")
    10744     (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")
    10745     (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")
    10746     (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")
    10747     (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")
    10748     (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")
    10749     (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")
    10750     # reclaim arr
    10751     (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")
    10752     #
    10753     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array-of-user-defined-types-to-eax/17")
    10754     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array-of-user-defined-types-to-eax/18")
    10755     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array-of-user-defined-types-to-eax/19")
    10756     (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")
    10757     (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")
    10758     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array-of-user-defined-types-to-eax/22")
    10759     # . epilogue
    10760     89/<- %esp 5/r32/ebp
    10761     5d/pop-to-ebp
    10762     c3/return
    10763
    10764 test-convert-length-of-array-of-user-defined-types-to-ecx:
    10765     # . prologue
    10766     55/push-ebp
    10767     89/<- %ebp 4/r32/esp
    10768     # setup
    10769     (clear-stream _test-input-stream)
    10770     (clear-stream $_test-input-buffered-file->buffer)
    10771     (clear-stream _test-output-stream)
    10772     (clear-stream $_test-output-buffered-file->buffer)
    10773     #
    10774     (write _test-input-stream "type t {\n")  # size = 12, which is not a power of 2
    10775     (write _test-input-stream "  x: int\n")
    10776     (write _test-input-stream "  y: int\n")
    10777     (write _test-input-stream "  z: int\n")
    10778     (write _test-input-stream "}\n")
    10779     (write _test-input-stream "fn foo {\n")
    10780     (write _test-input-stream "  var arr/eax: (addr array t) <- copy 0\n")
    10781     (write _test-input-stream "  var x/ecx: int <- length arr\n")
    10782     (write _test-input-stream "}\n")
    10783     # convert
    10784     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
    10785     (flush _test-output-buffered-file)
    10786 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
    10792     # check output
    10793     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array-of-user-defined-types-to-ecx/0")
    10794     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array-of-user-defined-types-to-ecx/1")
    10795     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array-of-user-defined-types-to-ecx/2")
    10796     (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")
    10797     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array-of-user-defined-types-to-ecx/4")
    10798     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array-of-user-defined-types-to-ecx/5")
    10799     # var a
    10800     (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")
    10801     (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")
    10802     # var x
    10803     (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")
    10804     # length instruction
    10805     (check-next-stream-line-equal _test-output-stream "    50/push-eax"         "F - test-convert-length-of-array-of-user-defined-types-to-ecx/9")
    10806     (check-next-stream-line-equal _test-output-stream "    52/push-edx"         "F - test-convert-length-of-array-of-user-defined-types-to-ecx/10")
    10807     (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")
    10808     (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")
    10809     (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")
    10810     (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")
    10811     (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")
    10812     (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")
    10813     (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")
    10814     # reclaim x
    10815     (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")
    10816     # reclaim a
    10817     (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")
    10818     #
    10819     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array-of-user-defined-types-to-ecx/20")
    10820     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array-of-user-defined-types-to-ecx/21")
    10821     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array-of-user-defined-types-to-ecx/22")
    10822     (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")
    10823     (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")
    10824     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array-of-user-defined-types-to-ecx/25")
    10825     # . epilogue
    10826     89/<- %esp 5/r32/ebp
    10827     5d/pop-to-ebp
    10828     c3/return
    10829
    10830 test-convert-length-of-array-of-user-defined-types-to-edx:
    10831     # . prologue
    10832     55/push-ebp
    10833     89/<- %ebp 4/r32/esp
    10834     # setup
    10835     (clear-stream _test-input-stream)
    10836     (clear-stream $_test-input-buffered-file->buffer)
    10837     (clear-stream _test-output-stream)
    10838     (clear-stream $_test-output-buffered-file->buffer)
    10839     #
    10840     (write _test-input-stream "type t {\n")  # size = 12, which is not a power of 2
    10841     (write _test-input-stream "  x: int\n")
    10842     (write _test-input-stream "  y: int\n")
    10843     (write _test-input-stream "  z: int\n")
    10844     (write _test-input-stream "}\n")
    10845     (write _test-input-stream "fn foo {\n")
    10846     (write _test-input-stream "  var arr/eax: (addr array t) <- copy 0\n")
    10847     (write _test-input-stream "  var x/edx: int <- length arr\n")
    10848     (write _test-input-stream "}\n")
    10849     # convert
    10850     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
    10851     (flush _test-output-buffered-file)
    10852 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
    10858     # check output
    10859     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array-of-user-defined-types-to-edx/0")
    10860     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array-of-user-defined-types-to-edx/1")
    10861     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array-of-user-defined-types-to-edx/2")
    10862     (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")
    10863     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array-of-user-defined-types-to-edx/4")
    10864     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array-of-user-defined-types-to-edx/5")
    10865     # var a
    10866     (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")
    10867     (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")
    10868     # var x
    10869     (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")
    10870     # length instruction
    10871     (check-next-stream-line-equal _test-output-stream "    50/push-eax"         "F - test-convert-length-of-array-of-user-defined-types-to-edx/9")
    10872     (check-next-stream-line-equal _test-output-stream "    51/push-ecx"         "F - test-convert-length-of-array-of-user-defined-types-to-edx/10")
    10873     (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")
    10874     (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")
    10875     (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")
    10876     (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")
    10877     (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")
    10878     (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")
    10879     (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")
    10880     # reclaim x
    10881     (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")
    10882     # reclaim a
    10883     (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")
    10884     #
    10885     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array-of-user-defined-types-to-edx/20")
    10886     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array-of-user-defined-types-to-edx/21")
    10887     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array-of-user-defined-types-to-edx/22")
    10888     (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")
    10889     (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")
    10890     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array-of-user-defined-types-to-edx/25")
    10891     # . epilogue
    10892     89/<- %esp 5/r32/ebp
    10893     5d/pop-to-ebp
    10894     c3/return
    10895
    10896 test-convert-length-of-array-of-user-defined-types:
    10897     # . prologue
    10898     55/push-ebp
    10899     89/<- %ebp 4/r32/esp
    10900     # setup
    10901     (clear-stream _test-input-stream)
    10902     (clear-stream $_test-input-buffered-file->buffer)
    10903     (clear-stream _test-output-stream)
    10904     (clear-stream $_test-output-buffered-file->buffer)
    10905     #
    10906     (write _test-input-stream "type t {\n")  # each t is 8 bytes, which is a power of 2
    10907     (write _test-input-stream "  x: int\n")
    10908     (write _test-input-stream "  y: int\n")
    10909     (write _test-input-stream "  z: int\n")
    10910     (write _test-input-stream "}\n")
    10911     (write _test-input-stream "fn foo {\n")
    10912     (write _test-input-stream "  var arr/eax: (addr array t) <- copy 0\n")
    10913     (write _test-input-stream "  var x/ebx: int <- length arr\n")
    10914     (write _test-input-stream "}\n")
    10915     # convert
    10916     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
    10917     (flush _test-output-buffered-file)
    10918 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
    10924     # check output
    10925     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array-of-user-defined-types/0")
    10926     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array-of-user-defined-types/1")
    10927     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array-of-user-defined-types/2")
    10928     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-length-of-array-of-user-defined-types/3")
    10929     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array-of-user-defined-types/4")
    10930     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array-of-user-defined-types/5")
    10931     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-length-of-array-of-user-defined-types/6")
    10932     (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")
    10933     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ebx"  "F - test-convert-length-of-array-of-user-defined-types/8")
    10934     (check-next-stream-line-equal _test-output-stream "    50/push-eax"         "F - test-convert-length-of-array-of-user-defined-types/9")
    10935     (check-next-stream-line-equal _test-output-stream "    51/push-ecx"         "F - test-convert-length-of-array-of-user-defined-types/10")
    10936     (check-next-stream-line-equal _test-output-stream "    52/push-edx"         "F - test-convert-length-of-array-of-user-defined-types/11")
    10937     (check-next-stream-line-equal _test-output-stream "    8b/-> *eax 0x00000000/r32"  "F - test-convert-length-of-array-of-user-defined-types/12")
    10938     (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")
    10939     (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")
    10940     (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")
    10941     (check-next-stream-line-equal _test-output-stream "    89/<- %ebx 0/r32/eax"  "F - test-convert-length-of-array-of-user-defined-types/16")
    10942     (check-next-stream-line-equal _test-output-stream "    5a/pop-to-edx"       "F - test-convert-length-of-array-of-user-defined-types/17")
    10943     (check-next-stream-line-equal _test-output-stream "    59/pop-to-ecx"       "F - test-convert-length-of-array-of-user-defined-types/18")
    10944     (check-next-stream-line-equal _test-output-stream "    58/pop-to-eax"       "F - test-convert-length-of-array-of-user-defined-types/19")
    10945     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ebx"  "F - test-convert-length-of-array-of-user-defined-types/20")
    10946     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"  "F - test-convert-length-of-array-of-user-defined-types/21")
    10947     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array-of-user-defined-types/22")
    10948     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array-of-user-defined-types/23")
    10949     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array-of-user-defined-types/24")
    10950     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-length-of-array-of-user-defined-types/25")
    10951     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-length-of-array-of-user-defined-types/26")
    10952     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array-of-user-defined-types/27")
    10953     # . epilogue
    10954     89/<- %esp 5/r32/ebp
    10955     5d/pop-to-ebp
    10956     c3/return
    10957
    10958 test-index-with-non-array-atom-base-type:
    10959     # . prologue
    10960     55/push-ebp
    10961     89/<- %ebp 4/r32/esp
    10962     # setup
    10963     (clear-stream _test-input-stream)
    10964     (clear-stream $_test-input-buffered-file->buffer)
    10965     (clear-stream _test-output-stream)
    10966     (clear-stream $_test-output-buffered-file->buffer)
    10967     (clear-stream _test-error-stream)
    10968     (clear-stream $_test-error-buffered-file->buffer)
    10969     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    10970     68/push 0/imm32
    10971     68/push 0/imm32
    10972     89/<- %edx 4/r32/esp
    10973     (tailor-exit-descriptor %edx 0x10)
    10974     #
    10975     (write _test-input-stream "fn foo {\n")
    10976     (write _test-input-stream "  var a: int\n")
    10977     (write _test-input-stream "  var c/ecx: (addr int) <- index a, 0\n")
    10978     (write _test-input-stream "}\n")
    10979     # convert
    10980     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    10981     # registers except esp clobbered at this point
    10982     # restore ed
    10983     89/<- %edx 4/r32/esp
    10984     (flush _test-output-buffered-file)
    10985     (flush _test-error-buffered-file)
    10986 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    10992     # check output
    10993     (check-stream-equal _test-output-stream  ""  "F - test-index-with-non-array-atom-base-type: output should be empty")
    10994     (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")
    10995     # check that stop(1) was called
    10996     (check-ints-equal *(edx+4) 2 "F - test-index-with-non-array-atom-base-type: exit status")
    10997     # don't restore from ebp
    10998     81 0/subop/add %esp 8/imm32
    10999     # . epilogue
    11000     5d/pop-to-ebp
    11001     c3/return
    11002
    11003 test-index-with-non-array-compound-base-type:
    11004     # . prologue
    11005     55/push-ebp
    11006     89/<- %ebp 4/r32/esp
    11007     # setup
    11008     (clear-stream _test-input-stream)
    11009     (clear-stream $_test-input-buffered-file->buffer)
    11010     (clear-stream _test-output-stream)
    11011     (clear-stream $_test-output-buffered-file->buffer)
    11012     (clear-stream _test-error-stream)
    11013     (clear-stream $_test-error-buffered-file->buffer)
    11014     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    11015     68/push 0/imm32
    11016     68/push 0/imm32
    11017     89/<- %edx 4/r32/esp
    11018     (tailor-exit-descriptor %edx 0x10)
    11019     #
    11020     (write _test-input-stream "fn foo {\n")
    11021     (write _test-input-stream "  var a: (handle int)\n")
    11022     (write _test-input-stream "  var c/ecx: (addr int) <- index a, 0\n")
    11023     (write _test-input-stream "}\n")
    11024     # convert
    11025     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    11026     # registers except esp clobbered at this point
    11027     # restore ed
    11028     89/<- %edx 4/r32/esp
    11029     (flush _test-output-buffered-file)
    11030     (flush _test-error-buffered-file)
    11031 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    11037     # check output
    11038     (check-stream-equal _test-output-stream  ""  "F - test-index-with-non-array-compound-base-type: output should be empty")
    11039     (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")
    11040     # check that stop(1) was called
    11041     (check-ints-equal *(edx+4) 2 "F - test-index-with-non-array-compound-base-type: exit status")
    11042     # don't restore from ebp
    11043     81 0/subop/add %esp 8/imm32
    11044     # . epilogue
    11045     5d/pop-to-ebp
    11046     c3/return
    11047
    11048 test-index-with-non-array-compound-base-type-2:
    11049     # . prologue
    11050     55/push-ebp
    11051     89/<- %ebp 4/r32/esp
    11052     # setup
    11053     (clear-stream _test-input-stream)
    11054     (clear-stream $_test-input-buffered-file->buffer)
    11055     (clear-stream _test-output-stream)
    11056     (clear-stream $_test-output-buffered-file->buffer)
    11057     (clear-stream _test-error-stream)
    11058     (clear-stream $_test-error-buffered-file->buffer)
    11059     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    11060     68/push 0/imm32
    11061     68/push 0/imm32
    11062     89/<- %edx 4/r32/esp
    11063     (tailor-exit-descriptor %edx 0x10)
    11064     #
    11065     (write _test-input-stream "fn foo {\n")
    11066     (write _test-input-stream "  var a: (addr int)\n")
    11067     (write _test-input-stream "  var c/ecx: (addr int) <- index a, 0\n")
    11068     (write _test-input-stream "}\n")
    11069     # convert
    11070     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    11071     # registers except esp clobbered at this point
    11072     # restore ed
    11073     89/<- %edx 4/r32/esp
    11074     (flush _test-output-buffered-file)
    11075     (flush _test-error-buffered-file)
    11076 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    11082     # check output
    11083     (check-stream-equal _test-output-stream  ""  "F - test-index-with-non-array-compound-base-type-2: output should be empty")
    11084     (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")
    11085     # check that stop(1) was called
    11086     (check-ints-equal *(edx+4) 2 "F - test-index-with-non-array-compound-base-type-2: exit status")
    11087     # don't restore from ebp
    11088     81 0/subop/add %esp 8/imm32
    11089     # . epilogue
    11090     5d/pop-to-ebp
    11091     c3/return
    11092
    11093 test-index-with-array-atom-base-type:
    11094     # . prologue
    11095     55/push-ebp
    11096     89/<- %ebp 4/r32/esp
    11097     # setup
    11098     (clear-stream _test-input-stream)
    11099     (clear-stream $_test-input-buffered-file->buffer)
    11100     (clear-stream _test-output-stream)
    11101     (clear-stream $_test-output-buffered-file->buffer)
    11102     (clear-stream _test-error-stream)
    11103     (clear-stream $_test-error-buffered-file->buffer)
    11104     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    11105     68/push 0/imm32
    11106     68/push 0/imm32
    11107     89/<- %edx 4/r32/esp
    11108     (tailor-exit-descriptor %edx 0x10)
    11109     #
    11110     (write _test-input-stream "fn foo {\n")
    11111     (write _test-input-stream "  var a: array\n")
    11112     (write _test-input-stream "  var c/ecx: (addr int) <- index a, 0\n")
    11113     (write _test-input-stream "}\n")
    11114     # convert
    11115     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    11116     # registers except esp clobbered at this point
    11117     # restore ed
    11118     89/<- %edx 4/r32/esp
    11119     (flush _test-output-buffered-file)
    11120     (flush _test-error-buffered-file)
    11121 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    11127     # check output
    11128     (check-stream-equal _test-output-stream  ""  "F - test-index-with-array-atom-base-type: output should be empty")
    11129     (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")
    11130     # check that stop(1) was called
    11131     (check-ints-equal *(edx+4) 2 "F - test-index-with-array-atom-base-type: exit status")
    11132     # don't restore from ebp
    11133     81 0/subop/add %esp 8/imm32
    11134     # . epilogue
    11135     5d/pop-to-ebp
    11136     c3/return
    11137
    11138 test-index-with-addr-base-on-stack:
    11139     # . prologue
    11140     55/push-ebp
    11141     89/<- %ebp 4/r32/esp
    11142     # setup
    11143     (clear-stream _test-input-stream)
    11144     (clear-stream $_test-input-buffered-file->buffer)
    11145     (clear-stream _test-output-stream)
    11146     (clear-stream $_test-output-buffered-file->buffer)
    11147     (clear-stream _test-error-stream)
    11148     (clear-stream $_test-error-buffered-file->buffer)
    11149     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    11150     68/push 0/imm32
    11151     68/push 0/imm32
    11152     89/<- %edx 4/r32/esp
    11153     (tailor-exit-descriptor %edx 0x10)
    11154     #
    11155     (write _test-input-stream "fn foo {\n")
    11156     (write _test-input-stream "  var a: (addr array int)\n")
    11157     (write _test-input-stream "  var c/ecx: (addr int) <- index a, 0\n")
    11158     (write _test-input-stream "}\n")
    11159     # convert
    11160     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    11161     # registers except esp clobbered at this point
    11162     # restore ed
    11163     89/<- %edx 4/r32/esp
    11164     (flush _test-output-buffered-file)
    11165     (flush _test-error-buffered-file)
    11166 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    11172     # check output
    11173     (check-stream-equal _test-output-stream  ""  "F - test-index-with-addr-base-on-stack: output should be empty")
    11174     (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")
    11175     # check that stop(1) was called
    11176     (check-ints-equal *(edx+4) 2 "F - test-index-with-addr-base-on-stack: exit status")
    11177     # don't restore from ebp
    11178     81 0/subop/add %esp 8/imm32
    11179     # . epilogue
    11180     5d/pop-to-ebp
    11181     c3/return
    11182
    11183 test-index-with-wrong-index-type:
    11184     # . prologue
    11185     55/push-ebp
    11186     89/<- %ebp 4/r32/esp
    11187     # setup
    11188     (clear-stream _test-input-stream)
    11189     (clear-stream $_test-input-buffered-file->buffer)
    11190     (clear-stream _test-output-stream)
    11191     (clear-stream $_test-output-buffered-file->buffer)
    11192     (clear-stream _test-error-stream)
    11193     (clear-stream $_test-error-buffered-file->buffer)
    11194     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    11195     68/push 0/imm32
    11196     68/push 0/imm32
    11197     89/<- %edx 4/r32/esp
    11198     (tailor-exit-descriptor %edx 0x10)
    11199     #
    11200     (write _test-input-stream "fn foo {\n")
    11201     (write _test-input-stream "  var a/eax: (addr array int) <- copy 0\n")
    11202     (write _test-input-stream "  var b: boolean\n")
    11203     (write _test-input-stream "  var c/ecx: (addr int) <- index a, b\n")
    11204     (write _test-input-stream "}\n")
    11205     # convert
    11206     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    11207     # registers except esp clobbered at this point
    11208     # restore ed
    11209     89/<- %edx 4/r32/esp
    11210     (flush _test-output-buffered-file)
    11211     (flush _test-error-buffered-file)
    11212 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    11218     # check output
    11219     (check-stream-equal _test-output-stream  ""  "F - test-index-with-wrong-index-type: output should be empty")
    11220     (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")
    11221     # check that stop(1) was called
    11222     (check-ints-equal *(edx+4) 2 "F - test-index-with-wrong-index-type: exit status")
    11223     # don't restore from ebp
    11224     81 0/subop/add %esp 8/imm32
    11225     # . epilogue
    11226     5d/pop-to-ebp
    11227     c3/return
    11228
    11229 test-index-with-offset-atom-index-type:
    11230     # . prologue
    11231     55/push-ebp
    11232     89/<- %ebp 4/r32/esp
    11233     # setup
    11234     (clear-stream _test-input-stream)
    11235     (clear-stream $_test-input-buffered-file->buffer)
    11236     (clear-stream _test-output-stream)
    11237     (clear-stream $_test-output-buffered-file->buffer)
    11238     (clear-stream _test-error-stream)
    11239     (clear-stream $_test-error-buffered-file->buffer)
    11240     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    11241     68/push 0/imm32
    11242     68/push 0/imm32
    11243     89/<- %edx 4/r32/esp
    11244     (tailor-exit-descriptor %edx 0x10)
    11245     #
    11246     (write _test-input-stream "fn foo {\n")
    11247     (write _test-input-stream "  var a/eax: (addr array int) <- copy 0\n")
    11248     (write _test-input-stream "  var b: offset\n")
    11249     (write _test-input-stream "  var c/ecx: (addr int) <- index a, b\n")
    11250     (write _test-input-stream "}\n")
    11251     # convert
    11252     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    11253     # registers except esp clobbered at this point
    11254     # restore ed
    11255     89/<- %edx 4/r32/esp
    11256     (flush _test-output-buffered-file)
    11257     (flush _test-error-buffered-file)
    11258 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    11264     # check output
    11265     (check-stream-equal _test-output-stream  ""  "F - test-index-with-offset-atom-index-type: output should be empty")
    11266     (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")
    11267     # check that stop(1) was called
    11268     (check-ints-equal *(edx+4) 2 "F - test-index-with-offset-atom-index-type: exit status")
    11269     # don't restore from ebp
    11270     81 0/subop/add %esp 8/imm32
    11271     # . epilogue
    11272     5d/pop-to-ebp
    11273     c3/return
    11274
    11275 test-index-with-offset-on-stack:
    11276     # . prologue
    11277     55/push-ebp
    11278     89/<- %ebp 4/r32/esp
    11279     # setup
    11280     (clear-stream _test-input-stream)
    11281     (clear-stream $_test-input-buffered-file->buffer)
    11282     (clear-stream _test-output-stream)
    11283     (clear-stream $_test-output-buffered-file->buffer)
    11284     (clear-stream _test-error-stream)
    11285     (clear-stream $_test-error-buffered-file->buffer)
    11286     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    11287     68/push 0/imm32
    11288     68/push 0/imm32
    11289     89/<- %edx 4/r32/esp
    11290     (tailor-exit-descriptor %edx 0x10)
    11291     #
    11292     (write _test-input-stream "fn foo {\n")
    11293     (write _test-input-stream "  var a/eax: (addr array int) <- copy 0\n")
    11294     (write _test-input-stream "  var b: int\n")
    11295     (write _test-input-stream "  var c/ecx: (addr int) <- index a, b\n")
    11296     (write _test-input-stream "}\n")
    11297     # convert
    11298     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    11299     # registers except esp clobbered at this point
    11300     # restore ed
    11301     89/<- %edx 4/r32/esp
    11302     (flush _test-output-buffered-file)
    11303     (flush _test-error-buffered-file)
    11304 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    11310     # check output
    11311     (check-stream-equal _test-output-stream  ""  "F - test-index-with-offset-on-stack: output should be empty")
    11312     (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")
    11313     # check that stop(1) was called
    11314     (check-ints-equal *(edx+4) 2 "F - test-index-with-offset-on-stack: exit status")
    11315     # don't restore from ebp
    11316     81 0/subop/add %esp 8/imm32
    11317     # . epilogue
    11318     5d/pop-to-ebp
    11319     c3/return
    11320
    11321 test-index-needs-offset-type:
    11322     # . prologue
    11323     55/push-ebp
    11324     89/<- %ebp 4/r32/esp
    11325     # setup
    11326     (clear-stream _test-input-stream)
    11327     (clear-stream $_test-input-buffered-file->buffer)
    11328     (clear-stream _test-output-stream)
    11329     (clear-stream $_test-output-buffered-file->buffer)
    11330     (clear-stream _test-error-stream)
    11331     (clear-stream $_test-error-buffered-file->buffer)
    11332     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    11333     68/push 0/imm32
    11334     68/push 0/imm32
    11335     89/<- %edx 4/r32/esp
    11336     (tailor-exit-descriptor %edx 0x10)
    11337     #
    11338     (write _test-input-stream "fn foo {\n")
    11339     (write _test-input-stream "  var a/eax: (addr array t) <- copy 0\n")
    11340     (write _test-input-stream "  var b/ebx: int <- copy 0\n")
    11341     (write _test-input-stream "  var c/ecx: (addr int) <- index a, b\n")
    11342     (write _test-input-stream "}\n")
    11343     (write _test-input-stream "type t {\n")  # size 12 is not a power of two
    11344     (write _test-input-stream "  x: int\n")
    11345     (write _test-input-stream "  y: int\n")
    11346     (write _test-input-stream "  z: int\n")
    11347     (write _test-input-stream "}\n")
    11348     # convert
    11349     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    11350     # registers except esp clobbered at this point
    11351     # restore ed
    11352     89/<- %edx 4/r32/esp
    11353     (flush _test-output-buffered-file)
    11354     (flush _test-error-buffered-file)
    11355 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    11361     # check output
    11362     (check-stream-equal _test-output-stream  ""  "F - test-index-needs-offset-type: output should be empty")
    11363     (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")
    11364     # check that stop(1) was called
    11365     (check-ints-equal *(edx+4) 2 "F - test-index-needs-offset-type: exit status")
    11366     # don't restore from ebp
    11367     81 0/subop/add %esp 8/imm32
    11368     # . epilogue
    11369     5d/pop-to-ebp
    11370     c3/return
    11371
    11372 test-index-with-output-not-address:
    11373     # . prologue
    11374     55/push-ebp
    11375     89/<- %ebp 4/r32/esp
    11376     # setup
    11377     (clear-stream _test-input-stream)
    11378     (clear-stream $_test-input-buffered-file->buffer)
    11379     (clear-stream _test-output-stream)
    11380     (clear-stream $_test-output-buffered-file->buffer)
    11381     (clear-stream _test-error-stream)
    11382     (clear-stream $_test-error-buffered-file->buffer)
    11383     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    11384     68/push 0/imm32
    11385     68/push 0/imm32
    11386     89/<- %edx 4/r32/esp
    11387     (tailor-exit-descriptor %edx 0x10)
    11388     #
    11389     (write _test-input-stream "fn foo {\n")
    11390     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
    11391     (write _test-input-stream "  var o/edi: int <- index a, 0\n")
    11392     (write _test-input-stream "}\n")
    11393     # convert
    11394     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    11395     # registers except esp clobbered at this point
    11396     # restore ed
    11397     89/<- %edx 4/r32/esp
    11398     (flush _test-output-buffered-file)
    11399     (flush _test-error-buffered-file)
    11400 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    11406     # check output
    11407     (check-stream-equal _test-output-stream  ""  "F - test-index-with-output-not-address: output should be empty")
    11408     (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")
    11409     # check that stop(1) was called
    11410     (check-ints-equal *(edx+4) 2 "F - test-index-with-output-not-address: exit status")
    11411     # don't restore from ebp
    11412     81 0/subop/add %esp 8/imm32
    11413     # . epilogue
    11414     5d/pop-to-ebp
    11415     c3/return
    11416
    11417 test-index-with-output-not-address-2:
    11418     # . prologue
    11419     55/push-ebp
    11420     89/<- %ebp 4/r32/esp
    11421     # setup
    11422     (clear-stream _test-input-stream)
    11423     (clear-stream $_test-input-buffered-file->buffer)
    11424     (clear-stream _test-output-stream)
    11425     (clear-stream $_test-output-buffered-file->buffer)
    11426     (clear-stream _test-error-stream)
    11427     (clear-stream $_test-error-buffered-file->buffer)
    11428     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    11429     68/push 0/imm32
    11430     68/push 0/imm32
    11431     89/<- %edx 4/r32/esp
    11432     (tailor-exit-descriptor %edx 0x10)
    11433     #
    11434     (write _test-input-stream "fn foo {\n")
    11435     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
    11436     (write _test-input-stream "  var o/edi: (int) <- index a, 0\n")
    11437     (write _test-input-stream "}\n")
    11438     # convert
    11439     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    11440     # registers except esp clobbered at this point
    11441     # restore ed
    11442     89/<- %edx 4/r32/esp
    11443     (flush _test-output-buffered-file)
    11444     (flush _test-error-buffered-file)
    11445 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    11451     # check output
    11452     (check-stream-equal _test-output-stream  ""  "F - test-index-with-output-not-address-2: output should be empty")
    11453     (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")
    11454     # check that stop(1) was called
    11455     (check-ints-equal *(edx+4) 2 "F - test-index-with-output-not-address-2: exit status")
    11456     # don't restore from ebp
    11457     81 0/subop/add %esp 8/imm32
    11458     # . epilogue
    11459     5d/pop-to-ebp
    11460     c3/return
    11461
    11462 test-index-with-wrong-output-type:
    11463     # . prologue
    11464     55/push-ebp
    11465     89/<- %ebp 4/r32/esp
    11466     # setup
    11467     (clear-stream _test-input-stream)
    11468     (clear-stream $_test-input-buffered-file->buffer)
    11469     (clear-stream _test-output-stream)
    11470     (clear-stream $_test-output-buffered-file->buffer)
    11471     (clear-stream _test-error-stream)
    11472     (clear-stream $_test-error-buffered-file->buffer)
    11473     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    11474     68/push 0/imm32
    11475     68/push 0/imm32
    11476     89/<- %edx 4/r32/esp
    11477     (tailor-exit-descriptor %edx 0x10)
    11478     #
    11479     (write _test-input-stream "fn foo {\n")
    11480     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
    11481     (write _test-input-stream "  var o/edi: (addr int) <- index a, 0\n")
    11482     (write _test-input-stream "}\n")
    11483     # convert
    11484     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    11485     # registers except esp clobbered at this point
    11486     # restore ed
    11487     89/<- %edx 4/r32/esp
    11488     (flush _test-output-buffered-file)
    11489     (flush _test-error-buffered-file)
    11490 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    11496     # check output
    11497     (check-stream-equal _test-output-stream  ""  "F - test-index-with-wrong-output-type: output should be empty")
    11498     (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")
    11499     # check that stop(1) was called
    11500     (check-ints-equal *(edx+4) 2 "F - test-index-with-wrong-output-type: exit status")
    11501     # don't restore from ebp
    11502     81 0/subop/add %esp 8/imm32
    11503     # . epilogue
    11504     5d/pop-to-ebp
    11505     c3/return
    11506
    11507 test-index-with-wrong-output-compound-type:
    11508     # . prologue
    11509     55/push-ebp
    11510     89/<- %ebp 4/r32/esp
    11511     # setup
    11512     (clear-stream _test-input-stream)
    11513     (clear-stream $_test-input-buffered-file->buffer)
    11514     (clear-stream _test-output-stream)
    11515     (clear-stream $_test-output-buffered-file->buffer)
    11516     (clear-stream _test-error-stream)
    11517     (clear-stream $_test-error-buffered-file->buffer)
    11518     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    11519     68/push 0/imm32
    11520     68/push 0/imm32
    11521     89/<- %edx 4/r32/esp
    11522     (tailor-exit-descriptor %edx 0x10)
    11523     #
    11524     (write _test-input-stream "fn foo {\n")
    11525     (write _test-input-stream "  var a/ebx: (addr array handle boolean) <- copy 0\n")
    11526     (write _test-input-stream "  var o/edi: (addr handle int) <- index a, 0\n")
    11527     (write _test-input-stream "}\n")
    11528     # convert
    11529     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    11530     # registers except esp clobbered at this point
    11531     # restore ed
    11532     89/<- %edx 4/r32/esp
    11533     (flush _test-output-buffered-file)
    11534     (flush _test-error-buffered-file)
    11535 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    11541     # check output
    11542     (check-stream-equal _test-output-stream  ""  "F - test-index-with-wrong-output-compound-type: output should be empty")
    11543     (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")
    11544     # check that stop(1) was called
    11545     (check-ints-equal *(edx+4) 2 "F - test-index-with-wrong-output-compound-type: exit status")
    11546     # don't restore from ebp
    11547     81 0/subop/add %esp 8/imm32
    11548     # . epilogue
    11549     5d/pop-to-ebp
    11550     c3/return
    11551
    11552 test-index-with-no-inouts:
    11553     # . prologue
    11554     55/push-ebp
    11555     89/<- %ebp 4/r32/esp
    11556     # setup
    11557     (clear-stream _test-input-stream)
    11558     (clear-stream $_test-input-buffered-file->buffer)
    11559     (clear-stream _test-output-stream)
    11560     (clear-stream $_test-output-buffered-file->buffer)
    11561     (clear-stream _test-error-stream)
    11562     (clear-stream $_test-error-buffered-file->buffer)
    11563     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    11564     68/push 0/imm32
    11565     68/push 0/imm32
    11566     89/<- %edx 4/r32/esp
    11567     (tailor-exit-descriptor %edx 0x10)
    11568     #
    11569     (write _test-input-stream "fn foo {\n")
    11570     (write _test-input-stream "  var c/ecx: (addr int) <- index\n")
    11571     (write _test-input-stream "}\n")
    11572     # convert
    11573     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    11574     # registers except esp clobbered at this point
    11575     # restore ed
    11576     89/<- %edx 4/r32/esp
    11577     (flush _test-output-buffered-file)
    11578     (flush _test-error-buffered-file)
    11579 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    11585     # check output
    11586     (check-stream-equal _test-output-stream  ""  "F - test-index-with-no-inouts: output should be empty")
    11587     (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")
    11588     # check that stop(1) was called
    11589     (check-ints-equal *(edx+4) 2 "F - test-index-with-no-inouts: exit status")
    11590     # don't restore from ebp
    11591     81 0/subop/add %esp 8/imm32
    11592     # . epilogue
    11593     5d/pop-to-ebp
    11594     c3/return
    11595
    11596 test-index-with-too-few-inouts:
    11597     # . prologue
    11598     55/push-ebp
    11599     89/<- %ebp 4/r32/esp
    11600     # setup
    11601     (clear-stream _test-input-stream)
    11602     (clear-stream $_test-input-buffered-file->buffer)
    11603     (clear-stream _test-output-stream)
    11604     (clear-stream $_test-output-buffered-file->buffer)
    11605     (clear-stream _test-error-stream)
    11606     (clear-stream $_test-error-buffered-file->buffer)
    11607     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    11608     68/push 0/imm32
    11609     68/push 0/imm32
    11610     89/<- %edx 4/r32/esp
    11611     (tailor-exit-descriptor %edx 0x10)
    11612     #
    11613     (write _test-input-stream "fn foo {\n")
    11614     (write _test-input-stream "  var a: (array int 3)\n")
    11615     (write _test-input-stream "  var c/ecx: (addr int) <- index a\n")
    11616     (write _test-input-stream "}\n")
    11617     # convert
    11618     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    11619     # registers except esp clobbered at this point
    11620     # restore ed
    11621     89/<- %edx 4/r32/esp
    11622     (flush _test-output-buffered-file)
    11623     (flush _test-error-buffered-file)
    11624 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    11630     # check output
    11631     (check-stream-equal _test-output-stream  ""  "F - test-index-with-too-few-inouts: output should be empty")
    11632     (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")
    11633     # check that stop(1) was called
    11634     (check-ints-equal *(edx+4) 2 "F - test-index-with-too-few-inouts: exit status")
    11635     # don't restore from ebp
    11636     81 0/subop/add %esp 8/imm32
    11637     # . epilogue
    11638     5d/pop-to-ebp
    11639     c3/return
    11640
    11641 test-index-with-too-many-inouts:
    11642     # . prologue
    11643     55/push-ebp
    11644     89/<- %ebp 4/r32/esp
    11645     # setup
    11646     (clear-stream _test-input-stream)
    11647     (clear-stream $_test-input-buffered-file->buffer)
    11648     (clear-stream _test-output-stream)
    11649     (clear-stream $_test-output-buffered-file->buffer)
    11650     (clear-stream _test-error-stream)
    11651     (clear-stream $_test-error-buffered-file->buffer)
    11652     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    11653     68/push 0/imm32
    11654     68/push 0/imm32
    11655     89/<- %edx 4/r32/esp
    11656     (tailor-exit-descriptor %edx 0x10)
    11657     #
    11658     (write _test-input-stream "fn foo {\n")
    11659     (write _test-input-stream "  var a: (array int 3)\n")
    11660     (write _test-input-stream "  var c/ecx: (addr int) <- index a, 0, 0\n")
    11661     (write _test-input-stream "}\n")
    11662     # convert
    11663     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    11664     # registers except esp clobbered at this point
    11665     # restore ed
    11666     89/<- %edx 4/r32/esp
    11667     (flush _test-output-buffered-file)
    11668     (flush _test-error-buffered-file)
    11669 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    11675     # check output
    11676     (check-stream-equal _test-output-stream  ""  "F - test-index-with-too-many-inouts: output should be empty")
    11677     (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")
    11678     # check that stop(1) was called
    11679     (check-ints-equal *(edx+4) 2 "F - test-index-with-too-many-inouts: exit status")
    11680     # don't restore from ebp
    11681     81 0/subop/add %esp 8/imm32
    11682     # . epilogue
    11683     5d/pop-to-ebp
    11684     c3/return
    11685
    11686 test-index-with-no-output:
    11687     # . prologue
    11688     55/push-ebp
    11689     89/<- %ebp 4/r32/esp
    11690     # setup
    11691     (clear-stream _test-input-stream)
    11692     (clear-stream $_test-input-buffered-file->buffer)
    11693     (clear-stream _test-output-stream)
    11694     (clear-stream $_test-output-buffered-file->buffer)
    11695     (clear-stream _test-error-stream)
    11696     (clear-stream $_test-error-buffered-file->buffer)
    11697     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    11698     68/push 0/imm32
    11699     68/push 0/imm32
    11700     89/<- %edx 4/r32/esp
    11701     (tailor-exit-descriptor %edx 0x10)
    11702     #
    11703     (write _test-input-stream "fn foo {\n")
    11704     (write _test-input-stream "  var a: (array int 3)\n")
    11705     (write _test-input-stream "  index a, 0\n")
    11706     (write _test-input-stream "}\n")
    11707     # convert
    11708     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    11709     # registers except esp clobbered at this point
    11710     # restore ed
    11711     89/<- %edx 4/r32/esp
    11712     (flush _test-output-buffered-file)
    11713     (flush _test-error-buffered-file)
    11714 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    11720     # check output
    11721     (check-stream-equal _test-output-stream  ""  "F - test-index-with-no-output: output should be empty")
    11722     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt index: must have an output"  "F - test-index-with-no-output: error message")
    11723     # check that stop(1) was called
    11724     (check-ints-equal *(edx+4) 2 "F - test-index-with-no-output: exit status")
    11725     # don't restore from ebp
    11726     81 0/subop/add %esp 8/imm32
    11727     # . epilogue
    11728     5d/pop-to-ebp
    11729     c3/return
    11730
    11731 test-index-with-too-many-outputs:
    11732     # . prologue
    11733     55/push-ebp
    11734     89/<- %ebp 4/r32/esp
    11735     # setup
    11736     (clear-stream _test-input-stream)
    11737     (clear-stream $_test-input-buffered-file->buffer)
    11738     (clear-stream _test-output-stream)
    11739     (clear-stream $_test-output-buffered-file->buffer)
    11740     (clear-stream _test-error-stream)
    11741     (clear-stream $_test-error-buffered-file->buffer)
    11742     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    11743     68/push 0/imm32
    11744     68/push 0/imm32
    11745     89/<- %edx 4/r32/esp
    11746     (tailor-exit-descriptor %edx 0x10)
    11747     #
    11748     (write _test-input-stream "fn foo {\n")
    11749     (write _test-input-stream "  var a: (array int 3)\n")
    11750     (write _test-input-stream "  var b/eax: (addr int) <- copy 0\n")
    11751     (write _test-input-stream "  var c/ecx: (addr int) <- copy 0\n")
    11752     (write _test-input-stream "  b, c <- index a, 0\n")
    11753     (write _test-input-stream "}\n")
    11754     # convert
    11755     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    11756     # registers except esp clobbered at this point
    11757     # restore ed
    11758     89/<- %edx 4/r32/esp
    11759     (flush _test-output-buffered-file)
    11760     (flush _test-error-buffered-file)
    11761 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    11767     # check output
    11768     (check-stream-equal _test-output-stream  ""  "F - test-index-with-too-many-outputs: output should be empty")
    11769     (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")
    11770     # check that stop(1) was called
    11771     (check-ints-equal *(edx+4) 2 "F - test-index-with-too-many-outputs: exit status")
    11772     # don't restore from ebp
    11773     81 0/subop/add %esp 8/imm32
    11774     # . epilogue
    11775     5d/pop-to-ebp
    11776     c3/return
    11777
    11778 test-compute-offset-with-non-array-atom-base-type:
    11779     # . prologue
    11780     55/push-ebp
    11781     89/<- %ebp 4/r32/esp
    11782     # setup
    11783     (clear-stream _test-input-stream)
    11784     (clear-stream $_test-input-buffered-file->buffer)
    11785     (clear-stream _test-output-stream)
    11786     (clear-stream $_test-output-buffered-file->buffer)
    11787     (clear-stream _test-error-stream)
    11788     (clear-stream $_test-error-buffered-file->buffer)
    11789     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    11790     68/push 0/imm32
    11791     68/push 0/imm32
    11792     89/<- %edx 4/r32/esp
    11793     (tailor-exit-descriptor %edx 0x10)
    11794     #
    11795     (write _test-input-stream "fn foo {\n")
    11796     (write _test-input-stream "  var a: int\n")
    11797     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a, 0\n")
    11798     (write _test-input-stream "}\n")
    11799     # convert
    11800     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    11801     # registers except esp clobbered at this point
    11802     # restore ed
    11803     89/<- %edx 4/r32/esp
    11804     (flush _test-output-buffered-file)
    11805     (flush _test-error-buffered-file)
    11806 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    11812     # check output
    11813     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-non-array-atom-base-type: output should be empty")
    11814     (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")
    11815     # check that stop(1) was called
    11816     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-non-array-atom-base-type: exit status")
    11817     # don't restore from ebp
    11818     81 0/subop/add %esp 8/imm32
    11819     # . epilogue
    11820     5d/pop-to-ebp
    11821     c3/return
    11822
    11823 test-compute-offset-with-non-array-compound-base-type:
    11824     # . prologue
    11825     55/push-ebp
    11826     89/<- %ebp 4/r32/esp
    11827     # setup
    11828     (clear-stream _test-input-stream)
    11829     (clear-stream $_test-input-buffered-file->buffer)
    11830     (clear-stream _test-output-stream)
    11831     (clear-stream $_test-output-buffered-file->buffer)
    11832     (clear-stream _test-error-stream)
    11833     (clear-stream $_test-error-buffered-file->buffer)
    11834     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    11835     68/push 0/imm32
    11836     68/push 0/imm32
    11837     89/<- %edx 4/r32/esp
    11838     (tailor-exit-descriptor %edx 0x10)
    11839     #
    11840     (write _test-input-stream "fn foo {\n")
    11841     (write _test-input-stream "  var a: (handle int)\n")
    11842     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a, 0\n")
    11843     (write _test-input-stream "}\n")
    11844     # convert
    11845     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    11846     # registers except esp clobbered at this point
    11847     # restore ed
    11848     89/<- %edx 4/r32/esp
    11849     (flush _test-output-buffered-file)
    11850     (flush _test-error-buffered-file)
    11851 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    11857     # check output
    11858     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-non-array-compound-base-type: output should be empty")
    11859     (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")
    11860     # check that stop(1) was called
    11861     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-non-array-compound-base-type: exit status")
    11862     # don't restore from ebp
    11863     81 0/subop/add %esp 8/imm32
    11864     # . epilogue
    11865     5d/pop-to-ebp
    11866     c3/return
    11867
    11868 test-compute-offset-with-non-array-compound-base-type-2:
    11869     # . prologue
    11870     55/push-ebp
    11871     89/<- %ebp 4/r32/esp
    11872     # setup
    11873     (clear-stream _test-input-stream)
    11874     (clear-stream $_test-input-buffered-file->buffer)
    11875     (clear-stream _test-output-stream)
    11876     (clear-stream $_test-output-buffered-file->buffer)
    11877     (clear-stream _test-error-stream)
    11878     (clear-stream $_test-error-buffered-file->buffer)
    11879     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    11880     68/push 0/imm32
    11881     68/push 0/imm32
    11882     89/<- %edx 4/r32/esp
    11883     (tailor-exit-descriptor %edx 0x10)
    11884     #
    11885     (write _test-input-stream "fn foo {\n")
    11886     (write _test-input-stream "  var a: (addr int)\n")
    11887     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a, 0\n")
    11888     (write _test-input-stream "}\n")
    11889     # convert
    11890     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    11891     # registers except esp clobbered at this point
    11892     # restore ed
    11893     89/<- %edx 4/r32/esp
    11894     (flush _test-output-buffered-file)
    11895     (flush _test-error-buffered-file)
    11896 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    11902     # check output
    11903     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-non-array-compound-base-type-2: output should be empty")
    11904     (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")
    11905     # check that stop(1) was called
    11906     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-non-array-compound-base-type-2: exit status")
    11907     # don't restore from ebp
    11908     81 0/subop/add %esp 8/imm32
    11909     # . epilogue
    11910     5d/pop-to-ebp
    11911     c3/return
    11912
    11913 test-compute-offset-with-array-atom-base-type:
    11914     # . prologue
    11915     55/push-ebp
    11916     89/<- %ebp 4/r32/esp
    11917     # setup
    11918     (clear-stream _test-input-stream)
    11919     (clear-stream $_test-input-buffered-file->buffer)
    11920     (clear-stream _test-output-stream)
    11921     (clear-stream $_test-output-buffered-file->buffer)
    11922     (clear-stream _test-error-stream)
    11923     (clear-stream $_test-error-buffered-file->buffer)
    11924     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    11925     68/push 0/imm32
    11926     68/push 0/imm32
    11927     89/<- %edx 4/r32/esp
    11928     (tailor-exit-descriptor %edx 0x10)
    11929     #
    11930     (write _test-input-stream "fn foo {\n")
    11931     (write _test-input-stream "  var a: array\n")
    11932     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a, 0\n")
    11933     (write _test-input-stream "}\n")
    11934     # convert
    11935     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    11936     # registers except esp clobbered at this point
    11937     # restore ed
    11938     89/<- %edx 4/r32/esp
    11939     (flush _test-output-buffered-file)
    11940     (flush _test-error-buffered-file)
    11941 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    11947     # check output
    11948     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-array-atom-base-type: output should be empty")
    11949     (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")
    11950     # check that stop(1) was called
    11951     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-array-atom-base-type: exit status")
    11952     # don't restore from ebp
    11953     81 0/subop/add %esp 8/imm32
    11954     # . epilogue
    11955     5d/pop-to-ebp
    11956     c3/return
    11957
    11958 test-compute-offset-with-wrong-index-type:
    11959     # . prologue
    11960     55/push-ebp
    11961     89/<- %ebp 4/r32/esp
    11962     # setup
    11963     (clear-stream _test-input-stream)
    11964     (clear-stream $_test-input-buffered-file->buffer)
    11965     (clear-stream _test-output-stream)
    11966     (clear-stream $_test-output-buffered-file->buffer)
    11967     (clear-stream _test-error-stream)
    11968     (clear-stream $_test-error-buffered-file->buffer)
    11969     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    11970     68/push 0/imm32
    11971     68/push 0/imm32
    11972     89/<- %edx 4/r32/esp
    11973     (tailor-exit-descriptor %edx 0x10)
    11974     #
    11975     (write _test-input-stream "fn foo {\n")
    11976     (write _test-input-stream "  var a/eax: (addr array int) <- copy 0\n")
    11977     (write _test-input-stream "  var b: boolean\n")
    11978     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a, b\n")
    11979     (write _test-input-stream "}\n")
    11980     # convert
    11981     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    11982     # registers except esp clobbered at this point
    11983     # restore ed
    11984     89/<- %edx 4/r32/esp
    11985     (flush _test-output-buffered-file)
    11986     (flush _test-error-buffered-file)
    11987 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    11993     # check output
    11994     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-wrong-index-type: output should be empty")
    11995     (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")
    11996     # check that stop(1) was called
    11997     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-wrong-index-type: exit status")
    11998     # don't restore from ebp
    11999     81 0/subop/add %esp 8/imm32
    12000     # . epilogue
    12001     5d/pop-to-ebp
    12002     c3/return
    12003
    12004 test-compute-offset-with-output-not-offset:
    12005     # . prologue
    12006     55/push-ebp
    12007     89/<- %ebp 4/r32/esp
    12008     # setup
    12009     (clear-stream _test-input-stream)
    12010     (clear-stream $_test-input-buffered-file->buffer)
    12011     (clear-stream _test-output-stream)
    12012     (clear-stream $_test-output-buffered-file->buffer)
    12013     (clear-stream _test-error-stream)
    12014     (clear-stream $_test-error-buffered-file->buffer)
    12015     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    12016     68/push 0/imm32
    12017     68/push 0/imm32
    12018     89/<- %edx 4/r32/esp
    12019     (tailor-exit-descriptor %edx 0x10)
    12020     #
    12021     (write _test-input-stream "fn foo {\n")
    12022     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
    12023     (write _test-input-stream "  var o/edi: int <- compute-offset a, 0\n")
    12024     (write _test-input-stream "}\n")
    12025     # convert
    12026     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    12027     # registers except esp clobbered at this point
    12028     # restore ed
    12029     89/<- %edx 4/r32/esp
    12030     (flush _test-output-buffered-file)
    12031     (flush _test-error-buffered-file)
    12032 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    12038     # check output
    12039     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-output-not-offset: output should be empty")
    12040     (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")
    12041     # check that stop(1) was called
    12042     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-output-not-offset: exit status")
    12043     # don't restore from ebp
    12044     81 0/subop/add %esp 8/imm32
    12045     # . epilogue
    12046     5d/pop-to-ebp
    12047     c3/return
    12048
    12049 test-compute-offset-with-output-not-address-2:
    12050     # . prologue
    12051     55/push-ebp
    12052     89/<- %ebp 4/r32/esp
    12053     # setup
    12054     (clear-stream _test-input-stream)
    12055     (clear-stream $_test-input-buffered-file->buffer)
    12056     (clear-stream _test-output-stream)
    12057     (clear-stream $_test-output-buffered-file->buffer)
    12058     (clear-stream _test-error-stream)
    12059     (clear-stream $_test-error-buffered-file->buffer)
    12060     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    12061     68/push 0/imm32
    12062     68/push 0/imm32
    12063     89/<- %edx 4/r32/esp
    12064     (tailor-exit-descriptor %edx 0x10)
    12065     #
    12066     (write _test-input-stream "fn foo {\n")
    12067     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
    12068     (write _test-input-stream "  var o/edi: (int) <- compute-offset a, 0\n")
    12069     (write _test-input-stream "}\n")
    12070     # convert
    12071     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    12072     # registers except esp clobbered at this point
    12073     # restore ed
    12074     89/<- %edx 4/r32/esp
    12075     (flush _test-output-buffered-file)
    12076     (flush _test-error-buffered-file)
    12077 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    12083     # check output
    12084     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-output-not-address-2: output should be empty")
    12085     (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")
    12086     # check that stop(1) was called
    12087     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-output-not-address-2: exit status")
    12088     # don't restore from ebp
    12089     81 0/subop/add %esp 8/imm32
    12090     # . epilogue
    12091     5d/pop-to-ebp
    12092     c3/return
    12093
    12094 test-compute-offset-with-wrong-output-type:
    12095     # . prologue
    12096     55/push-ebp
    12097     89/<- %ebp 4/r32/esp
    12098     # setup
    12099     (clear-stream _test-input-stream)
    12100     (clear-stream $_test-input-buffered-file->buffer)
    12101     (clear-stream _test-output-stream)
    12102     (clear-stream $_test-output-buffered-file->buffer)
    12103     (clear-stream _test-error-stream)
    12104     (clear-stream $_test-error-buffered-file->buffer)
    12105     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    12106     68/push 0/imm32
    12107     68/push 0/imm32
    12108     89/<- %edx 4/r32/esp
    12109     (tailor-exit-descriptor %edx 0x10)
    12110     #
    12111     (write _test-input-stream "fn foo {\n")
    12112     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
    12113     (write _test-input-stream "  var o/edi: (offset int) <- compute-offset a, 0\n")
    12114     (write _test-input-stream "}\n")
    12115     # convert
    12116     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    12117     # registers except esp clobbered at this point
    12118     # restore ed
    12119     89/<- %edx 4/r32/esp
    12120     (flush _test-output-buffered-file)
    12121     (flush _test-error-buffered-file)
    12122 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    12128     # check output
    12129     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-wrong-output-type: output should be empty")
    12130     (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")
    12131     # check that stop(1) was called
    12132     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-wrong-output-type: exit status")
    12133     # don't restore from ebp
    12134     81 0/subop/add %esp 8/imm32
    12135     # . epilogue
    12136     5d/pop-to-ebp
    12137     c3/return
    12138
    12139 test-compute-offset-with-wrong-output-compound-type:
    12140     # . prologue
    12141     55/push-ebp
    12142     89/<- %ebp 4/r32/esp
    12143     # setup
    12144     (clear-stream _test-input-stream)
    12145     (clear-stream $_test-input-buffered-file->buffer)
    12146     (clear-stream _test-output-stream)
    12147     (clear-stream $_test-output-buffered-file->buffer)
    12148     (clear-stream _test-error-stream)
    12149     (clear-stream $_test-error-buffered-file->buffer)
    12150     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    12151     68/push 0/imm32
    12152     68/push 0/imm32
    12153     89/<- %edx 4/r32/esp
    12154     (tailor-exit-descriptor %edx 0x10)
    12155     #
    12156     (write _test-input-stream "fn foo {\n")
    12157     (write _test-input-stream "  var a/ebx: (addr array handle boolean) <- copy 0\n")
    12158     (write _test-input-stream "  var o/edi: (offset handle int) <- compute-offset a, 0\n")
    12159     (write _test-input-stream "}\n")
    12160     # convert
    12161     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    12162     # registers except esp clobbered at this point
    12163     # restore ed
    12164     89/<- %edx 4/r32/esp
    12165     (flush _test-output-buffered-file)
    12166     (flush _test-error-buffered-file)
    12167 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    12173     # check output
    12174     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-wrong-output-compound-type: output should be empty")
    12175     (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")
    12176     # check that stop(1) was called
    12177     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-wrong-output-compound-type: exit status")
    12178     # don't restore from ebp
    12179     81 0/subop/add %esp 8/imm32
    12180     # . epilogue
    12181     5d/pop-to-ebp
    12182     c3/return
    12183
    12184 test-compute-offset-with-no-inouts:
    12185     # . prologue
    12186     55/push-ebp
    12187     89/<- %ebp 4/r32/esp
    12188     # setup
    12189     (clear-stream _test-input-stream)
    12190     (clear-stream $_test-input-buffered-file->buffer)
    12191     (clear-stream _test-output-stream)
    12192     (clear-stream $_test-output-buffered-file->buffer)
    12193     (clear-stream _test-error-stream)
    12194     (clear-stream $_test-error-buffered-file->buffer)
    12195     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    12196     68/push 0/imm32
    12197     68/push 0/imm32
    12198     89/<- %edx 4/r32/esp
    12199     (tailor-exit-descriptor %edx 0x10)
    12200     #
    12201     (write _test-input-stream "fn foo {\n")
    12202     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset\n")
    12203     (write _test-input-stream "}\n")
    12204     # convert
    12205     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    12206     # registers except esp clobbered at this point
    12207     # restore ed
    12208     89/<- %edx 4/r32/esp
    12209     (flush _test-output-buffered-file)
    12210     (flush _test-error-buffered-file)
    12211 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    12217     # check output
    12218     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-no-inouts: output should be empty")
    12219     (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")
    12220     # check that stop(1) was called
    12221     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-no-inouts: exit status")
    12222     # don't restore from ebp
    12223     81 0/subop/add %esp 8/imm32
    12224     # . epilogue
    12225     5d/pop-to-ebp
    12226     c3/return
    12227
    12228 test-compute-offset-with-too-few-inouts:
    12229     # . prologue
    12230     55/push-ebp
    12231     89/<- %ebp 4/r32/esp
    12232     # setup
    12233     (clear-stream _test-input-stream)
    12234     (clear-stream $_test-input-buffered-file->buffer)
    12235     (clear-stream _test-output-stream)
    12236     (clear-stream $_test-output-buffered-file->buffer)
    12237     (clear-stream _test-error-stream)
    12238     (clear-stream $_test-error-buffered-file->buffer)
    12239     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    12240     68/push 0/imm32
    12241     68/push 0/imm32
    12242     89/<- %edx 4/r32/esp
    12243     (tailor-exit-descriptor %edx 0x10)
    12244     #
    12245     (write _test-input-stream "fn foo {\n")
    12246     (write _test-input-stream "  var a: (array int 3)\n")
    12247     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a\n")
    12248     (write _test-input-stream "}\n")
    12249     # convert
    12250     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    12251     # registers except esp clobbered at this point
    12252     # restore ed
    12253     89/<- %edx 4/r32/esp
    12254     (flush _test-output-buffered-file)
    12255     (flush _test-error-buffered-file)
    12256 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    12262     # check output
    12263     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-too-few-inouts: output should be empty")
    12264     (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")
    12265     # check that stop(1) was called
    12266     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-too-few-inouts: exit status")
    12267     # don't restore from ebp
    12268     81 0/subop/add %esp 8/imm32
    12269     # . epilogue
    12270     5d/pop-to-ebp
    12271     c3/return
    12272
    12273 test-compute-offset-with-too-many-inouts:
    12274     # . prologue
    12275     55/push-ebp
    12276     89/<- %ebp 4/r32/esp
    12277     # setup
    12278     (clear-stream _test-input-stream)
    12279     (clear-stream $_test-input-buffered-file->buffer)
    12280     (clear-stream _test-output-stream)
    12281     (clear-stream $_test-output-buffered-file->buffer)
    12282     (clear-stream _test-error-stream)
    12283     (clear-stream $_test-error-buffered-file->buffer)
    12284     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    12285     68/push 0/imm32
    12286     68/push 0/imm32
    12287     89/<- %edx 4/r32/esp
    12288     (tailor-exit-descriptor %edx 0x10)
    12289     #
    12290     (write _test-input-stream "fn foo {\n")
    12291     (write _test-input-stream "  var a: (array int 3)\n")
    12292     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a, 0, 0\n")
    12293     (write _test-input-stream "}\n")
    12294     # convert
    12295     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    12296     # registers except esp clobbered at this point
    12297     # restore ed
    12298     89/<- %edx 4/r32/esp
    12299     (flush _test-output-buffered-file)
    12300     (flush _test-error-buffered-file)
    12301 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    12307     # check output
    12308     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-too-many-inouts: output should be empty")
    12309     (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")
    12310     # check that stop(1) was called
    12311     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-too-many-inouts: exit status")
    12312     # don't restore from ebp
    12313     81 0/subop/add %esp 8/imm32
    12314     # . epilogue
    12315     5d/pop-to-ebp
    12316     c3/return
    12317
    12318 test-compute-offset-with-no-output:
    12319     # . prologue
    12320     55/push-ebp
    12321     89/<- %ebp 4/r32/esp
    12322     # setup
    12323     (clear-stream _test-input-stream)
    12324     (clear-stream $_test-input-buffered-file->buffer)
    12325     (clear-stream _test-output-stream)
    12326     (clear-stream $_test-output-buffered-file->buffer)
    12327     (clear-stream _test-error-stream)
    12328     (clear-stream $_test-error-buffered-file->buffer)
    12329     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    12330     68/push 0/imm32
    12331     68/push 0/imm32
    12332     89/<- %edx 4/r32/esp
    12333     (tailor-exit-descriptor %edx 0x10)
    12334     #
    12335     (write _test-input-stream "fn foo {\n")
    12336     (write _test-input-stream "  var a: (array int 3)\n")
    12337     (write _test-input-stream "  compute-offset a, 0\n")
    12338     (write _test-input-stream "}\n")
    12339     # convert
    12340     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    12341     # registers except esp clobbered at this point
    12342     # restore ed
    12343     89/<- %edx 4/r32/esp
    12344     (flush _test-output-buffered-file)
    12345     (flush _test-error-buffered-file)
    12346 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    12352     # check output
    12353     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-no-output: output should be empty")
    12354     (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")
    12355     # check that stop(1) was called
    12356     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-no-output: exit status")
    12357     # don't restore from ebp
    12358     81 0/subop/add %esp 8/imm32
    12359     # . epilogue
    12360     5d/pop-to-ebp
    12361     c3/return
    12362
    12363 test-compute-offset-with-too-many-outputs:
    12364     # . prologue
    12365     55/push-ebp
    12366     89/<- %ebp 4/r32/esp
    12367     # setup
    12368     (clear-stream _test-input-stream)
    12369     (clear-stream $_test-input-buffered-file->buffer)
    12370     (clear-stream _test-output-stream)
    12371     (clear-stream $_test-output-buffered-file->buffer)
    12372     (clear-stream _test-error-stream)
    12373     (clear-stream $_test-error-buffered-file->buffer)
    12374     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    12375     68/push 0/imm32
    12376     68/push 0/imm32
    12377     89/<- %edx 4/r32/esp
    12378     (tailor-exit-descriptor %edx 0x10)
    12379     #
    12380     (write _test-input-stream "fn foo {\n")
    12381     (write _test-input-stream "  var a: (array int 3)\n")
    12382     (write _test-input-stream "  var b/eax: (offset int) <- compute-offset a, 0\n")
    12383     (write _test-input-stream "  var c/ecx: (addr int) <- copy 0\n")
    12384     (write _test-input-stream "  b, c <- compute-offset a, 0\n")
    12385     (write _test-input-stream "}\n")
    12386     # convert
    12387     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    12388     # registers except esp clobbered at this point
    12389     # restore ed
    12390     89/<- %edx 4/r32/esp
    12391     (flush _test-output-buffered-file)
    12392     (flush _test-error-buffered-file)
    12393 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    12399     # check output
    12400     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-too-many-outputs: output should be empty")
    12401     (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")
    12402     # check that stop(1) was called
    12403     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-too-many-outputs: exit status")
    12404     # don't restore from ebp
    12405     81 0/subop/add %esp 8/imm32
    12406     # . epilogue
    12407     5d/pop-to-ebp
    12408     c3/return
    12409
    12410 test-convert-read-from-stream:
    12411     # . prologue
    12412     55/push-ebp
    12413     89/<- %ebp 4/r32/esp
    12414     # setup
    12415     (clear-stream _test-input-stream)
    12416     (clear-stream $_test-input-buffered-file->buffer)
    12417     (clear-stream _test-output-stream)
    12418     (clear-stream $_test-output-buffered-file->buffer)
    12419     #
    12420     (write _test-input-stream "fn foo {\n")
    12421     (write _test-input-stream "  var s/esi: (addr stream int) <- copy 0\n")
    12422     (write _test-input-stream "  var o/ecx: (addr int) <- copy 0\n")
    12423     (write _test-input-stream "  read-from-stream s, o\n")
    12424     (write _test-input-stream "}\n")
    12425     # convert
    12426     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
    12427     # registers except esp clobbered at this point
    12428     # restore ed
    12429     89/<- %edx 4/r32/esp
    12430     (flush _test-output-buffered-file)
    12431     (flush _test-error-buffered-file)
    12432 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
    12438     # check output
    12439     (check-next-stream-line-equal _test-output-stream "foo:"                            "F - test-convert-read-from-stream/0")
    12440     (check-next-stream-line-equal _test-output-stream "  # . prologue"                  "F - test-convert-read-from-stream/1")
    12441     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                   "F - test-convert-read-from-stream/2")
    12442     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"          "F - test-convert-read-from-stream/3")
    12443     (check-next-stream-line-equal _test-output-stream "  {"                             "F - test-convert-read-from-stream/4")
    12444     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"           "F - test-convert-read-from-stream/5")
    12445     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %esi"        "F - test-convert-read-from-stream/6")
    12446     (check-next-stream-line-equal _test-output-stream "    be/copy-to-esi 0/imm32"      "F - test-convert-read-from-stream/7")
    12447     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"        "F - test-convert-read-from-stream/8")
    12448     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"      "F - test-convert-read-from-stream/9")
    12449     (check-next-stream-line-equal _test-output-stream "    (read-from-stream %esi %ecx 0x00000004)"  "F - test-convert-read-from-stream/10")
    12450     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"         "F - test-convert-read-from-stream/11")
    12451     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %esi"         "F - test-convert-read-from-stream/12")
    12452     (check-next-stream-line-equal _test-output-stream "  }"                             "F - test-convert-read-from-stream/13")
    12453     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"          "F - test-convert-read-from-stream/14")
    12454     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                  "F - test-convert-read-from-stream/15")
    12455     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"          "F - test-convert-read-from-stream/16")
    12456     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                 "F - test-convert-read-from-stream/17")
    12457     (check-next-stream-line-equal _test-output-stream "  c3/return"                     "F - test-convert-read-from-stream/18")
    12458     # . epilogue
    12459     89/<- %esp 5/r32/ebp
    12460     5d/pop-to-ebp
    12461     c3/return
    12462
    12463 test-convert-read-from-stream-with-correct-payload-size:
    12464     # . prologue
    12465     55/push-ebp
    12466     89/<- %ebp 4/r32/esp
    12467     # setup
    12468     (clear-stream _test-input-stream)
    12469     (clear-stream $_test-input-buffered-file->buffer)
    12470     (clear-stream _test-output-stream)
    12471     (clear-stream $_test-output-buffered-file->buffer)
    12472     #
    12473     (write _test-input-stream "fn foo {\n")
    12474     (write _test-input-stream "  var s/esi: (addr stream handle int) <- copy 0\n")
    12475     (write _test-input-stream "  var o/ecx: (addr handle int) <- copy 0\n")
    12476     (write _test-input-stream "  read-from-stream s, o\n")
    12477     (write _test-input-stream "}\n")
    12478     # convert
    12479     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
    12480     # registers except esp clobbered at this point
    12481     # restore ed
    12482     89/<- %edx 4/r32/esp
    12483     (flush _test-output-buffered-file)
    12484     (flush _test-error-buffered-file)
    12485 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
    12491     # check output
    12492     (check-next-stream-line-equal _test-output-stream "foo:"                            "F - test-convert-read-from-stream-with-correct-payload-size/0")
    12493     (check-next-stream-line-equal _test-output-stream "  # . prologue"                  "F - test-convert-read-from-stream-with-correct-payload-size/1")
    12494     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                   "F - test-convert-read-from-stream-with-correct-payload-size/2")
    12495     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"          "F - test-convert-read-from-stream-with-correct-payload-size/3")
    12496     (check-next-stream-line-equal _test-output-stream "  {"                             "F - test-convert-read-from-stream-with-correct-payload-size/4")
    12497     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"           "F - test-convert-read-from-stream-with-correct-payload-size/5")
    12498     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %esi"        "F - test-convert-read-from-stream-with-correct-payload-size/6")
    12499     (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")
    12500     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"        "F - test-convert-read-from-stream-with-correct-payload-size/8")
    12501     (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")
    12502     (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")
    12503     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"         "F - test-convert-read-from-stream-with-correct-payload-size/11")
    12504     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %esi"         "F - test-convert-read-from-stream-with-correct-payload-size/12")
    12505     (check-next-stream-line-equal _test-output-stream "  }"                             "F - test-convert-read-from-stream-with-correct-payload-size/13")
    12506     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"          "F - test-convert-read-from-stream-with-correct-payload-size/14")
    12507     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                  "F - test-convert-read-from-stream-with-correct-payload-size/15")
    12508     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"          "F - test-convert-read-from-stream-with-correct-payload-size/16")
    12509     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                 "F - test-convert-read-from-stream-with-correct-payload-size/17")
    12510     (check-next-stream-line-equal _test-output-stream "  c3/return"                     "F - test-convert-read-from-stream-with-correct-payload-size/18")
    12511     # . epilogue
    12512     89/<- %esp 5/r32/ebp
    12513     5d/pop-to-ebp
    12514     c3/return
    12515
    12516 test-read-from-stream-with-non-stream-atom-base-type:
    12517     # . prologue
    12518     55/push-ebp
    12519     89/<- %ebp 4/r32/esp
    12520     # setup
    12521     (clear-stream _test-input-stream)
    12522     (clear-stream $_test-input-buffered-file->buffer)
    12523     (clear-stream _test-output-stream)
    12524     (clear-stream $_test-output-buffered-file->buffer)
    12525     (clear-stream _test-error-stream)
    12526     (clear-stream $_test-error-buffered-file->buffer)
    12527     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    12528     68/push 0/imm32
    12529     68/push 0/imm32
    12530     89/<- %edx 4/r32/esp
    12531     (tailor-exit-descriptor %edx 0x10)
    12532     #
    12533     (write _test-input-stream "fn foo {\n")
    12534     (write _test-input-stream "  var a: int\n")
    12535     (write _test-input-stream "  read-from-stream a, 0\n")
    12536     (write _test-input-stream "}\n")
    12537     # convert
    12538     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    12539     # registers except esp clobbered at this point
    12540     # restore ed
    12541     89/<- %edx 4/r32/esp
    12542     (flush _test-output-buffered-file)
    12543     (flush _test-error-buffered-file)
    12544 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    12550     # check output
    12551     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-non-stream-atom-base-type: output should be empty")
    12552     (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")
    12553     # check that stop(1) was called
    12554     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-non-stream-atom-base-type: exit status")
    12555     # don't restore from ebp
    12556     81 0/subop/add %esp 8/imm32
    12557     # . epilogue
    12558     5d/pop-to-ebp
    12559     c3/return
    12560
    12561 test-read-from-stream-with-non-stream-compound-base-type:
    12562     # . prologue
    12563     55/push-ebp
    12564     89/<- %ebp 4/r32/esp
    12565     # setup
    12566     (clear-stream _test-input-stream)
    12567     (clear-stream $_test-input-buffered-file->buffer)
    12568     (clear-stream _test-output-stream)
    12569     (clear-stream $_test-output-buffered-file->buffer)
    12570     (clear-stream _test-error-stream)
    12571     (clear-stream $_test-error-buffered-file->buffer)
    12572     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    12573     68/push 0/imm32
    12574     68/push 0/imm32
    12575     89/<- %edx 4/r32/esp
    12576     (tailor-exit-descriptor %edx 0x10)
    12577     #
    12578     (write _test-input-stream "fn foo {\n")
    12579     (write _test-input-stream "  var a: (handle int)\n")
    12580     (write _test-input-stream "  read-from-stream a, 0\n")
    12581     (write _test-input-stream "}\n")
    12582     # convert
    12583     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    12584     # registers except esp clobbered at this point
    12585     # restore ed
    12586     89/<- %edx 4/r32/esp
    12587     (flush _test-output-buffered-file)
    12588     (flush _test-error-buffered-file)
    12589 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    12595     # check output
    12596     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-non-stream-compound-base-type: output should be empty")
    12597     (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")
    12598     # check that stop(1) was called
    12599     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-non-stream-compound-base-type: exit status")
    12600     # don't restore from ebp
    12601     81 0/subop/add %esp 8/imm32
    12602     # . epilogue
    12603     5d/pop-to-ebp
    12604     c3/return
    12605
    12606 test-read-from-stream-with-non-stream-compound-base-type-2:
    12607     # . prologue
    12608     55/push-ebp
    12609     89/<- %ebp 4/r32/esp
    12610     # setup
    12611     (clear-stream _test-input-stream)
    12612     (clear-stream $_test-input-buffered-file->buffer)
    12613     (clear-stream _test-output-stream)
    12614     (clear-stream $_test-output-buffered-file->buffer)
    12615     (clear-stream _test-error-stream)
    12616     (clear-stream $_test-error-buffered-file->buffer)
    12617     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    12618     68/push 0/imm32
    12619     68/push 0/imm32
    12620     89/<- %edx 4/r32/esp
    12621     (tailor-exit-descriptor %edx 0x10)
    12622     #
    12623     (write _test-input-stream "fn foo {\n")
    12624     (write _test-input-stream "  var a: (addr int)\n")
    12625     (write _test-input-stream "  read-from-stream a, 0\n")
    12626     (write _test-input-stream "}\n")
    12627     # convert
    12628     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    12629     # registers except esp clobbered at this point
    12630     # restore ed
    12631     89/<- %edx 4/r32/esp
    12632     (flush _test-output-buffered-file)
    12633     (flush _test-error-buffered-file)
    12634 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    12640     # check output
    12641     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-non-stream-compound-base-type-2: output should be empty")
    12642     (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")
    12643     # check that stop(1) was called
    12644     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-non-stream-compound-base-type-2: exit status")
    12645     # don't restore from ebp
    12646     81 0/subop/add %esp 8/imm32
    12647     # . epilogue
    12648     5d/pop-to-ebp
    12649     c3/return
    12650
    12651 test-read-from-stream-with-stream-atom-base-type:
    12652     # . prologue
    12653     55/push-ebp
    12654     89/<- %ebp 4/r32/esp
    12655     # setup
    12656     (clear-stream _test-input-stream)
    12657     (clear-stream $_test-input-buffered-file->buffer)
    12658     (clear-stream _test-output-stream)
    12659     (clear-stream $_test-output-buffered-file->buffer)
    12660     (clear-stream _test-error-stream)
    12661     (clear-stream $_test-error-buffered-file->buffer)
    12662     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    12663     68/push 0/imm32
    12664     68/push 0/imm32
    12665     89/<- %edx 4/r32/esp
    12666     (tailor-exit-descriptor %edx 0x10)
    12667     #
    12668     (write _test-input-stream "fn foo {\n")
    12669     (write _test-input-stream "  var a: stream\n")
    12670     (write _test-input-stream "  read-from-stream a, 0\n")
    12671     (write _test-input-stream "}\n")
    12672     # convert
    12673     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    12674     # registers except esp clobbered at this point
    12675     # restore ed
    12676     89/<- %edx 4/r32/esp
    12677     (flush _test-output-buffered-file)
    12678     (flush _test-error-buffered-file)
    12679 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    12685     # check output
    12686     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-stream-atom-base-type: output should be empty")
    12687     (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")
    12688     # check that stop(1) was called
    12689     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-stream-atom-base-type: exit status")
    12690     # don't restore from ebp
    12691     81 0/subop/add %esp 8/imm32
    12692     # . epilogue
    12693     5d/pop-to-ebp
    12694     c3/return
    12695
    12696 test-read-from-stream-with-wrong-index-type:
    12697     # . prologue
    12698     55/push-ebp
    12699     89/<- %ebp 4/r32/esp
    12700     # setup
    12701     (clear-stream _test-input-stream)
    12702     (clear-stream $_test-input-buffered-file->buffer)
    12703     (clear-stream _test-output-stream)
    12704     (clear-stream $_test-output-buffered-file->buffer)
    12705     (clear-stream _test-error-stream)
    12706     (clear-stream $_test-error-buffered-file->buffer)
    12707     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    12708     68/push 0/imm32
    12709     68/push 0/imm32
    12710     89/<- %edx 4/r32/esp
    12711     (tailor-exit-descriptor %edx 0x10)
    12712     #
    12713     (write _test-input-stream "fn foo {\n")
    12714     (write _test-input-stream "  var a/eax: (addr stream int) <- copy 0\n")
    12715     (write _test-input-stream "  var b: boolean\n")
    12716     (write _test-input-stream "  read-from-stream a, b\n")
    12717     (write _test-input-stream "}\n")
    12718     # convert
    12719     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    12720     # registers except esp clobbered at this point
    12721     # restore ed
    12722     89/<- %edx 4/r32/esp
    12723     (flush _test-output-buffered-file)
    12724     (flush _test-error-buffered-file)
    12725 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    12731     # check output
    12732     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-wrong-index-type: output should be empty")
    12733     (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")
    12734     # check that stop(1) was called
    12735     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-wrong-index-type: exit status")
    12736     # don't restore from ebp
    12737     81 0/subop/add %esp 8/imm32
    12738     # . epilogue
    12739     5d/pop-to-ebp
    12740     c3/return
    12741
    12742 test-read-from-stream-with-no-inouts:
    12743     # . prologue
    12744     55/push-ebp
    12745     89/<- %ebp 4/r32/esp
    12746     # setup
    12747     (clear-stream _test-input-stream)
    12748     (clear-stream $_test-input-buffered-file->buffer)
    12749     (clear-stream _test-output-stream)
    12750     (clear-stream $_test-output-buffered-file->buffer)
    12751     (clear-stream _test-error-stream)
    12752     (clear-stream $_test-error-buffered-file->buffer)
    12753     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    12754     68/push 0/imm32
    12755     68/push 0/imm32
    12756     89/<- %edx 4/r32/esp
    12757     (tailor-exit-descriptor %edx 0x10)
    12758     #
    12759     (write _test-input-stream "fn foo {\n")
    12760     (write _test-input-stream "  read-from-stream\n")
    12761     (write _test-input-stream "}\n")
    12762     # convert
    12763     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    12764     # registers except esp clobbered at this point
    12765     # restore ed
    12766     89/<- %edx 4/r32/esp
    12767     (flush _test-output-buffered-file)
    12768     (flush _test-error-buffered-file)
    12769 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    12775     # check output
    12776     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-no-inouts: output should be empty")
    12777     (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")
    12778     # check that stop(1) was called
    12779     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-no-inouts: exit status")
    12780     # don't restore from ebp
    12781     81 0/subop/add %esp 8/imm32
    12782     # . epilogue
    12783     5d/pop-to-ebp
    12784     c3/return
    12785
    12786 test-read-from-stream-with-too-few-inouts:
    12787     # . prologue
    12788     55/push-ebp
    12789     89/<- %ebp 4/r32/esp
    12790     # setup
    12791     (clear-stream _test-input-stream)
    12792     (clear-stream $_test-input-buffered-file->buffer)
    12793     (clear-stream _test-output-stream)
    12794     (clear-stream $_test-output-buffered-file->buffer)
    12795     (clear-stream _test-error-stream)
    12796     (clear-stream $_test-error-buffered-file->buffer)
    12797     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    12798     68/push 0/imm32
    12799     68/push 0/imm32
    12800     89/<- %edx 4/r32/esp
    12801     (tailor-exit-descriptor %edx 0x10)
    12802     #
    12803     (write _test-input-stream "fn foo {\n")
    12804     (write _test-input-stream "  var a: (addr stream int)\n")
    12805     (write _test-input-stream "  read-from-stream a\n")
    12806     (write _test-input-stream "}\n")
    12807     # convert
    12808     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    12809     # registers except esp clobbered at this point
    12810     # restore ed
    12811     89/<- %edx 4/r32/esp
    12812     (flush _test-output-buffered-file)
    12813     (flush _test-error-buffered-file)
    12814 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    12820     # check output
    12821     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-too-few-inouts: output should be empty")
    12822     (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")
    12823     # check that stop(1) was called
    12824     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-too-few-inouts: exit status")
    12825     # don't restore from ebp
    12826     81 0/subop/add %esp 8/imm32
    12827     # . epilogue
    12828     5d/pop-to-ebp
    12829     c3/return
    12830
    12831 test-read-from-stream-with-too-many-inouts:
    12832     # . prologue
    12833     55/push-ebp
    12834     89/<- %ebp 4/r32/esp
    12835     # setup
    12836     (clear-stream _test-input-stream)
    12837     (clear-stream $_test-input-buffered-file->buffer)
    12838     (clear-stream _test-output-stream)
    12839     (clear-stream $_test-output-buffered-file->buffer)
    12840     (clear-stream _test-error-stream)
    12841     (clear-stream $_test-error-buffered-file->buffer)
    12842     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    12843     68/push 0/imm32
    12844     68/push 0/imm32
    12845     89/<- %edx 4/r32/esp
    12846     (tailor-exit-descriptor %edx 0x10)
    12847     #
    12848     (write _test-input-stream "fn foo {\n")
    12849     (write _test-input-stream "  var a: (addr stream int)\n")
    12850     (write _test-input-stream "  var b: (addr int)\n")
    12851     (write _test-input-stream "  read-from-stream a, b, 0\n")
    12852     (write _test-input-stream "}\n")
    12853     # convert
    12854     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    12855     # registers except esp clobbered at this point
    12856     # restore ed
    12857     89/<- %edx 4/r32/esp
    12858     (flush _test-output-buffered-file)
    12859     (flush _test-error-buffered-file)
    12860 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    12866     # check output
    12867     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-too-many-inouts: output should be empty")
    12868     (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")
    12869     # check that stop(1) was called
    12870     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-too-many-inouts: exit status")
    12871     # don't restore from ebp
    12872     81 0/subop/add %esp 8/imm32
    12873     # . epilogue
    12874     5d/pop-to-ebp
    12875     c3/return
    12876
    12877 test-read-from-stream-with-output:
    12878     # . prologue
    12879     55/push-ebp
    12880     89/<- %ebp 4/r32/esp
    12881     # setup
    12882     (clear-stream _test-input-stream)
    12883     (clear-stream $_test-input-buffered-file->buffer)
    12884     (clear-stream _test-output-stream)
    12885     (clear-stream $_test-output-buffered-file->buffer)
    12886     (clear-stream _test-error-stream)
    12887     (clear-stream $_test-error-buffered-file->buffer)
    12888     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    12889     68/push 0/imm32
    12890     68/push 0/imm32
    12891     89/<- %edx 4/r32/esp
    12892     (tailor-exit-descriptor %edx 0x10)
    12893     #
    12894     (write _test-input-stream "fn foo {\n")
    12895     (write _test-input-stream "  var a: (addr stream int)\n")
    12896     (write _test-input-stream "  var b/eax: (addr int) <- copy 0\n")
    12897     (write _test-input-stream "  b <- read-from-stream a, b\n")
    12898     (write _test-input-stream "}\n")
    12899     # convert
    12900     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    12901     # registers except esp clobbered at this point
    12902     # restore ed
    12903     89/<- %edx 4/r32/esp
    12904     (flush _test-output-buffered-file)
    12905     (flush _test-error-buffered-file)
    12906 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    12912     # check output
    12913     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-output: output should be empty")
    12914     (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")
    12915     # check that stop(1) was called
    12916     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-output: exit status")
    12917     # don't restore from ebp
    12918     81 0/subop/add %esp 8/imm32
    12919     # . epilogue
    12920     5d/pop-to-ebp
    12921     c3/return
    12922
    12923 test-convert-write-to-stream:
    12924     # . prologue
    12925     55/push-ebp
    12926     89/<- %ebp 4/r32/esp
    12927     # setup
    12928     (clear-stream _test-input-stream)
    12929     (clear-stream $_test-input-buffered-file->buffer)
    12930     (clear-stream _test-output-stream)
    12931     (clear-stream $_test-output-buffered-file->buffer)
    12932     #
    12933     (write _test-input-stream "fn foo {\n")
    12934     (write _test-input-stream "  var s/esi: (addr stream int) <- copy 0\n")
    12935     (write _test-input-stream "  var o/ecx: (addr int) <- copy 0\n")
    12936     (write _test-input-stream "  write-to-stream s, o\n")
    12937     (write _test-input-stream "}\n")
    12938     # convert
    12939     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
    12940     # registers except esp clobbered at this point
    12941     # restore ed
    12942     89/<- %edx 4/r32/esp
    12943     (flush _test-output-buffered-file)
    12944     (flush _test-error-buffered-file)
    12945 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
    12951     # check output
    12952     (check-next-stream-line-equal _test-output-stream "foo:"                            "F - test-convert-write-to-stream/0")
    12953     (check-next-stream-line-equal _test-output-stream "  # . prologue"                  "F - test-convert-write-to-stream/1")
    12954     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                   "F - test-convert-write-to-stream/2")
    12955     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"          "F - test-convert-write-to-stream/3")
    12956     (check-next-stream-line-equal _test-output-stream "  {"                             "F - test-convert-write-to-stream/4")
    12957     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"           "F - test-convert-write-to-stream/5")
    12958     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %esi"        "F - test-convert-write-to-stream/6")
    12959     (check-next-stream-line-equal _test-output-stream "    be/copy-to-esi 0/imm32"      "F - test-convert-write-to-stream/7")
    12960     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"        "F - test-convert-write-to-stream/8")
    12961     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"      "F - test-convert-write-to-stream/9")
    12962     (check-next-stream-line-equal _test-output-stream "    (write-to-stream %esi %ecx 0x00000004)"  "F - test-convert-write-to-stream/10")
    12963     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"         "F - test-convert-write-to-stream/11")
    12964     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %esi"         "F - test-convert-write-to-stream/12")
    12965     (check-next-stream-line-equal _test-output-stream "  }"                             "F - test-convert-write-to-stream/13")
    12966     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"          "F - test-convert-write-to-stream/14")
    12967     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                  "F - test-convert-write-to-stream/15")
    12968     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"          "F - test-convert-write-to-stream/16")
    12969     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                 "F - test-convert-write-to-stream/17")
    12970     (check-next-stream-line-equal _test-output-stream "  c3/return"                     "F - test-convert-write-to-stream/18")
    12971     # . epilogue
    12972     89/<- %esp 5/r32/ebp
    12973     5d/pop-to-ebp
    12974     c3/return
    12975
    12976 test-convert-write-to-stream-with-correct-payload-size:
    12977     # . prologue
    12978     55/push-ebp
    12979     89/<- %ebp 4/r32/esp
    12980     # setup
    12981     (clear-stream _test-input-stream)
    12982     (clear-stream $_test-input-buffered-file->buffer)
    12983     (clear-stream _test-output-stream)
    12984     (clear-stream $_test-output-buffered-file->buffer)
    12985     #
    12986     (write _test-input-stream "fn foo {\n")
    12987     (write _test-input-stream "  var s/esi: (addr stream handle int) <- copy 0\n")
    12988     (write _test-input-stream "  var o/ecx: (addr handle int) <- copy 0\n")
    12989     (write _test-input-stream "  write-to-stream s, o\n")
    12990     (write _test-input-stream "}\n")
    12991     # convert
    12992     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
    12993     # registers except esp clobbered at this point
    12994     # restore ed
    12995     89/<- %edx 4/r32/esp
    12996     (flush _test-output-buffered-file)
    12997     (flush _test-error-buffered-file)
    12998 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
    13004     # check output
    13005     (check-next-stream-line-equal _test-output-stream "foo:"                            "F - test-convert-write-to-stream-with-correct-payload-size/0")
    13006     (check-next-stream-line-equal _test-output-stream "  # . prologue"                  "F - test-convert-write-to-stream-with-correct-payload-size/1")
    13007     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                   "F - test-convert-write-to-stream-with-correct-payload-size/2")
    13008     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"          "F - test-convert-write-to-stream-with-correct-payload-size/3")
    13009     (check-next-stream-line-equal _test-output-stream "  {"                             "F - test-convert-write-to-stream-with-correct-payload-size/4")
    13010     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"           "F - test-convert-write-to-stream-with-correct-payload-size/5")
    13011     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %esi"        "F - test-convert-write-to-stream-with-correct-payload-size/6")
    13012     (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")
    13013     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"        "F - test-convert-write-to-stream-with-correct-payload-size/8")
    13014     (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")
    13015     (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")
    13016     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"         "F - test-convert-write-to-stream-with-correct-payload-size/11")
    13017     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %esi"         "F - test-convert-write-to-stream-with-correct-payload-size/12")
    13018     (check-next-stream-line-equal _test-output-stream "  }"                             "F - test-convert-write-to-stream-with-correct-payload-size/13")
    13019     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"          "F - test-convert-write-to-stream-with-correct-payload-size/14")
    13020     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                  "F - test-convert-write-to-stream-with-correct-payload-size/15")
    13021     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"          "F - test-convert-write-to-stream-with-correct-payload-size/16")
    13022     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                 "F - test-convert-write-to-stream-with-correct-payload-size/17")
    13023     (check-next-stream-line-equal _test-output-stream "  c3/return"                     "F - test-convert-write-to-stream-with-correct-payload-size/18")
    13024     # . epilogue
    13025     89/<- %esp 5/r32/ebp
    13026     5d/pop-to-ebp
    13027     c3/return
    13028
    13029 test-write-to-stream-with-non-stream-atom-base-type:
    13030     # . prologue
    13031     55/push-ebp
    13032     89/<- %ebp 4/r32/esp
    13033     # setup
    13034     (clear-stream _test-input-stream)
    13035     (clear-stream $_test-input-buffered-file->buffer)
    13036     (clear-stream _test-output-stream)
    13037     (clear-stream $_test-output-buffered-file->buffer)
    13038     (clear-stream _test-error-stream)
    13039     (clear-stream $_test-error-buffered-file->buffer)
    13040     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    13041     68/push 0/imm32
    13042     68/push 0/imm32
    13043     89/<- %edx 4/r32/esp
    13044     (tailor-exit-descriptor %edx 0x10)
    13045     #
    13046     (write _test-input-stream "fn foo {\n")
    13047     (write _test-input-stream "  var a: int\n")
    13048     (write _test-input-stream "  write-to-stream a, 0\n")
    13049     (write _test-input-stream "}\n")
    13050     # convert
    13051     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    13052     # registers except esp clobbered at this point
    13053     # restore ed
    13054     89/<- %edx 4/r32/esp
    13055     (flush _test-output-buffered-file)
    13056     (flush _test-error-buffered-file)
    13057 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    13063     # check output
    13064     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-non-stream-atom-base-type: output should be empty")
    13065     (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")
    13066     # check that stop(1) was called
    13067     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-non-stream-atom-base-type: exit status")
    13068     # don't restore from ebp
    13069     81 0/subop/add %esp 8/imm32
    13070     # . epilogue
    13071     5d/pop-to-ebp
    13072     c3/return
    13073
    13074 test-write-to-stream-with-non-stream-compound-base-type:
    13075     # . prologue
    13076     55/push-ebp
    13077     89/<- %ebp 4/r32/esp
    13078     # setup
    13079     (clear-stream _test-input-stream)
    13080     (clear-stream $_test-input-buffered-file->buffer)
    13081     (clear-stream _test-output-stream)
    13082     (clear-stream $_test-output-buffered-file->buffer)
    13083     (clear-stream _test-error-stream)
    13084     (clear-stream $_test-error-buffered-file->buffer)
    13085     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    13086     68/push 0/imm32
    13087     68/push 0/imm32
    13088     89/<- %edx 4/r32/esp
    13089     (tailor-exit-descriptor %edx 0x10)
    13090     #
    13091     (write _test-input-stream "fn foo {\n")
    13092     (write _test-input-stream "  var a: (handle int)\n")
    13093     (write _test-input-stream "  write-to-stream a, 0\n")
    13094     (write _test-input-stream "}\n")
    13095     # convert
    13096     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    13097     # registers except esp clobbered at this point
    13098     # restore ed
    13099     89/<- %edx 4/r32/esp
    13100     (flush _test-output-buffered-file)
    13101     (flush _test-error-buffered-file)
    13102 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    13108     # check output
    13109     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-non-stream-compound-base-type: output should be empty")
    13110     (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")
    13111     # check that stop(1) was called
    13112     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-non-stream-compound-base-type: exit status")
    13113     # don't restore from ebp
    13114     81 0/subop/add %esp 8/imm32
    13115     # . epilogue
    13116     5d/pop-to-ebp
    13117     c3/return
    13118
    13119 test-write-to-stream-with-non-stream-compound-base-type-2:
    13120     # . prologue
    13121     55/push-ebp
    13122     89/<- %ebp 4/r32/esp
    13123     # setup
    13124     (clear-stream _test-input-stream)
    13125     (clear-stream $_test-input-buffered-file->buffer)
    13126     (clear-stream _test-output-stream)
    13127     (clear-stream $_test-output-buffered-file->buffer)
    13128     (clear-stream _test-error-stream)
    13129     (clear-stream $_test-error-buffered-file->buffer)
    13130     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    13131     68/push 0/imm32
    13132     68/push 0/imm32
    13133     89/<- %edx 4/r32/esp
    13134     (tailor-exit-descriptor %edx 0x10)
    13135     #
    13136     (write _test-input-stream "fn foo {\n")
    13137     (write _test-input-stream "  var a: (addr int)\n")
    13138     (write _test-input-stream "  write-to-stream a, 0\n")
    13139     (write _test-input-stream "}\n")
    13140     # convert
    13141     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    13142     # registers except esp clobbered at this point
    13143     # restore ed
    13144     89/<- %edx 4/r32/esp
    13145     (flush _test-output-buffered-file)
    13146     (flush _test-error-buffered-file)
    13147 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    13153     # check output
    13154     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-non-stream-compound-base-type-2: output should be empty")
    13155     (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")
    13156     # check that stop(1) was called
    13157     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-non-stream-compound-base-type-2: exit status")
    13158     # don't restore from ebp
    13159     81 0/subop/add %esp 8/imm32
    13160     # . epilogue
    13161     5d/pop-to-ebp
    13162     c3/return
    13163
    13164 test-write-to-stream-with-stream-atom-base-type:
    13165     # . prologue
    13166     55/push-ebp
    13167     89/<- %ebp 4/r32/esp
    13168     # setup
    13169     (clear-stream _test-input-stream)
    13170     (clear-stream $_test-input-buffered-file->buffer)
    13171     (clear-stream _test-output-stream)
    13172     (clear-stream $_test-output-buffered-file->buffer)
    13173     (clear-stream _test-error-stream)
    13174     (clear-stream $_test-error-buffered-file->buffer)
    13175     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    13176     68/push 0/imm32
    13177     68/push 0/imm32
    13178     89/<- %edx 4/r32/esp
    13179     (tailor-exit-descriptor %edx 0x10)
    13180     #
    13181     (write _test-input-stream "fn foo {\n")
    13182     (write _test-input-stream "  var a: stream\n")
    13183     (write _test-input-stream "  write-to-stream a, 0\n")
    13184     (write _test-input-stream "}\n")
    13185     # convert
    13186     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    13187     # registers except esp clobbered at this point
    13188     # restore ed
    13189     89/<- %edx 4/r32/esp
    13190     (flush _test-output-buffered-file)
    13191     (flush _test-error-buffered-file)
    13192 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    13198     # check output
    13199     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-stream-atom-base-type: output should be empty")
    13200     (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")
    13201     # check that stop(1) was called
    13202     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-stream-atom-base-type: exit status")
    13203     # don't restore from ebp
    13204     81 0/subop/add %esp 8/imm32
    13205     # . epilogue
    13206     5d/pop-to-ebp
    13207     c3/return
    13208
    13209 test-write-to-stream-with-wrong-index-type:
    13210     # . prologue
    13211     55/push-ebp
    13212     89/<- %ebp 4/r32/esp
    13213     # setup
    13214     (clear-stream _test-input-stream)
    13215     (clear-stream $_test-input-buffered-file->buffer)
    13216     (clear-stream _test-output-stream)
    13217     (clear-stream $_test-output-buffered-file->buffer)
    13218     (clear-stream _test-error-stream)
    13219     (clear-stream $_test-error-buffered-file->buffer)
    13220     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    13221     68/push 0/imm32
    13222     68/push 0/imm32
    13223     89/<- %edx 4/r32/esp
    13224     (tailor-exit-descriptor %edx 0x10)
    13225     #
    13226     (write _test-input-stream "fn foo {\n")
    13227     (write _test-input-stream "  var a/eax: (addr stream int) <- copy 0\n")
    13228     (write _test-input-stream "  var b: boolean\n")
    13229     (write _test-input-stream "  write-to-stream a, b\n")
    13230     (write _test-input-stream "}\n")
    13231     # convert
    13232     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    13233     # registers except esp clobbered at this point
    13234     # restore ed
    13235     89/<- %edx 4/r32/esp
    13236     (flush _test-output-buffered-file)
    13237     (flush _test-error-buffered-file)
    13238 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    13244     # check output
    13245     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-wrong-index-type: output should be empty")
    13246     (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")
    13247     # check that stop(1) was called
    13248     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-wrong-index-type: exit status")
    13249     # don't restore from ebp
    13250     81 0/subop/add %esp 8/imm32
    13251     # . epilogue
    13252     5d/pop-to-ebp
    13253     c3/return
    13254
    13255 test-write-to-stream-with-no-inouts:
    13256     # . prologue
    13257     55/push-ebp
    13258     89/<- %ebp 4/r32/esp
    13259     # setup
    13260     (clear-stream _test-input-stream)
    13261     (clear-stream $_test-input-buffered-file->buffer)
    13262     (clear-stream _test-output-stream)
    13263     (clear-stream $_test-output-buffered-file->buffer)
    13264     (clear-stream _test-error-stream)
    13265     (clear-stream $_test-error-buffered-file->buffer)
    13266     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    13267     68/push 0/imm32
    13268     68/push 0/imm32
    13269     89/<- %edx 4/r32/esp
    13270     (tailor-exit-descriptor %edx 0x10)
    13271     #
    13272     (write _test-input-stream "fn foo {\n")
    13273     (write _test-input-stream "  write-to-stream\n")
    13274     (write _test-input-stream "}\n")
    13275     # convert
    13276     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    13277     # registers except esp clobbered at this point
    13278     # restore ed
    13279     89/<- %edx 4/r32/esp
    13280     (flush _test-output-buffered-file)
    13281     (flush _test-error-buffered-file)
    13282 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    13288     # check output
    13289     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-no-inouts: output should be empty")
    13290     (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")
    13291     # check that stop(1) was called
    13292     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-no-inouts: exit status")
    13293     # don't restore from ebp
    13294     81 0/subop/add %esp 8/imm32
    13295     # . epilogue
    13296     5d/pop-to-ebp
    13297     c3/return
    13298
    13299 test-write-to-stream-with-too-few-inouts:
    13300     # . prologue
    13301     55/push-ebp
    13302     89/<- %ebp 4/r32/esp
    13303     # setup
    13304     (clear-stream _test-input-stream)
    13305     (clear-stream $_test-input-buffered-file->buffer)
    13306     (clear-stream _test-output-stream)
    13307     (clear-stream $_test-output-buffered-file->buffer)
    13308     (clear-stream _test-error-stream)
    13309     (clear-stream $_test-error-buffered-file->buffer)
    13310     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    13311     68/push 0/imm32
    13312     68/push 0/imm32
    13313     89/<- %edx 4/r32/esp
    13314     (tailor-exit-descriptor %edx 0x10)
    13315     #
    13316     (write _test-input-stream "fn foo {\n")
    13317     (write _test-input-stream "  var a: (addr stream int)\n")
    13318     (write _test-input-stream "  write-to-stream a\n")
    13319     (write _test-input-stream "}\n")
    13320     # convert
    13321     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    13322     # registers except esp clobbered at this point
    13323     # restore ed
    13324     89/<- %edx 4/r32/esp
    13325     (flush _test-output-buffered-file)
    13326     (flush _test-error-buffered-file)
    13327 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    13333     # check output
    13334     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-too-few-inouts: output should be empty")
    13335     (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")
    13336     # check that stop(1) was called
    13337     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-too-few-inouts: exit status")
    13338     # don't restore from ebp
    13339     81 0/subop/add %esp 8/imm32
    13340     # . epilogue
    13341     5d/pop-to-ebp
    13342     c3/return
    13343
    13344 test-write-to-stream-with-too-many-inouts:
    13345     # . prologue
    13346     55/push-ebp
    13347     89/<- %ebp 4/r32/esp
    13348     # setup
    13349     (clear-stream _test-input-stream)
    13350     (clear-stream $_test-input-buffered-file->buffer)
    13351     (clear-stream _test-output-stream)
    13352     (clear-stream $_test-output-buffered-file->buffer)
    13353     (clear-stream _test-error-stream)
    13354     (clear-stream $_test-error-buffered-file->buffer)
    13355     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    13356     68/push 0/imm32
    13357     68/push 0/imm32
    13358     89/<- %edx 4/r32/esp
    13359     (tailor-exit-descriptor %edx 0x10)
    13360     #
    13361     (write _test-input-stream "fn foo {\n")
    13362     (write _test-input-stream "  var a: (addr stream int)\n")
    13363     (write _test-input-stream "  var b: (addr int)\n")
    13364     (write _test-input-stream "  write-to-stream a, b, 0\n")
    13365     (write _test-input-stream "}\n")
    13366     # convert
    13367     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    13368     # registers except esp clobbered at this point
    13369     # restore ed
    13370     89/<- %edx 4/r32/esp
    13371     (flush _test-output-buffered-file)
    13372     (flush _test-error-buffered-file)
    13373 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    13379     # check output
    13380     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-too-many-inouts: output should be empty")
    13381     (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")
    13382     # check that stop(1) was called
    13383     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-too-many-inouts: exit status")
    13384     # don't restore from ebp
    13385     81 0/subop/add %esp 8/imm32
    13386     # . epilogue
    13387     5d/pop-to-ebp
    13388     c3/return
    13389
    13390 test-write-to-stream-with-output:
    13391     # . prologue
    13392     55/push-ebp
    13393     89/<- %ebp 4/r32/esp
    13394     # setup
    13395     (clear-stream _test-input-stream)
    13396     (clear-stream $_test-input-buffered-file->buffer)
    13397     (clear-stream _test-output-stream)
    13398     (clear-stream $_test-output-buffered-file->buffer)
    13399     (clear-stream _test-error-stream)
    13400     (clear-stream $_test-error-buffered-file->buffer)
    13401     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    13402     68/push 0/imm32
    13403     68/push 0/imm32
    13404     89/<- %edx 4/r32/esp
    13405     (tailor-exit-descriptor %edx 0x10)
    13406     #
    13407     (write _test-input-stream "fn foo {\n")
    13408     (write _test-input-stream "  var a: (addr stream int)\n")
    13409     (write _test-input-stream "  var b/eax: (addr int) <- copy 0\n")
    13410     (write _test-input-stream "  b <- write-to-stream a, b\n")
    13411     (write _test-input-stream "}\n")
    13412     # convert
    13413     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    13414     # registers except esp clobbered at this point
    13415     # restore ed
    13416     89/<- %edx 4/r32/esp
    13417     (flush _test-output-buffered-file)
    13418     (flush _test-error-buffered-file)
    13419 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    13425     # check output
    13426     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-output: output should be empty")
    13427     (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")
    13428     # check that stop(1) was called
    13429     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-output: exit status")
    13430     # don't restore from ebp
    13431     81 0/subop/add %esp 8/imm32
    13432     # . epilogue
    13433     5d/pop-to-ebp
    13434     c3/return
    13435
    13436 test-length-with-non-array-atom-base-type:
    13437     # . prologue
    13438     55/push-ebp
    13439     89/<- %ebp 4/r32/esp
    13440     # setup
    13441     (clear-stream _test-input-stream)
    13442     (clear-stream $_test-input-buffered-file->buffer)
    13443     (clear-stream _test-output-stream)
    13444     (clear-stream $_test-output-buffered-file->buffer)
    13445     (clear-stream _test-error-stream)
    13446     (clear-stream $_test-error-buffered-file->buffer)
    13447     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    13448     68/push 0/imm32
    13449     68/push 0/imm32
    13450     89/<- %edx 4/r32/esp
    13451     (tailor-exit-descriptor %edx 0x10)
    13452     #
    13453     (write _test-input-stream "fn foo {\n")
    13454     (write _test-input-stream "  var a: int\n")
    13455     (write _test-input-stream "  var c/ecx: int <- length a\n")
    13456     (write _test-input-stream "}\n")
    13457     # convert
    13458     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    13459     # registers except esp clobbered at this point
    13460     # restore ed
    13461     89/<- %edx 4/r32/esp
    13462     (flush _test-output-buffered-file)
    13463     (flush _test-error-buffered-file)
    13464 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    13470     # check output
    13471     (check-stream-equal _test-output-stream  ""  "F - test-length-with-non-array-atom-base-type: output should be empty")
    13472     (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")
    13473     # check that stop(1) was called
    13474     (check-ints-equal *(edx+4) 2 "F - test-length-with-non-array-atom-base-type: exit status")
    13475     # don't restore from ebp
    13476     81 0/subop/add %esp 8/imm32
    13477     # . epilogue
    13478     5d/pop-to-ebp
    13479     c3/return
    13480
    13481 test-length-with-non-array-compound-base-type:
    13482     # . prologue
    13483     55/push-ebp
    13484     89/<- %ebp 4/r32/esp
    13485     # setup
    13486     (clear-stream _test-input-stream)
    13487     (clear-stream $_test-input-buffered-file->buffer)
    13488     (clear-stream _test-output-stream)
    13489     (clear-stream $_test-output-buffered-file->buffer)
    13490     (clear-stream _test-error-stream)
    13491     (clear-stream $_test-error-buffered-file->buffer)
    13492     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    13493     68/push 0/imm32
    13494     68/push 0/imm32
    13495     89/<- %edx 4/r32/esp
    13496     (tailor-exit-descriptor %edx 0x10)
    13497     #
    13498     (write _test-input-stream "fn foo {\n")
    13499     (write _test-input-stream "  var a: (handle int)\n")
    13500     (write _test-input-stream "  var c/ecx: (addr int) <- length a, 0\n")
    13501     (write _test-input-stream "}\n")
    13502     # convert
    13503     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    13504     # registers except esp clobbered at this point
    13505     # restore ed
    13506     89/<- %edx 4/r32/esp
    13507     (flush _test-output-buffered-file)
    13508     (flush _test-error-buffered-file)
    13509 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    13515     # check output
    13516     (check-stream-equal _test-output-stream  ""  "F - test-length-with-non-array-compound-base-type: output should be empty")
    13517     (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")
    13518     # check that stop(1) was called
    13519     (check-ints-equal *(edx+4) 2 "F - test-length-with-non-array-compound-base-type: exit status")
    13520     # don't restore from ebp
    13521     81 0/subop/add %esp 8/imm32
    13522     # . epilogue
    13523     5d/pop-to-ebp
    13524     c3/return
    13525
    13526 test-length-with-non-array-compound-base-type-2:
    13527     # . prologue
    13528     55/push-ebp
    13529     89/<- %ebp 4/r32/esp
    13530     # setup
    13531     (clear-stream _test-input-stream)
    13532     (clear-stream $_test-input-buffered-file->buffer)
    13533     (clear-stream _test-output-stream)
    13534     (clear-stream $_test-output-buffered-file->buffer)
    13535     (clear-stream _test-error-stream)
    13536     (clear-stream $_test-error-buffered-file->buffer)
    13537     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    13538     68/push 0/imm32
    13539     68/push 0/imm32
    13540     89/<- %edx 4/r32/esp
    13541     (tailor-exit-descriptor %edx 0x10)
    13542     #
    13543     (write _test-input-stream "fn foo {\n")
    13544     (write _test-input-stream "  var a: (addr int)\n")
    13545     (write _test-input-stream "  var c/ecx: (addr int) <- length a, 0\n")
    13546     (write _test-input-stream "}\n")
    13547     # convert
    13548     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    13549     # registers except esp clobbered at this point
    13550     # restore ed
    13551     89/<- %edx 4/r32/esp
    13552     (flush _test-output-buffered-file)
    13553     (flush _test-error-buffered-file)
    13554 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    13560     # check output
    13561     (check-stream-equal _test-output-stream  ""  "F - test-length-with-non-array-compound-base-type-2: output should be empty")
    13562     (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")
    13563     # check that stop(1) was called
    13564     (check-ints-equal *(edx+4) 2 "F - test-length-with-non-array-compound-base-type-2: exit status")
    13565     # don't restore from ebp
    13566     81 0/subop/add %esp 8/imm32
    13567     # . epilogue
    13568     5d/pop-to-ebp
    13569     c3/return
    13570
    13571 test-length-with-array-atom-base-type:
    13572     # . prologue
    13573     55/push-ebp
    13574     89/<- %ebp 4/r32/esp
    13575     # setup
    13576     (clear-stream _test-input-stream)
    13577     (clear-stream $_test-input-buffered-file->buffer)
    13578     (clear-stream _test-output-stream)
    13579     (clear-stream $_test-output-buffered-file->buffer)
    13580     (clear-stream _test-error-stream)
    13581     (clear-stream $_test-error-buffered-file->buffer)
    13582     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    13583     68/push 0/imm32
    13584     68/push 0/imm32
    13585     89/<- %edx 4/r32/esp
    13586     (tailor-exit-descriptor %edx 0x10)
    13587     #
    13588     (write _test-input-stream "fn foo {\n")
    13589     (write _test-input-stream "  var a: array\n")
    13590     (write _test-input-stream "  var c/ecx: (addr int) <- length a\n")
    13591     (write _test-input-stream "}\n")
    13592     # convert
    13593     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    13594     # registers except esp clobbered at this point
    13595     # restore ed
    13596     89/<- %edx 4/r32/esp
    13597     (flush _test-output-buffered-file)
    13598     (flush _test-error-buffered-file)
    13599 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    13605     # check output
    13606     (check-stream-equal _test-output-stream  ""  "F - test-length-with-array-atom-base-type: output should be empty")
    13607     (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")
    13608     # check that stop(1) was called
    13609     (check-ints-equal *(edx+4) 2 "F - test-length-with-array-atom-base-type: exit status")
    13610     # don't restore from ebp
    13611     81 0/subop/add %esp 8/imm32
    13612     # . epilogue
    13613     5d/pop-to-ebp
    13614     c3/return
    13615
    13616 test-length-with-addr-base-on-stack:
    13617     # . prologue
    13618     55/push-ebp
    13619     89/<- %ebp 4/r32/esp
    13620     # setup
    13621     (clear-stream _test-input-stream)
    13622     (clear-stream $_test-input-buffered-file->buffer)
    13623     (clear-stream _test-output-stream)
    13624     (clear-stream $_test-output-buffered-file->buffer)
    13625     (clear-stream _test-error-stream)
    13626     (clear-stream $_test-error-buffered-file->buffer)
    13627     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    13628     68/push 0/imm32
    13629     68/push 0/imm32
    13630     89/<- %edx 4/r32/esp
    13631     (tailor-exit-descriptor %edx 0x10)
    13632     #
    13633     (write _test-input-stream "fn foo {\n")
    13634     (write _test-input-stream "  var a: (addr array int)\n")
    13635     (write _test-input-stream "  var c/ecx: (addr int) <- length a\n")
    13636     (write _test-input-stream "}\n")
    13637     # convert
    13638     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    13639     # registers except esp clobbered at this point
    13640     # restore ed
    13641     89/<- %edx 4/r32/esp
    13642     (flush _test-output-buffered-file)
    13643     (flush _test-error-buffered-file)
    13644 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    13650     # check output
    13651     (check-stream-equal _test-output-stream  ""  "F - test-length-with-addr-base-on-stack: output should be empty")
    13652     (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")
    13653     # check that stop(1) was called
    13654     (check-ints-equal *(edx+4) 2 "F - test-length-with-addr-base-on-stack: exit status")
    13655     # don't restore from ebp
    13656     81 0/subop/add %esp 8/imm32
    13657     # . epilogue
    13658     5d/pop-to-ebp
    13659     c3/return
    13660
    13661 test-length-with-wrong-output-type:
    13662     # . prologue
    13663     55/push-ebp
    13664     89/<- %ebp 4/r32/esp
    13665     # setup
    13666     (clear-stream _test-input-stream)
    13667     (clear-stream $_test-input-buffered-file->buffer)
    13668     (clear-stream _test-output-stream)
    13669     (clear-stream $_test-output-buffered-file->buffer)
    13670     (clear-stream _test-error-stream)
    13671     (clear-stream $_test-error-buffered-file->buffer)
    13672     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    13673     68/push 0/imm32
    13674     68/push 0/imm32
    13675     89/<- %edx 4/r32/esp
    13676     (tailor-exit-descriptor %edx 0x10)
    13677     #
    13678     (write _test-input-stream "fn foo {\n")
    13679     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
    13680     (write _test-input-stream "  var o/edi: (addr int) <- length a\n")
    13681     (write _test-input-stream "}\n")
    13682     # convert
    13683     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    13684     # registers except esp clobbered at this point
    13685     # restore ed
    13686     89/<- %edx 4/r32/esp
    13687     (flush _test-output-buffered-file)
    13688     (flush _test-error-buffered-file)
    13689 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    13695     # check output
    13696     (check-stream-equal _test-output-stream  ""  "F - test-length-with-wrong-output-type: output should be empty")
    13697     (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")
    13698     # check that stop(1) was called
    13699     (check-ints-equal *(edx+4) 2 "F - test-length-with-wrong-output-type: exit status")
    13700     # don't restore from ebp
    13701     81 0/subop/add %esp 8/imm32
    13702     # . epilogue
    13703     5d/pop-to-ebp
    13704     c3/return
    13705
    13706 test-length-with-wrong-output-compound-type:
    13707     # . prologue
    13708     55/push-ebp
    13709     89/<- %ebp 4/r32/esp
    13710     # setup
    13711     (clear-stream _test-input-stream)
    13712     (clear-stream $_test-input-buffered-file->buffer)
    13713     (clear-stream _test-output-stream)
    13714     (clear-stream $_test-output-buffered-file->buffer)
    13715     (clear-stream _test-error-stream)
    13716     (clear-stream $_test-error-buffered-file->buffer)
    13717     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    13718     68/push 0/imm32
    13719     68/push 0/imm32
    13720     89/<- %edx 4/r32/esp
    13721     (tailor-exit-descriptor %edx 0x10)
    13722     #
    13723     (write _test-input-stream "fn foo {\n")
    13724     (write _test-input-stream "  var a/ebx: (addr array handle boolean) <- copy 0\n")
    13725     (write _test-input-stream "  var o/edi: (addr handle int) <- length a\n")
    13726     (write _test-input-stream "}\n")
    13727     # convert
    13728     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    13729     # registers except esp clobbered at this point
    13730     # restore ed
    13731     89/<- %edx 4/r32/esp
    13732     (flush _test-output-buffered-file)
    13733     (flush _test-error-buffered-file)
    13734 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    13740     # check output
    13741     (check-stream-equal _test-output-stream  ""  "F - test-length-with-wrong-output-compound-type: output should be empty")
    13742     (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")
    13743     # check that stop(1) was called
    13744     (check-ints-equal *(edx+4) 2 "F - test-length-with-wrong-output-compound-type: exit status")
    13745     # don't restore from ebp
    13746     81 0/subop/add %esp 8/imm32
    13747     # . epilogue
    13748     5d/pop-to-ebp
    13749     c3/return
    13750
    13751 test-length-with-no-inouts:
    13752     # . prologue
    13753     55/push-ebp
    13754     89/<- %ebp 4/r32/esp
    13755     # setup
    13756     (clear-stream _test-input-stream)
    13757     (clear-stream $_test-input-buffered-file->buffer)
    13758     (clear-stream _test-output-stream)
    13759     (clear-stream $_test-output-buffered-file->buffer)
    13760     (clear-stream _test-error-stream)
    13761     (clear-stream $_test-error-buffered-file->buffer)
    13762     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    13763     68/push 0/imm32
    13764     68/push 0/imm32
    13765     89/<- %edx 4/r32/esp
    13766     (tailor-exit-descriptor %edx 0x10)
    13767     #
    13768     (write _test-input-stream "fn foo {\n")
    13769     (write _test-input-stream "  var c/ecx: int <- length\n")
    13770     (write _test-input-stream "}\n")
    13771     # convert
    13772     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    13773     # registers except esp clobbered at this point
    13774     # restore ed
    13775     89/<- %edx 4/r32/esp
    13776     (flush _test-output-buffered-file)
    13777     (flush _test-error-buffered-file)
    13778 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    13784     # check output
    13785     (check-stream-equal _test-output-stream  ""  "F - test-length-with-no-inouts: output should be empty")
    13786     (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")
    13787     # check that stop(1) was called
    13788     (check-ints-equal *(edx+4) 2 "F - test-length-with-no-inouts: exit status")
    13789     # don't restore from ebp
    13790     81 0/subop/add %esp 8/imm32
    13791     # . epilogue
    13792     5d/pop-to-ebp
    13793     c3/return
    13794
    13795 test-length-with-too-many-inouts:
    13796     # . prologue
    13797     55/push-ebp
    13798     89/<- %ebp 4/r32/esp
    13799     # setup
    13800     (clear-stream _test-input-stream)
    13801     (clear-stream $_test-input-buffered-file->buffer)
    13802     (clear-stream _test-output-stream)
    13803     (clear-stream $_test-output-buffered-file->buffer)
    13804     (clear-stream _test-error-stream)
    13805     (clear-stream $_test-error-buffered-file->buffer)
    13806     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    13807     68/push 0/imm32
    13808     68/push 0/imm32
    13809     89/<- %edx 4/r32/esp
    13810     (tailor-exit-descriptor %edx 0x10)
    13811     #
    13812     (write _test-input-stream "fn foo {\n")
    13813     (write _test-input-stream "  var a: (array int 3)\n")
    13814     (write _test-input-stream "  var c/ecx: int <- length a, 0, 0\n")
    13815     (write _test-input-stream "}\n")
    13816     # convert
    13817     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    13818     # registers except esp clobbered at this point
    13819     # restore ed
    13820     89/<- %edx 4/r32/esp
    13821     (flush _test-output-buffered-file)
    13822     (flush _test-error-buffered-file)
    13823 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    13829     # check output
    13830     (check-stream-equal _test-output-stream  ""  "F - test-length-with-too-many-inouts: output should be empty")
    13831     (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")
    13832     # check that stop(1) was called
    13833     (check-ints-equal *(edx+4) 2 "F - test-length-with-too-many-inouts: exit status")
    13834     # don't restore from ebp
    13835     81 0/subop/add %esp 8/imm32
    13836     # . epilogue
    13837     5d/pop-to-ebp
    13838     c3/return
    13839
    13840 test-length-with-no-output:
    13841     # . prologue
    13842     55/push-ebp
    13843     89/<- %ebp 4/r32/esp
    13844     # setup
    13845     (clear-stream _test-input-stream)
    13846     (clear-stream $_test-input-buffered-file->buffer)
    13847     (clear-stream _test-output-stream)
    13848     (clear-stream $_test-output-buffered-file->buffer)
    13849     (clear-stream _test-error-stream)
    13850     (clear-stream $_test-error-buffered-file->buffer)
    13851     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    13852     68/push 0/imm32
    13853     68/push 0/imm32
    13854     89/<- %edx 4/r32/esp
    13855     (tailor-exit-descriptor %edx 0x10)
    13856     #
    13857     (write _test-input-stream "fn foo {\n")
    13858     (write _test-input-stream "  var a: (array int 3)\n")
    13859     (write _test-input-stream "  length a\n")
    13860     (write _test-input-stream "}\n")
    13861     # convert
    13862     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    13863     # registers except esp clobbered at this point
    13864     # restore ed
    13865     89/<- %edx 4/r32/esp
    13866     (flush _test-output-buffered-file)
    13867     (flush _test-error-buffered-file)
    13868 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    13874     # check output
    13875     (check-stream-equal _test-output-stream  ""  "F - test-length-with-no-output: output should be empty")
    13876     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt length: must have an output"  "F - test-length-with-no-output: error message")
    13877     # check that stop(1) was called
    13878     (check-ints-equal *(edx+4) 2 "F - test-length-with-no-output: exit status")
    13879     # don't restore from ebp
    13880     81 0/subop/add %esp 8/imm32
    13881     # . epilogue
    13882     5d/pop-to-ebp
    13883     c3/return
    13884
    13885 test-length-with-too-many-outputs:
    13886     # . prologue
    13887     55/push-ebp
    13888     89/<- %ebp 4/r32/esp
    13889     # setup
    13890     (clear-stream _test-input-stream)
    13891     (clear-stream $_test-input-buffered-file->buffer)
    13892     (clear-stream _test-output-stream)
    13893     (clear-stream $_test-output-buffered-file->buffer)
    13894     (clear-stream _test-error-stream)
    13895     (clear-stream $_test-error-buffered-file->buffer)
    13896     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    13897     68/push 0/imm32
    13898     68/push 0/imm32
    13899     89/<- %edx 4/r32/esp
    13900     (tailor-exit-descriptor %edx 0x10)
    13901     #
    13902     (write _test-input-stream "fn foo {\n")
    13903     (write _test-input-stream "  var a: (array int 3)\n")
    13904     (write _test-input-stream "  var b/eax: int <- copy 0\n")
    13905     (write _test-input-stream "  var c/ecx: int <- copy 0\n")
    13906     (write _test-input-stream "  b, c <- length a\n")
    13907     (write _test-input-stream "}\n")
    13908     # convert
    13909     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    13910     # registers except esp clobbered at this point
    13911     # restore ed
    13912     89/<- %edx 4/r32/esp
    13913     (flush _test-output-buffered-file)
    13914     (flush _test-error-buffered-file)
    13915 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    13921     # check output
    13922     (check-stream-equal _test-output-stream  ""  "F - test-length-with-too-many-outputs: output should be empty")
    13923     (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")
    13924     # check that stop(1) was called
    13925     (check-ints-equal *(edx+4) 2 "F - test-length-with-too-many-outputs: exit status")
    13926     # don't restore from ebp
    13927     81 0/subop/add %esp 8/imm32
    13928     # . epilogue
    13929     5d/pop-to-ebp
    13930     c3/return
    13931
    13932 test-convert-function-with-return-register-and-local:
    13933     # . prologue
    13934     55/push-ebp
    13935     89/<- %ebp 4/r32/esp
    13936     # setup
    13937     (clear-stream _test-input-stream)
    13938     (clear-stream $_test-input-buffered-file->buffer)
    13939     (clear-stream _test-output-stream)
    13940     (clear-stream $_test-output-buffered-file->buffer)
    13941     #
    13942     (write _test-input-stream "fn foo -> _/eax: int {\n")
    13943     (write _test-input-stream "  var y/eax: int <- copy 3\n")
    13944     (write _test-input-stream "  var z/ecx: int <- copy 4\n")
    13945     (write _test-input-stream "  return y\n")
    13946     (write _test-input-stream "}\n")
    13947     # convert
    13948     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
    13949     (flush _test-output-buffered-file)
    13950 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
    13956     # check output
    13957     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return-register-and-local/0")
    13958     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return-register-and-local/1")
    13959     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return-register-and-local/2")
    13960     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return-register-and-local/3")
    13961     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return-register-and-local/4")
    13962     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return-register-and-local/5")
    13963     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-with-return-register-and-local/6")
    13964     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 3/imm32"  "F - test-convert-function-with-return-register-and-local/7")
    13965     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-return-register-and-local/8")
    13966     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 4/imm32"  "F - test-convert-function-with-return-register-and-local/9")
    13967     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000000/r32" "F - test-convert-function-with-return-register-and-local/10")
    13968     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"         "F - test-convert-function-with-return-register-and-local/11")
    13969     (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")
    13970     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-return-register-and-local/13")
    13971     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return-register-and-local/14")
    13972     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return-register-and-local/15")
    13973     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return-register-and-local/16")
    13974     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return-register-and-local/17")
    13975     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return-register-and-local/18")
    13976     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return-register-and-local/19")
    13977     # . epilogue
    13978     89/<- %esp 5/r32/ebp
    13979     5d/pop-to-ebp
    13980     c3/return
    13981
    13982 test-convert-function-with-return-register-and-local-2:
    13983     # . prologue
    13984     55/push-ebp
    13985     89/<- %ebp 4/r32/esp
    13986     # setup
    13987     (clear-stream _test-input-stream)
    13988     (clear-stream $_test-input-buffered-file->buffer)
    13989     (clear-stream _test-output-stream)
    13990     (clear-stream $_test-output-buffered-file->buffer)
    13991     #
    13992     (write _test-input-stream "fn foo -> _/eax: int {\n")
    13993     (write _test-input-stream "  var y/eax: int <- copy 3\n")
    13994     (write _test-input-stream "  var z/ecx: int <- copy 4\n")
    13995     (write _test-input-stream "  return z\n")
    13996     (write _test-input-stream "}\n")
    13997     # convert
    13998     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
    13999     (flush _test-output-buffered-file)
    14000 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
    14006     # check output
    14007     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return-register-and-local-2/0")
    14008     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return-register-and-local-2/1")
    14009     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return-register-and-local-2/2")
    14010     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return-register-and-local-2/3")
    14011     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return-register-and-local-2/4")
    14012     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return-register-and-local-2/5")
    14013     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-with-return-register-and-local-2/6")
    14014     (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")
    14015     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-return-register-and-local-2/8")
    14016     (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")
    14017     (check-next-stream-line-equal _test-output-stream "    8b/-> %ecx 0x00000000/r32" "F - test-convert-function-with-return-register-and-local-2/10")
    14018     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"         "F - test-convert-function-with-return-register-and-local-2/11")
    14019     (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")
    14020     (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")
    14021     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return-register-and-local-2/14")
    14022     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return-register-and-local-2/15")
    14023     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return-register-and-local-2/16")
    14024     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return-register-and-local-2/17")
    14025     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return-register-and-local-2/18")
    14026     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return-register-and-local-2/19")
    14027     # . epilogue
    14028     89/<- %esp 5/r32/ebp
    14029     5d/pop-to-ebp
    14030     c3/return
    14031
    14032 test-convert-function-with-return-float-register-and-local:
    14033     # . prologue
    14034     55/push-ebp
    14035     89/<- %ebp 4/r32/esp
    14036     # setup
    14037     (clear-stream _test-input-stream)
    14038     (clear-stream $_test-input-buffered-file->buffer)
    14039     (clear-stream _test-output-stream)
    14040     (clear-stream $_test-output-buffered-file->buffer)
    14041     #
    14042     (write _test-input-stream "fn foo -> _/xmm1: float {\n")
    14043     (write _test-input-stream "  var y/eax: int <- copy 3\n")
    14044     (write _test-input-stream "  var g/xmm0: float <- convert y\n")
    14045     (write _test-input-stream "  var h/xmm1: float <- convert y\n")
    14046     (write _test-input-stream "  return g\n")
    14047     (write _test-input-stream "}\n")
    14048     # convert
    14049     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
    14050     (flush _test-output-buffered-file)
    14051 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
    14057     # check output
    14058     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return-float-register-and-local/0")
    14059     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return-float-register-and-local/1")
    14060     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return-float-register-and-local/2")
    14061     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return-float-register-and-local/3")
    14062     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return-float-register-and-local/4")
    14063     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return-float-register-and-local/5")
    14064     (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
    14065     (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")
    14066     (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
    14067     (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")
    14068     (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")
    14069     (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
    14070     (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")
    14071     (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")
    14072     (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
    14073     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-floating-point-dereferenced/15")  # reclaim h
    14074     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/-> *esp 0/x32"  "F - test-convert-floating-point-dereferenced/16")  # reclaim g
    14075     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-floating-point-dereferenced/17")
    14076     (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
    14077     (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")
    14078     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return-float-register-and-local/20")
    14079     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return-float-register-and-local/21")
    14080     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return-float-register-and-local/22")
    14081     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return-float-register-and-local/23")
    14082     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return-float-register-and-local/24")
    14083     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return-float-register-and-local/25")
    14084     # . epilogue
    14085     89/<- %esp 5/r32/ebp
    14086     5d/pop-to-ebp
    14087     c3/return
    14088
    14089 test-convert-function-with-return-and-local-vars:
    14090     # . prologue
    14091     55/push-ebp
    14092     89/<- %ebp 4/r32/esp
    14093     # setup
    14094     (clear-stream _test-input-stream)
    14095     (clear-stream $_test-input-buffered-file->buffer)
    14096     (clear-stream _test-output-stream)
    14097     (clear-stream $_test-output-buffered-file->buffer)
    14098     #
    14099     (write _test-input-stream "fn foo -> _/eax: int {\n")
    14100     (write _test-input-stream "  {\n")
    14101     (write _test-input-stream "    var x: int\n")
    14102     (write _test-input-stream "    {\n")
    14103     (write _test-input-stream "      var y: int\n")
    14104     (write _test-input-stream "      return y\n")
    14105     (write _test-input-stream "      increment x\n")
    14106     (write _test-input-stream "    }\n")
    14107     (write _test-input-stream "  }\n")
    14108     (write _test-input-stream "  return 0\n")
    14109     (write _test-input-stream "}\n")
    14110     # convert
    14111     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
    14112     (flush _test-output-buffered-file)
    14113 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
    14119     # check output
    14120     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return-and-local-vars/0")
    14121     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return-and-local-vars/1")
    14122     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return-and-local-vars/2")
    14123     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return-and-local-vars/3")
    14124     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return-and-local-vars/4")
    14125     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return-and-local-vars/5")
    14126     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-return-and-local-vars/6")
    14127     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-return-and-local-vars/7")
    14128     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-return-and-local-vars/8")  # var x
    14129     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-return-and-local-vars/9")
    14130     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-return-and-local-vars/10")
    14131     (check-next-stream-line-equal _test-output-stream "        68/push 0/imm32" "F - test-convert-function-with-return-and-local-vars/11")  # var y
    14132     (check-next-stream-line-equal _test-output-stream "        8b/-> *(ebp+0xfffffff8) 0x00000000/r32" "F - test-convert-function-with-return-and-local-vars/12")
    14133     (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")
    14134     (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")
    14135     (check-next-stream-line-equal _test-output-stream "        e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-return-and-local-vars/15")
    14136     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-return-and-local-vars/16")
    14137     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-return-and-local-vars/17")
    14138     (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")
    14139     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-return-and-local-vars/19")
    14140     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-return-and-local-vars/20")
    14141     (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")
    14142     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-return-and-local-vars/21")
    14143     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return-and-local-vars/21")
    14144     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return-and-local-vars/22")
    14145     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return-and-local-vars/23")
    14146     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return-and-local-vars/24")
    14147     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return-and-local-vars/25")
    14148     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return-and-local-vars/26")
    14149     # . epilogue
    14150     89/<- %esp 5/r32/ebp
    14151     5d/pop-to-ebp
    14152     c3/return
    14153
    14154 test-copy-object-with-no-inout:
    14155     # . prologue
    14156     55/push-ebp
    14157     89/<- %ebp 4/r32/esp
    14158     # setup
    14159     (clear-stream _test-input-stream)
    14160     (clear-stream $_test-input-buffered-file->buffer)
    14161     (clear-stream _test-output-stream)
    14162     (clear-stream $_test-output-buffered-file->buffer)
    14163     (clear-stream _test-error-stream)
    14164     (clear-stream $_test-error-buffered-file->buffer)
    14165     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    14166     68/push 0/imm32
    14167     68/push 0/imm32
    14168     89/<- %edx 4/r32/esp
    14169     (tailor-exit-descriptor %edx 0x10)
    14170     #
    14171     (write _test-input-stream "fn foo {\n")
    14172     (write _test-input-stream "  copy-object\n")
    14173     (write _test-input-stream "}\n")
    14174     # convert
    14175     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    14176     # registers except esp clobbered at this point
    14177     # restore ed
    14178     89/<- %edx 4/r32/esp
    14179     (flush _test-output-buffered-file)
    14180     (flush _test-error-buffered-file)
    14181 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    14187     # check output
    14188     (check-stream-equal _test-output-stream  ""  "F - test-copy-object-with-no-inout: output should be empty")
    14189     (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")
    14190     # check that stop(1) was called
    14191     (check-ints-equal *(edx+4) 2 "F - test-copy-object-with-no-inout: exit status")
    14192     # don't restore from ebp
    14193     81 0/subop/add %esp 8/imm32
    14194     # . epilogue
    14195     5d/pop-to-ebp
    14196     c3/return
    14197
    14198 test-copy-object-with-no-source:
    14199     # . prologue
    14200     55/push-ebp
    14201     89/<- %ebp 4/r32/esp
    14202     # setup
    14203     (clear-stream _test-input-stream)
    14204     (clear-stream $_test-input-buffered-file->buffer)
    14205     (clear-stream _test-output-stream)
    14206     (clear-stream $_test-output-buffered-file->buffer)
    14207     (clear-stream _test-error-stream)
    14208     (clear-stream $_test-error-buffered-file->buffer)
    14209     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    14210     68/push 0/imm32
    14211     68/push 0/imm32
    14212     89/<- %edx 4/r32/esp
    14213     (tailor-exit-descriptor %edx 0x10)
    14214     #
    14215     (write _test-input-stream "fn foo {\n")
    14216     (write _test-input-stream "  var x: (addr int)\n")
    14217     (write _test-input-stream "  copy-object x\n")
    14218     (write _test-input-stream "}\n")
    14219     # convert
    14220     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    14221     # registers except esp clobbered at this point
    14222     # restore ed
    14223     89/<- %edx 4/r32/esp
    14224     (flush _test-output-buffered-file)
    14225     (flush _test-error-buffered-file)
    14226 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    14232     # check output
    14233     (check-stream-equal _test-output-stream  ""  "F - test-copy-object-with-no-source: output should be empty")
    14234     (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")
    14235     # check that stop(1) was called
    14236     (check-ints-equal *(edx+4) 2 "F - test-copy-object-with-no-source: exit status")
    14237     # don't restore from ebp
    14238     81 0/subop/add %esp 8/imm32
    14239     # . epilogue
    14240     5d/pop-to-ebp
    14241     c3/return
    14242
    14243 test-copy-object-with-too-many-inouts:
    14244     # . prologue
    14245     55/push-ebp
    14246     89/<- %ebp 4/r32/esp
    14247     # setup
    14248     (clear-stream _test-input-stream)
    14249     (clear-stream $_test-input-buffered-file->buffer)
    14250     (clear-stream _test-output-stream)
    14251     (clear-stream $_test-output-buffered-file->buffer)
    14252     (clear-stream _test-error-stream)
    14253     (clear-stream $_test-error-buffered-file->buffer)
    14254     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    14255     68/push 0/imm32
    14256     68/push 0/imm32
    14257     89/<- %edx 4/r32/esp
    14258     (tailor-exit-descriptor %edx 0x10)
    14259     #
    14260     (write _test-input-stream "fn foo {\n")
    14261     (write _test-input-stream "  var x: (addr boolean)\n")
    14262     (write _test-input-stream "  copy-object x, x, x\n")
    14263     (write _test-input-stream "}\n")
    14264     # convert
    14265     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    14266     # registers except esp clobbered at this point
    14267     # restore ed
    14268     89/<- %edx 4/r32/esp
    14269     (flush _test-output-buffered-file)
    14270     (flush _test-error-buffered-file)
    14271 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    14277     # check output
    14278     (check-stream-equal _test-output-stream  ""  "F - test-copy-object-with-too-many-inouts: output should be empty")
    14279     (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")
    14280     # check that stop(1) was called
    14281     (check-ints-equal *(edx+4) 2 "F - test-copy-object-with-too-many-inouts: exit status")
    14282     # don't restore from ebp
    14283     81 0/subop/add %esp 8/imm32
    14284     # . epilogue
    14285     5d/pop-to-ebp
    14286     c3/return
    14287
    14288 test-copy-object-with-output:
    14289     # . prologue
    14290     55/push-ebp
    14291     89/<- %ebp 4/r32/esp
    14292     # setup
    14293     (clear-stream _test-input-stream)
    14294     (clear-stream $_test-input-buffered-file->buffer)
    14295     (clear-stream _test-output-stream)
    14296     (clear-stream $_test-output-buffered-file->buffer)
    14297     (clear-stream _test-error-stream)
    14298     (clear-stream $_test-error-buffered-file->buffer)
    14299     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    14300     68/push 0/imm32
    14301     68/push 0/imm32
    14302     89/<- %edx 4/r32/esp
    14303     (tailor-exit-descriptor %edx 0x10)
    14304     #
    14305     (write _test-input-stream "fn foo {\n")
    14306     (write _test-input-stream "  var x/eax: (addr boolean) <- copy 0\n")
    14307     (write _test-input-stream "  var y/ecx: (addr boolean) <- copy 0\n")
    14308     (write _test-input-stream "  x <- copy-object x, y\n")
    14309     (write _test-input-stream "}\n")
    14310     # convert
    14311     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    14312     # registers except esp clobbered at this point
    14313     # restore ed
    14314     89/<- %edx 4/r32/esp
    14315     (flush _test-output-buffered-file)
    14316     (flush _test-error-buffered-file)
    14317 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    14323     # check output
    14324     (check-stream-equal _test-output-stream  ""  "F - test-copy-object-with-output: output should be empty")
    14325     (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")
    14326     # check that stop(1) was called
    14327     (check-ints-equal *(edx+4) 2 "F - test-copy-object-with-output: exit status")
    14328     # don't restore from ebp
    14329     81 0/subop/add %esp 8/imm32
    14330     # . epilogue
    14331     5d/pop-to-ebp
    14332     c3/return
    14333
    14334 test-copy-object-deref-address:
    14335     # . prologue
    14336     55/push-ebp
    14337     89/<- %ebp 4/r32/esp
    14338     # setup
    14339     (clear-stream _test-input-stream)
    14340     (clear-stream $_test-input-buffered-file->buffer)
    14341     (clear-stream _test-output-stream)
    14342     (clear-stream $_test-output-buffered-file->buffer)
    14343     #
    14344     (write _test-input-stream "fn foo {\n")
    14345     (write _test-input-stream "  var x/eax: (addr int) <- copy 0\n")
    14346     (write _test-input-stream "  var y/ecx: (addr addr int) <- copy 0\n")
    14347     (write _test-input-stream "  copy-object *y, x\n")
    14348     (write _test-input-stream "}\n")
    14349     # convert
    14350     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
    14351     (flush _test-output-buffered-file)
    14352     # no errors
    14353     # . epilogue
    14354     5d/pop-to-ebp
    14355     c3/return
    14356
    14357 test-copy-object-non-addr:
    14358     # . prologue
    14359     55/push-ebp
    14360     89/<- %ebp 4/r32/esp
    14361     # setup
    14362     (clear-stream _test-input-stream)
    14363     (clear-stream $_test-input-buffered-file->buffer)
    14364     (clear-stream _test-output-stream)
    14365     (clear-stream $_test-output-buffered-file->buffer)
    14366     (clear-stream _test-error-stream)
    14367     (clear-stream $_test-error-buffered-file->buffer)
    14368     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    14369     68/push 0/imm32
    14370     68/push 0/imm32
    14371     89/<- %edx 4/r32/esp
    14372     (tailor-exit-descriptor %edx 0x10)
    14373     #
    14374     (write _test-input-stream "fn foo {\n")
    14375     (write _test-input-stream "  var x: int\n")
    14376     (write _test-input-stream "  var y: int\n")
    14377     (write _test-input-stream "  copy-object y, x\n")
    14378     (write _test-input-stream "}\n")
    14379     # convert
    14380     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    14381     # registers except esp clobbered at this point
    14382     # restore ed
    14383     89/<- %edx 4/r32/esp
    14384     (flush _test-output-buffered-file)
    14385     (flush _test-error-buffered-file)
    14386 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    14392     # check output
    14393     (check-stream-equal _test-output-stream  ""  "F - test-copy-object-non-addr: output should be empty")
    14394     (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")
    14395     # check that stop(1) was called
    14396     (check-ints-equal *(edx+4) 2 "F - test-copy-object-non-addr: exit status")
    14397     # don't restore from ebp
    14398     81 0/subop/add %esp 8/imm32
    14399     # . epilogue
    14400     5d/pop-to-ebp
    14401     c3/return
    14402
    14403 test-copy-object-non-equal:
    14404     # . prologue
    14405     55/push-ebp
    14406     89/<- %ebp 4/r32/esp
    14407     # setup
    14408     (clear-stream _test-input-stream)
    14409     (clear-stream $_test-input-buffered-file->buffer)
    14410     (clear-stream _test-output-stream)
    14411     (clear-stream $_test-output-buffered-file->buffer)
    14412     (clear-stream _test-error-stream)
    14413     (clear-stream $_test-error-buffered-file->buffer)
    14414     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    14415     68/push 0/imm32
    14416     68/push 0/imm32
    14417     89/<- %edx 4/r32/esp
    14418     (tailor-exit-descriptor %edx 0x10)
    14419     #
    14420     (write _test-input-stream "fn foo {\n")
    14421     (write _test-input-stream "  var x: (addr int)\n")
    14422     (write _test-input-stream "  var y: (addr boolean)\n")
    14423     (write _test-input-stream "  copy-object y, x\n")
    14424     (write _test-input-stream "}\n")
    14425     # convert
    14426     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    14427     # registers except esp clobbered at this point
    14428     # restore ed
    14429     89/<- %edx 4/r32/esp
    14430     (flush _test-output-buffered-file)
    14431     (flush _test-error-buffered-file)
    14432 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    14438     # check output
    14439     (check-stream-equal _test-output-stream  ""  "F - test-copy-object-non-equal: output should be empty")
    14440     (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")
    14441     # check that stop(1) was called
    14442     (check-ints-equal *(edx+4) 2 "F - test-copy-object-non-equal: exit status")
    14443     # don't restore from ebp
    14444     81 0/subop/add %esp 8/imm32
    14445     # . epilogue
    14446     5d/pop-to-ebp
    14447     c3/return
    14448
    14449 test-allocate-with-no-inout:
    14450     # . prologue
    14451     55/push-ebp
    14452     89/<- %ebp 4/r32/esp
    14453     # setup
    14454     (clear-stream _test-input-stream)
    14455     (clear-stream $_test-input-buffered-file->buffer)
    14456     (clear-stream _test-output-stream)
    14457     (clear-stream $_test-output-buffered-file->buffer)
    14458     (clear-stream _test-error-stream)
    14459     (clear-stream $_test-error-buffered-file->buffer)
    14460     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    14461     68/push 0/imm32
    14462     68/push 0/imm32
    14463     89/<- %edx 4/r32/esp
    14464     (tailor-exit-descriptor %edx 0x10)
    14465     #
    14466     (write _test-input-stream "fn foo {\n")
    14467     (write _test-input-stream "  allocate\n")
    14468     (write _test-input-stream "}\n")
    14469     # convert
    14470     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    14471     # registers except esp clobbered at this point
    14472     # restore ed
    14473     89/<- %edx 4/r32/esp
    14474     (flush _test-output-buffered-file)
    14475     (flush _test-error-buffered-file)
    14476 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    14482     # check output
    14483     (check-stream-equal _test-output-stream  ""  "F - test-allocate-with-no-inout: output should be empty")
    14484     (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")
    14485     # check that stop(1) was called
    14486     (check-ints-equal *(edx+4) 2 "F - test-allocate-with-no-inout: exit status")
    14487     # don't restore from ebp
    14488     81 0/subop/add %esp 8/imm32
    14489     # . epilogue
    14490     5d/pop-to-ebp
    14491     c3/return
    14492
    14493 test-allocate-with-too-many-inouts:
    14494     # . prologue
    14495     55/push-ebp
    14496     89/<- %ebp 4/r32/esp
    14497     # setup
    14498     (clear-stream _test-input-stream)
    14499     (clear-stream $_test-input-buffered-file->buffer)
    14500     (clear-stream _test-output-stream)
    14501     (clear-stream $_test-output-buffered-file->buffer)
    14502     (clear-stream _test-error-stream)
    14503     (clear-stream $_test-error-buffered-file->buffer)
    14504     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    14505     68/push 0/imm32
    14506     68/push 0/imm32
    14507     89/<- %edx 4/r32/esp
    14508     (tailor-exit-descriptor %edx 0x10)
    14509     #
    14510     (write _test-input-stream "fn foo {\n")
    14511     (write _test-input-stream "  var x: (addr handle int)\n")
    14512     (write _test-input-stream "  allocate x, 0\n")
    14513     (write _test-input-stream "}\n")
    14514     # convert
    14515     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    14516     # registers except esp clobbered at this point
    14517     # restore ed
    14518     89/<- %edx 4/r32/esp
    14519     (flush _test-output-buffered-file)
    14520     (flush _test-error-buffered-file)
    14521 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    14527     # check output
    14528     (check-stream-equal _test-output-stream  ""  "F - test-allocate-with-too-many-inouts: output should be empty")
    14529     (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")
    14530     # check that stop(1) was called
    14531     (check-ints-equal *(edx+4) 2 "F - test-allocate-with-too-many-inouts: exit status")
    14532     # don't restore from ebp
    14533     81 0/subop/add %esp 8/imm32
    14534     # . epilogue
    14535     5d/pop-to-ebp
    14536     c3/return
    14537
    14538 test-allocate-with-output:
    14539     # . prologue
    14540     55/push-ebp
    14541     89/<- %ebp 4/r32/esp
    14542     # setup
    14543     (clear-stream _test-input-stream)
    14544     (clear-stream $_test-input-buffered-file->buffer)
    14545     (clear-stream _test-output-stream)
    14546     (clear-stream $_test-output-buffered-file->buffer)
    14547     (clear-stream _test-error-stream)
    14548     (clear-stream $_test-error-buffered-file->buffer)
    14549     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    14550     68/push 0/imm32
    14551     68/push 0/imm32
    14552     89/<- %edx 4/r32/esp
    14553     (tailor-exit-descriptor %edx 0x10)
    14554     #
    14555     (write _test-input-stream "fn foo {\n")
    14556     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
    14557     (write _test-input-stream "  var y/ecx: (addr handle int) <- copy 0\n")
    14558     (write _test-input-stream "  x <- allocate y\n")
    14559     (write _test-input-stream "}\n")
    14560     # convert
    14561     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    14562     # registers except esp clobbered at this point
    14563     # restore ed
    14564     89/<- %edx 4/r32/esp
    14565     (flush _test-output-buffered-file)
    14566     (flush _test-error-buffered-file)
    14567 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    14573     # check output
    14574     (check-stream-equal _test-output-stream  ""  "F - test-allocate-with-output: output should be empty")
    14575     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'allocate' must not have any outputs"  "F - test-allocate-with-output: error message")
    14576     # check that stop(1) was called
    14577     (check-ints-equal *(edx+4) 2 "F - test-allocate-with-output: exit status")
    14578     # don't restore from ebp
    14579     81 0/subop/add %esp 8/imm32
    14580     # . epilogue
    14581     5d/pop-to-ebp
    14582     c3/return
    14583
    14584 test-allocate-non-addr:
    14585     # . prologue
    14586     55/push-ebp
    14587     89/<- %ebp 4/r32/esp
    14588     # setup
    14589     (clear-stream _test-input-stream)
    14590     (clear-stream $_test-input-buffered-file->buffer)
    14591     (clear-stream _test-output-stream)
    14592     (clear-stream $_test-output-buffered-file->buffer)
    14593     (clear-stream _test-error-stream)
    14594     (clear-stream $_test-error-buffered-file->buffer)
    14595     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    14596     68/push 0/imm32
    14597     68/push 0/imm32
    14598     89/<- %edx 4/r32/esp
    14599     (tailor-exit-descriptor %edx 0x10)
    14600     #
    14601     (write _test-input-stream "fn foo {\n")
    14602     (write _test-input-stream "  var y: (handle int)\n")
    14603     (write _test-input-stream "  allocate y\n")
    14604     (write _test-input-stream "}\n")
    14605     # convert
    14606     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    14607     # registers except esp clobbered at this point
    14608     # restore ed
    14609     89/<- %edx 4/r32/esp
    14610     (flush _test-output-buffered-file)
    14611     (flush _test-error-buffered-file)
    14612 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    14618     # check output
    14619     (check-stream-equal _test-output-stream  ""  "F - test-allocate-non-addr: output must be empty")
    14620     (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")
    14621     # check that stop(1) was called
    14622     (check-ints-equal *(edx+4) 2 "F - test-allocate-non-addr: exit status")
    14623     # don't restore from ebp
    14624     81 0/subop/add %esp 8/imm32
    14625     # . epilogue
    14626     5d/pop-to-ebp
    14627     c3/return
    14628
    14629 test-allocate-non-addr-handle:
    14630     # . prologue
    14631     55/push-ebp
    14632     89/<- %ebp 4/r32/esp
    14633     # setup
    14634     (clear-stream _test-input-stream)
    14635     (clear-stream $_test-input-buffered-file->buffer)
    14636     (clear-stream _test-output-stream)
    14637     (clear-stream $_test-output-buffered-file->buffer)
    14638     (clear-stream _test-error-stream)
    14639     (clear-stream $_test-error-buffered-file->buffer)
    14640     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    14641     68/push 0/imm32
    14642     68/push 0/imm32
    14643     89/<- %edx 4/r32/esp
    14644     (tailor-exit-descriptor %edx 0x10)
    14645     #
    14646     (write _test-input-stream "fn foo {\n")
    14647     (write _test-input-stream "  var y/ecx: (addr int) <- copy 0\n")
    14648     (write _test-input-stream "  allocate y\n")
    14649     (write _test-input-stream "}\n")
    14650     # convert
    14651     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    14652     # registers except esp clobbered at this point
    14653     # restore ed
    14654     89/<- %edx 4/r32/esp
    14655     (flush _test-output-buffered-file)
    14656     (flush _test-error-buffered-file)
    14657 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    14663     # check output
    14664     (check-stream-equal _test-output-stream  ""  "F - test-allocate-non-addr-handle: output should be empty")
    14665     (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")
    14666     # check that stop(1) was called
    14667     (check-ints-equal *(edx+4) 2 "F - test-allocate-non-addr-handle: exit status")
    14668     # don't restore from ebp
    14669     81 0/subop/add %esp 8/imm32
    14670     # . epilogue
    14671     5d/pop-to-ebp
    14672     c3/return
    14673
    14674 test-allocate-deref-address:
    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     #
    14684     (write _test-input-stream "fn foo {\n")
    14685     (write _test-input-stream "  var y/ecx: (addr addr handle int) <- copy 0\n")
    14686     (write _test-input-stream "  allocate *y\n")
    14687     (write _test-input-stream "}\n")
    14688     # convert
    14689     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
    14690     (flush _test-output-buffered-file)
    14691     # no errors
    14692     # . epilogue
    14693     5d/pop-to-ebp
    14694     c3/return
    14695
    14696 test-populate-with-no-inout:
    14697     # . prologue
    14698     55/push-ebp
    14699     89/<- %ebp 4/r32/esp
    14700     # setup
    14701     (clear-stream _test-input-stream)
    14702     (clear-stream $_test-input-buffered-file->buffer)
    14703     (clear-stream _test-output-stream)
    14704     (clear-stream $_test-output-buffered-file->buffer)
    14705     (clear-stream _test-error-stream)
    14706     (clear-stream $_test-error-buffered-file->buffer)
    14707     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    14708     68/push 0/imm32
    14709     68/push 0/imm32
    14710     89/<- %edx 4/r32/esp
    14711     (tailor-exit-descriptor %edx 0x10)
    14712     #
    14713     (write _test-input-stream "fn foo {\n")
    14714     (write _test-input-stream "  populate\n")
    14715     (write _test-input-stream "}\n")
    14716     # convert
    14717     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    14718     # registers except esp clobbered at this point
    14719     # restore ed
    14720     89/<- %edx 4/r32/esp
    14721     (flush _test-output-buffered-file)
    14722     (flush _test-error-buffered-file)
    14723 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    14729     # check output
    14730     (check-stream-equal _test-output-stream  ""  "F - test-populate-with-no-inout: output should be empty")
    14731     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'populate' must have two inouts"  "F - test-populate-with-no-inout: error message")
    14732     # check that stop(1) was called
    14733     (check-ints-equal *(edx+4) 2 "F - test-populate-with-no-inout: exit status")
    14734     # don't restore from ebp
    14735     81 0/subop/add %esp 8/imm32
    14736     # . epilogue
    14737     5d/pop-to-ebp
    14738     c3/return
    14739
    14740 test-populate-with-too-many-inouts:
    14741     # . prologue
    14742     55/push-ebp
    14743     89/<- %ebp 4/r32/esp
    14744     # setup
    14745     (clear-stream _test-input-stream)
    14746     (clear-stream $_test-input-buffered-file->buffer)
    14747     (clear-stream _test-output-stream)
    14748     (clear-stream $_test-output-buffered-file->buffer)
    14749     (clear-stream _test-error-stream)
    14750     (clear-stream $_test-error-buffered-file->buffer)
    14751     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    14752     68/push 0/imm32
    14753     68/push 0/imm32
    14754     89/<- %edx 4/r32/esp
    14755     (tailor-exit-descriptor %edx 0x10)
    14756     #
    14757     (write _test-input-stream "fn foo {\n")
    14758     (write _test-input-stream "  var x: (addr handle int)\n")
    14759     (write _test-input-stream "  populate x, 3, 0\n")
    14760     (write _test-input-stream "}\n")
    14761     # convert
    14762     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    14763     # registers except esp clobbered at this point
    14764     # restore ed
    14765     89/<- %edx 4/r32/esp
    14766     (flush _test-output-buffered-file)
    14767     (flush _test-error-buffered-file)
    14768 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    14774     # check output
    14775     (check-stream-equal _test-output-stream  ""  "F - test-populate-with-too-many-inouts: output should be empty")
    14776     (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")
    14777     # check that stop(1) was called
    14778     (check-ints-equal *(edx+4) 2 "F - test-populate-with-too-many-inouts: exit status")
    14779     # don't restore from ebp
    14780     81 0/subop/add %esp 8/imm32
    14781     # . epilogue
    14782     5d/pop-to-ebp
    14783     c3/return
    14784
    14785 test-populate-with-output:
    14786     # . prologue
    14787     55/push-ebp
    14788     89/<- %ebp 4/r32/esp
    14789     # setup
    14790     (clear-stream _test-input-stream)
    14791     (clear-stream $_test-input-buffered-file->buffer)
    14792     (clear-stream _test-output-stream)
    14793     (clear-stream $_test-output-buffered-file->buffer)
    14794     (clear-stream _test-error-stream)
    14795     (clear-stream $_test-error-buffered-file->buffer)
    14796     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    14797     68/push 0/imm32
    14798     68/push 0/imm32
    14799     89/<- %edx 4/r32/esp
    14800     (tailor-exit-descriptor %edx 0x10)
    14801     #
    14802     (write _test-input-stream "fn foo {\n")
    14803     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
    14804     (write _test-input-stream "  var y/ecx: (addr handle int) <- copy 0\n")
    14805     (write _test-input-stream "  x <- populate y\n")
    14806     (write _test-input-stream "}\n")
    14807     # convert
    14808     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    14809     # registers except esp clobbered at this point
    14810     # restore ed
    14811     89/<- %edx 4/r32/esp
    14812     (flush _test-output-buffered-file)
    14813     (flush _test-error-buffered-file)
    14814 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    14820     # check output
    14821     (check-stream-equal _test-output-stream  ""  "F - test-populate-with-output: output should be empty")
    14822     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'populate' must not have any outputs"  "F - test-populate-with-output: error message")
    14823     # check that stop(1) was called
    14824     (check-ints-equal *(edx+4) 2 "F - test-populate-with-output: exit status")
    14825     # don't restore from ebp
    14826     81 0/subop/add %esp 8/imm32
    14827     # . epilogue
    14828     5d/pop-to-ebp
    14829     c3/return
    14830
    14831 test-populate-non-addr:
    14832     # . prologue
    14833     55/push-ebp
    14834     89/<- %ebp 4/r32/esp
    14835     # setup
    14836     (clear-stream _test-input-stream)
    14837     (clear-stream $_test-input-buffered-file->buffer)
    14838     (clear-stream _test-output-stream)
    14839     (clear-stream $_test-output-buffered-file->buffer)
    14840     (clear-stream _test-error-stream)
    14841     (clear-stream $_test-error-buffered-file->buffer)
    14842     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    14843     68/push 0/imm32
    14844     68/push 0/imm32
    14845     89/<- %edx 4/r32/esp
    14846     (tailor-exit-descriptor %edx 0x10)
    14847     #
    14848     (write _test-input-stream "fn foo {\n")
    14849     (write _test-input-stream "  var y: (handle int)\n")
    14850     (write _test-input-stream "  populate y, 3\n")
    14851     (write _test-input-stream "}\n")
    14852     # convert
    14853     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    14854     # registers except esp clobbered at this point
    14855     # restore ed
    14856     89/<- %edx 4/r32/esp
    14857     (flush _test-output-buffered-file)
    14858     (flush _test-error-buffered-file)
    14859 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    14865     # check output
    14866     (check-stream-equal _test-output-stream  ""  "F - test-populate-non-addr: output must be empty")
    14867     (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")
    14868     # check that stop(1) was called
    14869     (check-ints-equal *(edx+4) 2 "F - test-populate-non-addr: exit status")
    14870     # don't restore from ebp
    14871     81 0/subop/add %esp 8/imm32
    14872     # . epilogue
    14873     5d/pop-to-ebp
    14874     c3/return
    14875
    14876 test-populate-non-addr-handle:
    14877     # . prologue
    14878     55/push-ebp
    14879     89/<- %ebp 4/r32/esp
    14880     # setup
    14881     (clear-stream _test-input-stream)
    14882     (clear-stream $_test-input-buffered-file->buffer)
    14883     (clear-stream _test-output-stream)
    14884     (clear-stream $_test-output-buffered-file->buffer)
    14885     (clear-stream _test-error-stream)
    14886     (clear-stream $_test-error-buffered-file->buffer)
    14887     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    14888     68/push 0/imm32
    14889     68/push 0/imm32
    14890     89/<- %edx 4/r32/esp
    14891     (tailor-exit-descriptor %edx 0x10)
    14892     #
    14893     (write _test-input-stream "fn foo {\n")
    14894     (write _test-input-stream "  var y/ecx: (addr int) <- copy 0\n")
    14895     (write _test-input-stream "  populate y, 3\n")
    14896     (write _test-input-stream "}\n")
    14897     # convert
    14898     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    14899     # registers except esp clobbered at this point
    14900     # restore ed
    14901     89/<- %edx 4/r32/esp
    14902     (flush _test-output-buffered-file)
    14903     (flush _test-error-buffered-file)
    14904 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    14910     # check output
    14911     (check-stream-equal _test-output-stream  ""  "F - test-populate-non-addr-handle: output should be empty")
    14912     (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")
    14913     # check that stop(1) was called
    14914     (check-ints-equal *(edx+4) 2 "F - test-populate-non-addr-handle: exit status")
    14915     # don't restore from ebp
    14916     81 0/subop/add %esp 8/imm32
    14917     # . epilogue
    14918     5d/pop-to-ebp
    14919     c3/return
    14920
    14921 test-populate-non-addr-handle-array:
    14922     # . prologue
    14923     55/push-ebp
    14924     89/<- %ebp 4/r32/esp
    14925     # setup
    14926     (clear-stream _test-input-stream)
    14927     (clear-stream $_test-input-buffered-file->buffer)
    14928     (clear-stream _test-output-stream)
    14929     (clear-stream $_test-output-buffered-file->buffer)
    14930     (clear-stream _test-error-stream)
    14931     (clear-stream $_test-error-buffered-file->buffer)
    14932     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    14933     68/push 0/imm32
    14934     68/push 0/imm32
    14935     89/<- %edx 4/r32/esp
    14936     (tailor-exit-descriptor %edx 0x10)
    14937     #
    14938     (write _test-input-stream "fn foo {\n")
    14939     (write _test-input-stream "  var y/ecx: (addr handle int) <- copy 0\n")
    14940     (write _test-input-stream "  populate y, 3\n")
    14941     (write _test-input-stream "}\n")
    14942     # convert
    14943     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    14944     # registers except esp clobbered at this point
    14945     # restore ed
    14946     89/<- %edx 4/r32/esp
    14947     (flush _test-output-buffered-file)
    14948     (flush _test-error-buffered-file)
    14949 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    14955     # check output
    14956     (check-stream-equal _test-output-stream  ""  "F - test-populate-non-addr-handle-array: output should be empty")
    14957     (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")
    14958     # check that stop(1) was called
    14959     (check-ints-equal *(edx+4) 2 "F - test-populate-non-addr-handle-array: exit status")
    14960     # don't restore from ebp
    14961     81 0/subop/add %esp 8/imm32
    14962     # . epilogue
    14963     5d/pop-to-ebp
    14964     c3/return
    14965
    14966 test-populate-deref-address:
    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     #
    14976     (write _test-input-stream "fn foo {\n")
    14977     (write _test-input-stream "  var y/ecx: (addr addr handle array int) <- copy 0\n")
    14978     (write _test-input-stream "  populate *y, 3\n")
    14979     (write _test-input-stream "}\n")
    14980     # convert
    14981     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
    14982     (flush _test-output-buffered-file)
    14983     # no errors
    14984     # . epilogue
    14985     5d/pop-to-ebp
    14986     c3/return
    14987
    14988 test-populate-stream-with-no-inout:
    14989     # . prologue
    14990     55/push-ebp
    14991     89/<- %ebp 4/r32/esp
    14992     # setup
    14993     (clear-stream _test-input-stream)
    14994     (clear-stream $_test-input-buffered-file->buffer)
    14995     (clear-stream _test-output-stream)
    14996     (clear-stream $_test-output-buffered-file->buffer)
    14997     (clear-stream _test-error-stream)
    14998     (clear-stream $_test-error-buffered-file->buffer)
    14999     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    15000     68/push 0/imm32
    15001     68/push 0/imm32
    15002     89/<- %edx 4/r32/esp
    15003     (tailor-exit-descriptor %edx 0x10)
    15004     #
    15005     (write _test-input-stream "fn foo {\n")
    15006     (write _test-input-stream "  populate-stream\n")
    15007     (write _test-input-stream "}\n")
    15008     # convert
    15009     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    15010     # registers except esp clobbered at this point
    15011     # restore ed
    15012     89/<- %edx 4/r32/esp
    15013     (flush _test-output-buffered-file)
    15014     (flush _test-error-buffered-file)
    15015 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    15021     # check output
    15022     (check-stream-equal _test-output-stream  ""  "F - test-populate-stream-with-no-inout: output should be empty")
    15023     (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")
    15024     # check that stop(1) was called
    15025     (check-ints-equal *(edx+4) 2 "F - test-populate-stream-with-no-inout: exit status")
    15026     # don't restore from ebp
    15027     81 0/subop/add %esp 8/imm32
    15028     # . epilogue
    15029     5d/pop-to-ebp
    15030     c3/return
    15031
    15032 test-populate-stream-with-too-many-inouts:
    15033     # . prologue
    15034     55/push-ebp
    15035     89/<- %ebp 4/r32/esp
    15036     # setup
    15037     (clear-stream _test-input-stream)
    15038     (clear-stream $_test-input-buffered-file->buffer)
    15039     (clear-stream _test-output-stream)
    15040     (clear-stream $_test-output-buffered-file->buffer)
    15041     (clear-stream _test-error-stream)
    15042     (clear-stream $_test-error-buffered-file->buffer)
    15043     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    15044     68/push 0/imm32
    15045     68/push 0/imm32
    15046     89/<- %edx 4/r32/esp
    15047     (tailor-exit-descriptor %edx 0x10)
    15048     #
    15049     (write _test-input-stream "fn foo {\n")
    15050     (write _test-input-stream "  var x: (addr handle int)\n")
    15051     (write _test-input-stream "  populate-stream x, 3, 0\n")
    15052     (write _test-input-stream "}\n")
    15053     # convert
    15054     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    15055     # registers except esp clobbered at this point
    15056     # restore ed
    15057     89/<- %edx 4/r32/esp
    15058     (flush _test-output-buffered-file)
    15059     (flush _test-error-buffered-file)
    15060 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    15066     # check output
    15067     (check-stream-equal _test-output-stream  ""  "F - test-populate-stream-with-too-many-inouts: output should be empty")
    15068     (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")
    15069     # check that stop(1) was called
    15070     (check-ints-equal *(edx+4) 2 "F - test-populate-stream-with-too-many-inouts: exit status")
    15071     # don't restore from ebp
    15072     81 0/subop/add %esp 8/imm32
    15073     # . epilogue
    15074     5d/pop-to-ebp
    15075     c3/return
    15076
    15077 test-populate-stream-with-output:
    15078     # . prologue
    15079     55/push-ebp
    15080     89/<- %ebp 4/r32/esp
    15081     # setup
    15082     (clear-stream _test-input-stream)
    15083     (clear-stream $_test-input-buffered-file->buffer)
    15084     (clear-stream _test-output-stream)
    15085     (clear-stream $_test-output-buffered-file->buffer)
    15086     (clear-stream _test-error-stream)
    15087     (clear-stream $_test-error-buffered-file->buffer)
    15088     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    15089     68/push 0/imm32
    15090     68/push 0/imm32
    15091     89/<- %edx 4/r32/esp
    15092     (tailor-exit-descriptor %edx 0x10)
    15093     #
    15094     (write _test-input-stream "fn foo {\n")
    15095     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
    15096     (write _test-input-stream "  var y/ecx: (addr handle int) <- copy 0\n")
    15097     (write _test-input-stream "  x <- populate-stream y\n")
    15098     (write _test-input-stream "}\n")
    15099     # convert
    15100     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    15101     # registers except esp clobbered at this point
    15102     # restore ed
    15103     89/<- %edx 4/r32/esp
    15104     (flush _test-output-buffered-file)
    15105     (flush _test-error-buffered-file)
    15106 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    15112     # check output
    15113     (check-stream-equal _test-output-stream  ""  "F - test-populate-stream-with-output: output should be empty")
    15114     (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")
    15115     # check that stop(1) was called
    15116     (check-ints-equal *(edx+4) 2 "F - test-populate-stream-with-output: exit status")
    15117     # don't restore from ebp
    15118     81 0/subop/add %esp 8/imm32
    15119     # . epilogue
    15120     5d/pop-to-ebp
    15121     c3/return
    15122
    15123 test-populate-stream-non-addr:
    15124     # . prologue
    15125     55/push-ebp
    15126     89/<- %ebp 4/r32/esp
    15127     # setup
    15128     (clear-stream _test-input-stream)
    15129     (clear-stream $_test-input-buffered-file->buffer)
    15130     (clear-stream _test-output-stream)
    15131     (clear-stream $_test-output-buffered-file->buffer)
    15132     (clear-stream _test-error-stream)
    15133     (clear-stream $_test-error-buffered-file->buffer)
    15134     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    15135     68/push 0/imm32
    15136     68/push 0/imm32
    15137     89/<- %edx 4/r32/esp
    15138     (tailor-exit-descriptor %edx 0x10)
    15139     #
    15140     (write _test-input-stream "fn foo {\n")
    15141     (write _test-input-stream "  var y: (handle int)\n")
    15142     (write _test-input-stream "  populate-stream y, 3\n")
    15143     (write _test-input-stream "}\n")
    15144     # convert
    15145     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    15146     # registers except esp clobbered at this point
    15147     # restore ed
    15148     89/<- %edx 4/r32/esp
    15149     (flush _test-output-buffered-file)
    15150     (flush _test-error-buffered-file)
    15151 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    15157     # check output
    15158     (check-stream-equal _test-output-stream  ""  "F - test-populate-stream-non-addr: output must be empty")
    15159     (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")
    15160     # check that stop(1) was called
    15161     (check-ints-equal *(edx+4) 2 "F - test-populate-stream-non-addr: exit status")
    15162     # don't restore from ebp
    15163     81 0/subop/add %esp 8/imm32
    15164     # . epilogue
    15165     5d/pop-to-ebp
    15166     c3/return
    15167
    15168 test-populate-stream-non-addr-handle:
    15169     # . prologue
    15170     55/push-ebp
    15171     89/<- %ebp 4/r32/esp
    15172     # setup
    15173     (clear-stream _test-input-stream)
    15174     (clear-stream $_test-input-buffered-file->buffer)
    15175     (clear-stream _test-output-stream)
    15176     (clear-stream $_test-output-buffered-file->buffer)
    15177     (clear-stream _test-error-stream)
    15178     (clear-stream $_test-error-buffered-file->buffer)
    15179     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    15180     68/push 0/imm32
    15181     68/push 0/imm32
    15182     89/<- %edx 4/r32/esp
    15183     (tailor-exit-descriptor %edx 0x10)
    15184     #
    15185     (write _test-input-stream "fn foo {\n")
    15186     (write _test-input-stream "  var y/ecx: (addr int) <- copy 0\n")
    15187     (write _test-input-stream "  populate-stream y, 3\n")
    15188     (write _test-input-stream "}\n")
    15189     # convert
    15190     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    15191     # registers except esp clobbered at this point
    15192     # restore ed
    15193     89/<- %edx 4/r32/esp
    15194     (flush _test-output-buffered-file)
    15195     (flush _test-error-buffered-file)
    15196 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    15202     # check output
    15203     (check-stream-equal _test-output-stream  ""  "F - test-populate-stream-non-addr-handle: output should be empty")
    15204     (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")
    15205     # check that stop(1) was called
    15206     (check-ints-equal *(edx+4) 2 "F - test-populate-stream-non-addr-handle: exit status")
    15207     # don't restore from ebp
    15208     81 0/subop/add %esp 8/imm32
    15209     # . epilogue
    15210     5d/pop-to-ebp
    15211     c3/return
    15212
    15213 test-populate-stream-non-addr-handle-stream:
    15214     # . prologue
    15215     55/push-ebp
    15216     89/<- %ebp 4/r32/esp
    15217     # setup
    15218     (clear-stream _test-input-stream)
    15219     (clear-stream $_test-input-buffered-file->buffer)
    15220     (clear-stream _test-output-stream)
    15221     (clear-stream $_test-output-buffered-file->buffer)
    15222     (clear-stream _test-error-stream)
    15223     (clear-stream $_test-error-buffered-file->buffer)
    15224     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    15225     68/push 0/imm32
    15226     68/push 0/imm32
    15227     89/<- %edx 4/r32/esp
    15228     (tailor-exit-descriptor %edx 0x10)
    15229     #
    15230     (write _test-input-stream "fn foo {\n")
    15231     (write _test-input-stream "  var y/ecx: (addr handle int) <- copy 0\n")
    15232     (write _test-input-stream "  populate-stream y, 3\n")
    15233     (write _test-input-stream "}\n")
    15234     # convert
    15235     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    15236     # registers except esp clobbered at this point
    15237     # restore ed
    15238     89/<- %edx 4/r32/esp
    15239     (flush _test-output-buffered-file)
    15240     (flush _test-error-buffered-file)
    15241 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    15247     # check output
    15248     (check-stream-equal _test-output-stream  ""  "F - test-populate-stream-non-addr-handle-stream: output should be empty")
    15249     (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")
    15250     # check that stop(1) was called
    15251     (check-ints-equal *(edx+4) 2 "F - test-populate-stream-non-addr-handle-stream: exit status")
    15252     # don't restore from ebp
    15253     81 0/subop/add %esp 8/imm32
    15254     # . epilogue
    15255     5d/pop-to-ebp
    15256     c3/return
    15257
    15258 test-populate-stream-deref-address:
    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     #
    15268     (write _test-input-stream "fn foo {\n")
    15269     (write _test-input-stream "  var y/ecx: (addr addr handle stream int) <- copy 0\n")
    15270     (write _test-input-stream "  populate-stream *y, 3\n")
    15271     (write _test-input-stream "}\n")
    15272     # convert
    15273     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
    15274     (flush _test-output-buffered-file)
    15275     # no errors
    15276     # . epilogue
    15277     5d/pop-to-ebp
    15278     c3/return
    15279
    15280 test-convert-with-no-inout:
    15281     # . prologue
    15282     55/push-ebp
    15283     89/<- %ebp 4/r32/esp
    15284     # setup
    15285     (clear-stream _test-input-stream)
    15286     (clear-stream $_test-input-buffered-file->buffer)
    15287     (clear-stream _test-output-stream)
    15288     (clear-stream $_test-output-buffered-file->buffer)
    15289     (clear-stream _test-error-stream)
    15290     (clear-stream $_test-error-buffered-file->buffer)
    15291     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    15292     68/push 0/imm32
    15293     68/push 0/imm32
    15294     89/<- %edx 4/r32/esp
    15295     (tailor-exit-descriptor %edx 0x10)
    15296     #
    15297     (write _test-input-stream "fn foo {\n")
    15298     (write _test-input-stream "  var x/eax: int <- convert\n")
    15299     (write _test-input-stream "}\n")
    15300     # convert
    15301     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    15302     # registers except esp clobbered at this point
    15303     # restore ed
    15304     89/<- %edx 4/r32/esp
    15305     (flush _test-output-buffered-file)
    15306     (flush _test-error-buffered-file)
    15307 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    15313     # check output
    15314     (check-stream-equal _test-output-stream  ""  "F - test-convert-with-no-inout: output should be empty")
    15315     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'convert' expects an inout"  "F - test-convert-with-no-inout: error message")
    15316     # check that stop(1) was called
    15317     (check-ints-equal *(edx+4) 2 "F - test-convert-with-no-inout: exit status")
    15318     # don't restore from ebp
    15319     81 0/subop/add %esp 8/imm32
    15320     # . epilogue
    15321     5d/pop-to-ebp
    15322     c3/return
    15323
    15324 test-convert-with-multiple-inouts:
    15325     # . prologue
    15326     55/push-ebp
    15327     89/<- %ebp 4/r32/esp
    15328     # setup
    15329     (clear-stream _test-input-stream)
    15330     (clear-stream $_test-input-buffered-file->buffer)
    15331     (clear-stream _test-output-stream)
    15332     (clear-stream $_test-output-buffered-file->buffer)
    15333     (clear-stream _test-error-stream)
    15334     (clear-stream $_test-error-buffered-file->buffer)
    15335     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    15336     68/push 0/imm32
    15337     68/push 0/imm32
    15338     89/<- %edx 4/r32/esp
    15339     (tailor-exit-descriptor %edx 0x10)
    15340     #
    15341     (write _test-input-stream "fn foo {\n")
    15342     (write _test-input-stream "  var x/eax: int <- convert 0, 0\n")
    15343     (write _test-input-stream "}\n")
    15344     # convert
    15345     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    15346     # registers except esp clobbered at this point
    15347     # restore ed
    15348     89/<- %edx 4/r32/esp
    15349     (flush _test-output-buffered-file)
    15350     (flush _test-error-buffered-file)
    15351 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    15357     # check output
    15358     (check-stream-equal _test-output-stream  ""  "F - test-convert-with-multiple-inouts: output should be empty")
    15359     (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")
    15360     # check that stop(1) was called
    15361     (check-ints-equal *(edx+4) 2 "F - test-convert-with-multiple-inouts: exit status")
    15362     # don't restore from ebp
    15363     81 0/subop/add %esp 8/imm32
    15364     # . epilogue
    15365     5d/pop-to-ebp
    15366     c3/return
    15367
    15368 test-convert-with-no-output:
    15369     # . prologue
    15370     55/push-ebp
    15371     89/<- %ebp 4/r32/esp
    15372     # setup
    15373     (clear-stream _test-input-stream)
    15374     (clear-stream $_test-input-buffered-file->buffer)
    15375     (clear-stream _test-output-stream)
    15376     (clear-stream $_test-output-buffered-file->buffer)
    15377     (clear-stream _test-error-stream)
    15378     (clear-stream $_test-error-buffered-file->buffer)
    15379     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    15380     68/push 0/imm32
    15381     68/push 0/imm32
    15382     89/<- %edx 4/r32/esp
    15383     (tailor-exit-descriptor %edx 0x10)
    15384     #
    15385     (write _test-input-stream "fn foo {\n")
    15386     (write _test-input-stream "  convert 0\n")
    15387     (write _test-input-stream "}\n")
    15388     # convert
    15389     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    15390     # registers except esp clobbered at this point
    15391     # restore ed
    15392     89/<- %edx 4/r32/esp
    15393     (flush _test-output-buffered-file)
    15394     (flush _test-error-buffered-file)
    15395 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    15401     # check output
    15402     (check-stream-equal _test-output-stream  ""  "F - test-convert-with-no-output: output should be empty")
    15403     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'convert' expects an output"  "F - test-convert-with-no-output: error message")
    15404     # check that stop(1) was called
    15405     (check-ints-equal *(edx+4) 2 "F - test-convert-with-no-output: exit status")
    15406     # don't restore from ebp
    15407     81 0/subop/add %esp 8/imm32
    15408     # . epilogue
    15409     5d/pop-to-ebp
    15410     c3/return
    15411
    15412 test-convert-with-multiple-outputs:
    15413     # . prologue
    15414     55/push-ebp
    15415     89/<- %ebp 4/r32/esp
    15416     # setup
    15417     (clear-stream _test-input-stream)
    15418     (clear-stream $_test-input-buffered-file->buffer)
    15419     (clear-stream _test-output-stream)
    15420     (clear-stream $_test-output-buffered-file->buffer)
    15421     (clear-stream _test-error-stream)
    15422     (clear-stream $_test-error-buffered-file->buffer)
    15423     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    15424     68/push 0/imm32
    15425     68/push 0/imm32
    15426     89/<- %edx 4/r32/esp
    15427     (tailor-exit-descriptor %edx 0x10)
    15428     #
    15429     (write _test-input-stream "fn foo {\n")
    15430     (write _test-input-stream "  var x/eax: int <- copy 0\n")
    15431     (write _test-input-stream "  var y/ecx: int <- copy 0\n")
    15432     (write _test-input-stream "  x, y <- convert 0\n")
    15433     (write _test-input-stream "}\n")
    15434     # convert
    15435     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    15436     # registers except esp clobbered at this point
    15437     # restore ed
    15438     89/<- %edx 4/r32/esp
    15439     (flush _test-output-buffered-file)
    15440     (flush _test-error-buffered-file)
    15441 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    15447     # check output
    15448     (check-stream-equal _test-output-stream  ""  "F - test-convert-with-multiple-outputs: output should be empty")
    15449     (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")
    15450     # check that stop(1) was called
    15451     (check-ints-equal *(edx+4) 2 "F - test-convert-with-multiple-outputs: exit status")
    15452     # don't restore from ebp
    15453     81 0/subop/add %esp 8/imm32
    15454     # . epilogue
    15455     5d/pop-to-ebp
    15456     c3/return
    15457
    15458 test-convert-deref-address:
    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     #
    15468     (write _test-input-stream "fn foo {\n")
    15469     (write _test-input-stream "  var x/eax: (addr int) <- copy 0\n")
    15470     (write _test-input-stream "  var y/xmm4: float <- convert *x\n")
    15471     (write _test-input-stream "}\n")
    15472     # convert
    15473     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
    15474     (flush _test-output-buffered-file)
    15475     # no errors
    15476     # . epilogue
    15477     5d/pop-to-ebp
    15478     c3/return
    15479
    15480 test-convert-to-non-register:
    15481     # . prologue
    15482     55/push-ebp
    15483     89/<- %ebp 4/r32/esp
    15484     # setup
    15485     (clear-stream _test-input-stream)
    15486     (clear-stream $_test-input-buffered-file->buffer)
    15487     (clear-stream _test-output-stream)
    15488     (clear-stream $_test-output-buffered-file->buffer)
    15489     (clear-stream _test-error-stream)
    15490     (clear-stream $_test-error-buffered-file->buffer)
    15491     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    15492     68/push 0/imm32
    15493     68/push 0/imm32
    15494     89/<- %edx 4/r32/esp
    15495     (tailor-exit-descriptor %edx 0x10)
    15496     #
    15497     (write _test-input-stream "fn foo {\n")
    15498     (write _test-input-stream "  var x: float\n")
    15499     (write _test-input-stream "  var y: int\n")
    15500     (write _test-input-stream "  x <- convert y\n")
    15501     (write _test-input-stream "}\n")
    15502     # convert
    15503     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    15504     # registers except esp clobbered at this point
    15505     # restore ed
    15506     89/<- %edx 4/r32/esp
    15507     (flush _test-output-buffered-file)
    15508     (flush _test-error-buffered-file)
    15509 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    15515     # check output
    15516     (check-stream-equal _test-output-stream  ""  "F - test-convert-to-non-register: output should be empty")
    15517     (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")
    15518     # check that stop(1) was called
    15519     (check-ints-equal *(edx+4) 2 "F - test-convert-to-non-register: exit status")
    15520     # don't restore from ebp
    15521     81 0/subop/add %esp 8/imm32
    15522     # . epilogue
    15523     5d/pop-to-ebp
    15524     c3/return
    15525
    15526 test-convert-invalid-inout-type:
    15527     # . prologue
    15528     55/push-ebp
    15529     89/<- %ebp 4/r32/esp
    15530     # setup
    15531     (clear-stream _test-input-stream)
    15532     (clear-stream $_test-input-buffered-file->buffer)
    15533     (clear-stream _test-output-stream)
    15534     (clear-stream $_test-output-buffered-file->buffer)
    15535     (clear-stream _test-error-stream)
    15536     (clear-stream $_test-error-buffered-file->buffer)
    15537     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    15538     68/push 0/imm32
    15539     68/push 0/imm32
    15540     89/<- %edx 4/r32/esp
    15541     (tailor-exit-descriptor %edx 0x10)
    15542     #
    15543     (write _test-input-stream "fn foo {\n")
    15544     (write _test-input-stream "  var x: boolean\n")
    15545     (write _test-input-stream "  var y/xmm1: float <- convert x\n")
    15546     (write _test-input-stream "}\n")
    15547     # convert
    15548     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    15549     # registers except esp clobbered at this point
    15550     # restore ed
    15551     89/<- %edx 4/r32/esp
    15552     (flush _test-output-buffered-file)
    15553     (flush _test-error-buffered-file)
    15554 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    15560     # check output
    15561     (check-stream-equal _test-output-stream  ""  "F - test-convert-invalid-inout-type: output should be empty")
    15562     (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")
    15563     # check that stop(1) was called
    15564     (check-ints-equal *(edx+4) 2 "F - test-convert-invalid-inout-type: exit status")
    15565     # don't restore from ebp
    15566     81 0/subop/add %esp 8/imm32
    15567     # . epilogue
    15568     5d/pop-to-ebp
    15569     c3/return
    15570
    15571 test-convert-invalid-output-type:
    15572     # . prologue
    15573     55/push-ebp
    15574     89/<- %ebp 4/r32/esp
    15575     # setup
    15576     (clear-stream _test-input-stream)
    15577     (clear-stream $_test-input-buffered-file->buffer)
    15578     (clear-stream _test-output-stream)
    15579     (clear-stream $_test-output-buffered-file->buffer)
    15580     (clear-stream _test-error-stream)
    15581     (clear-stream $_test-error-buffered-file->buffer)
    15582     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    15583     68/push 0/imm32
    15584     68/push 0/imm32
    15585     89/<- %edx 4/r32/esp
    15586     (tailor-exit-descriptor %edx 0x10)
    15587     #
    15588     (write _test-input-stream "fn foo {\n")
    15589     (write _test-input-stream "  var x: float\n")
    15590     (write _test-input-stream "  var y/eax: boolean <- convert x\n")
    15591     (write _test-input-stream "}\n")
    15592     # convert
    15593     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    15594     # registers except esp clobbered at this point
    15595     # restore ed
    15596     89/<- %edx 4/r32/esp
    15597     (flush _test-output-buffered-file)
    15598     (flush _test-error-buffered-file)
    15599 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    15605     # check output
    15606     (check-stream-equal _test-output-stream  ""  "F - test-convert-invalid-output-type: output should be empty")
    15607     (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")
    15608     # check that stop(1) was called
    15609     (check-ints-equal *(edx+4) 2 "F - test-convert-invalid-output-type: exit status")
    15610     # don't restore from ebp
    15611     81 0/subop/add %esp 8/imm32
    15612     # . epilogue
    15613     5d/pop-to-ebp
    15614     c3/return
    15615
    15616 test-convert-int-to-int:
    15617     # . prologue
    15618     55/push-ebp
    15619     89/<- %ebp 4/r32/esp
    15620     # setup
    15621     (clear-stream _test-input-stream)
    15622     (clear-stream $_test-input-buffered-file->buffer)
    15623     (clear-stream _test-output-stream)
    15624     (clear-stream $_test-output-buffered-file->buffer)
    15625     (clear-stream _test-error-stream)
    15626     (clear-stream $_test-error-buffered-file->buffer)
    15627     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    15628     68/push 0/imm32
    15629     68/push 0/imm32
    15630     89/<- %edx 4/r32/esp
    15631     (tailor-exit-descriptor %edx 0x10)
    15632     #
    15633     (write _test-input-stream "fn foo {\n")
    15634     (write _test-input-stream "  var x: int\n")
    15635     (write _test-input-stream "  var y/eax: int <- convert x\n")
    15636     (write _test-input-stream "}\n")
    15637     # convert
    15638     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    15639     # registers except esp clobbered at this point
    15640     # restore ed
    15641     89/<- %edx 4/r32/esp
    15642     (flush _test-output-buffered-file)
    15643     (flush _test-error-buffered-file)
    15644 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    15650     # check output
    15651     (check-stream-equal _test-output-stream  ""  "F - test-convert-int-to-int: output should be empty")
    15652     (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")
    15653     # check that stop(1) was called
    15654     (check-ints-equal *(edx+4) 2 "F - test-convert-int-to-int: exit status")
    15655     # don't restore from ebp
    15656     81 0/subop/add %esp 8/imm32
    15657     # . epilogue
    15658     5d/pop-to-ebp
    15659     c3/return
    15660
    15661 test-convert-float-to-float:
    15662     # . prologue
    15663     55/push-ebp
    15664     89/<- %ebp 4/r32/esp
    15665     # setup
    15666     (clear-stream _test-input-stream)
    15667     (clear-stream $_test-input-buffered-file->buffer)
    15668     (clear-stream _test-output-stream)
    15669     (clear-stream $_test-output-buffered-file->buffer)
    15670     (clear-stream _test-error-stream)
    15671     (clear-stream $_test-error-buffered-file->buffer)
    15672     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    15673     68/push 0/imm32
    15674     68/push 0/imm32
    15675     89/<- %edx 4/r32/esp
    15676     (tailor-exit-descriptor %edx 0x10)
    15677     #
    15678     (write _test-input-stream "fn foo {\n")
    15679     (write _test-input-stream "  var x: float\n")
    15680     (write _test-input-stream "  var y/xmm6: float <- convert x\n")
    15681     (write _test-input-stream "}\n")
    15682     # convert
    15683     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    15684     # registers except esp clobbered at this point
    15685     # restore ed
    15686     89/<- %edx 4/r32/esp
    15687     (flush _test-output-buffered-file)
    15688     (flush _test-error-buffered-file)
    15689 +--  6 lines: #?     # dump _test-error-stream ------------------------------------------------------------------------------------------------------------------------------------------
    15695     # check output
    15696     (check-stream-equal _test-output-stream  ""  "F - test-convert-float-to-float: output should be empty")
    15697     (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")
    15698     # check that stop(1) was called
    15699     (check-ints-equal *(edx+4) 2 "F - test-convert-float-to-float: exit status")
    15700     # don't restore from ebp
    15701     81 0/subop/add %esp 8/imm32
    15702     # . epilogue
    15703     5d/pop-to-ebp
    15704     c3/return
    15705
    15706 #######################################################
    15707 # Parsing
    15708 #######################################################
    15709
    15710 == data
    15711
    15712 # Global state added to each var record when parsing a function
    15713 Next-block-index:  # (addr int)
    15714     1/imm32
    15715
    15716 Curr-block-depth:  # (addr int)
    15717     1/imm32
    15718
    15719 == code
    15720
    15721 parse-mu:  # in: (addr buffered-file), err: (addr buffered-file), ed: (addr exit-descriptor)
    15722     # pseudocode
    15723     #   var curr-function: (addr handle function) = Program->functions
    15724     #   var curr-signature: (addr handle function) = Program->signatures
    15725     #   var curr-type: (addr handle typeinfo) = Program->types
    15726     #   var line: (stream byte 512)
    15727     #   var word-slice: slice
    15728     #   while true                                  # line loop
    15729     #     clear-stream(line)
    15730     #     read-line-buffered(in, line)
    15731     #     if (line->write == 0) break               # end of file
    15732     #     word-slice = next-mu-token(line)
    15733     #     if slice-empty?(word-slice)               # end of line
    15734     #       continue
    15735     #     else if slice-starts-with?(word-slice, "#")  # comment
    15736     #       continue                                # end of line
    15737     #     else if slice-equal?(word-slice, "fn")
    15738     #       var new-function: (handle function) = allocate(function)
    15739     #       var vars: (stack live-var 256)
    15740     #       populate-mu-function-header(line, new-function, vars)
    15741     #       populate-mu-function-body(in, new-function, vars)
    15742     #       assert(vars->top == 0)
    15743     #       *curr-function = new-function
    15744     #       curr-function = &new-function->next
    15745     #     else if slice-equal?(word-slice, "sig")
    15746     #       var new-function: (handle function) = allocate(function)
    15747     #       populate-mu-function-signature(line, new-function)
    15748     #       *curr-signature = new-function
    15749     #       curr-signature = &new-function->next
    15750     #     else if slice-equal?(word-slice, "type")
    15751     #       word-slice = next-mu-token(line)
    15752     #       type-id = pos-or-insert-slice(Type-id, word-slice)
    15753     #       var new-type: (handle typeinfo) = find-or-create-typeinfo(type-id)
    15754     #       assert(next-word(line) == "{")
    15755     #       populate-mu-type(in, new-type)
    15756     #     else
    15757     #       abort()
    15758     #
    15759     # . prologue
    15760     55/push-ebp
    15761     89/<- %ebp 4/r32/esp
    15762     # var curr-signature: (addr handle function) at *(ebp-4)
    15763     68/push _Program-signatures/imm32
    15764     # . save registers
    15765     50/push-eax
    15766     51/push-ecx
    15767     52/push-edx
    15768     53/push-ebx
    15769     56/push-esi
    15770     57/push-edi
    15771     # var line/ecx: (stream byte 512)
    15772     81 5/subop/subtract %esp 0x200/imm32
    15773     68/push 0x200/imm32/size
    15774     68/push 0/imm32/read
    15775     68/push 0/imm32/write
    15776     89/<- %ecx 4/r32/esp
    15777     # var word-slice/edx: slice
    15778     68/push 0/imm32/end
    15779     68/push 0/imm32/start
    15780     89/<- %edx 4/r32/esp
    15781     # var curr-function/edi: (addr handle function)
    15782     bf/copy-to-edi _Program-functions/imm32
    15783     # var vars/ebx: (stack live-var 256)
    15784     81 5/subop/subtract %esp 0xc00/imm32
    15785     68/push 0xc00/imm32/size
    15786     68/push 0/imm32/top
    15787     89/<- %ebx 4/r32/esp
    15788     {
    15789 $parse-mu:line-loop:
    15790       (clear-stream %ecx)
    15791       (read-line-buffered *(ebp+8) %ecx)
    15792       # if (line->write == 0) break
    15793       81 7/subop/compare *ecx 0/imm32
    15794       0f 84/jump-if-= break/disp32
    15795 +--  6 lines: #?       # dump line ------------------------------------------------------------------------------------------------------------------------------------------------------
    15801       (next-mu-token %ecx %edx)
    15802       # if slice-empty?(word-slice) continue
    15803       (slice-empty? %edx)  # => eax
    15804       3d/compare-eax-and 0/imm32/false
    15805       0f 85/jump-if-!= loop/disp32
    15806       # if (*word-slice->start == "#") continue
    15807       # . eax = *word-slice->start
    15808       8b/-> *edx 0/r32/eax
    15809       8a/copy-byte *eax 0/r32/AL
    15810       25/and-eax-with 0xff/imm32
    15811       # . if (eax == '#') continue
    15812       3d/compare-eax-and 0x23/imm32/hash
    15813       0f 84/jump-if-= loop/disp32
    15814       # if (slice-equal?(word-slice, "fn")) parse a function
    15815       {
    15816 $parse-mu:fn:
    15817         (slice-equal? %edx "fn")  # => eax
    15818         3d/compare-eax-and 0/imm32/false
    15819         0f 84/jump-if-= break/disp32
    15820         # var new-function/esi: (handle function)
    15821         68/push 0/imm32
    15822         68/push 0/imm32
    15823         89/<- %esi 4/r32/esp
    15824         # populate-mu-function(line, in, vars, new-function)
    15825         (allocate Heap *Function-size %esi)
    15826         # var new-function-addr/eax: (addr function)
    15827         (lookup *esi *(esi+4))  # => eax
    15828         # initialize vars
    15829         (clear-stack %ebx)
    15830         #
    15831         (populate-mu-function-header %ecx %eax %ebx *(ebp+0xc) *(ebp+0x10))
    15832         (populate-mu-function-body *(ebp+8) %eax %ebx *(ebp+0xc) *(ebp+0x10))
    15833         # *curr-function = new-function
    15834         8b/-> *esi 0/r32/eax
    15835         89/<- *edi 0/r32/eax
    15836         8b/-> *(esi+4) 0/r32/eax
    15837         89/<- *(edi+4) 0/r32/eax
    15838         # curr-function = &new-function->next
    15839         # . var tmp/eax: (addr function) = lookup(new-function)
    15840         (lookup *esi *(esi+4))  # => eax
    15841         # . curr-function = &tmp->next
    15842         8d/copy-address *(eax+0x20) 7/r32/edi  # Function-next
    15843         # reclaim new-function
    15844         81 0/subop/add %esp 8/imm32
    15845         #
    15846         e9/jump $parse-mu:line-loop/disp32
    15847       }
    15848       # if (slice-equal?(word-slice, "sig")) parse a function signature
    15849       # Function signatures are for providing types to SubX functions.
    15850       {
    15851 $parse-mu:sig:
    15852         (slice-equal? %edx "sig")  # => eax
    15853         3d/compare-eax-and 0/imm32/false
    15854         0f 84/jump-if-= break/disp32
    15855         # edi = curr-function
    15856         57/push-edi
    15857         8b/-> *(ebp-4) 7/r32/edi
    15858         # var new-function/esi: (handle function)
    15859         68/push 0/imm32
    15860         68/push 0/imm32
    15861         89/<- %esi 4/r32/esp
    15862         # populate-mu-function(line, in, vars, new-function)
    15863         (allocate Heap *Function-size %esi)
    15864         # var new-function-addr/eax: (addr function)
    15865         (lookup *esi *(esi+4))  # => eax
    15866         #
    15867         (populate-mu-function-signature %ecx %eax *(ebp+0xc) *(ebp+0x10))
    15868         # *curr-signature = new-function
    15869         8b/-> *esi 0/r32/eax
    15870         89/<- *edi 0/r32/eax
    15871         8b/-> *(esi+4) 0/r32/eax
    15872         89/<- *(edi+4) 0/r32/eax
    15873         # curr-signature = &new-function->next
    15874         # . var tmp/eax: (addr function) = lookup(new-function)
    15875         (lookup *esi *(esi+4))  # => eax
    15876         # . curr-function = &tmp->next
    15877         8d/copy-address *(eax+0x20) 7/r32/edi  # Function-next
    15878         # reclaim new-function
    15879         81 0/subop/add %esp 8/imm32
    15880         # save curr-function
    15881         89/<- *(ebp-4) 7/r32/edi
    15882         # restore edi
    15883         5f/pop-to-edi
    15884         #
    15885         e9/jump $parse-mu:line-loop/disp32
    15886       }
    15887       # if (slice-equal?(word-slice, "type")) parse a type (struct/record) definition
    15888       {
    15889 $parse-mu:type:
    15890         (slice-equal? %edx "type")  # => eax
    15891         3d/compare-eax-and 0/imm32
    15892         0f 84/jump-if-= break/disp32
    15893         (next-mu-token %ecx %edx)
    15894         # var type-id/eax: int
    15895         (pos-or-insert-slice Type-id %edx)  # => eax
    15896         # spill
    15897         51/push-ecx
    15898         # var new-type/ecx: (handle typeinfo)
    15899         68/push 0/imm32
    15900         68/push 0/imm32
    15901         89/<- %ecx 4/r32/esp
    15902         (find-or-create-typeinfo %eax %ecx)
    15903         #
    15904         (lookup *ecx *(ecx+4))  # => eax
    15905         # TODO: ensure that 'line' has nothing else but '{'
    15906 #? (dump-typeinfos "=== aaa\n")
    15907         (populate-mu-type *(ebp+8) %eax *(ebp+0xc) *(ebp+0x10))  # => eax
    15908 #? (dump-typeinfos "=== zzz\n")
    15909         # reclaim new-type
    15910         81 0/subop/add %esp 8/imm32
    15911         # restore
    15912         59/pop-to-ecx
    15913         e9/jump $parse-mu:line-loop/disp32
    15914       }
    15915       # otherwise abort
    15916       e9/jump $parse-mu:error1/disp32
    15917     } # end line loop
    15918 $parse-mu:end:
    15919     # . reclaim locals
    15920     81 0/subop/add %esp 0x20c/imm32  # line
    15921     81 0/subop/add %esp 0xc08/imm32  # vars
    15922     81 0/subop/add %esp 8/imm32
    15923     # . restore registers
    15924     5f/pop-to-edi
    15925     5e/pop-to-esi
    15926     5b/pop-to-ebx
    15927     5a/pop-to-edx
    15928     59/pop-to-ecx
    15929     58/pop-to-eax
    15930     # . reclaim local
    15931     81 0/subop/add %esp 4/imm32
    15932     # . epilogue
    15933     89/<- %esp 5/r32/ebp
    15934     5d/pop-to-ebp
    15935     c3/return
    15936
    15937 $parse-mu:error1:
    15938     # error("unexpected top-level command: " word-slice "\n")
    15939     (write-buffered *(ebp+0xc) "unexpected top-level command: ")
    15940     (write-slice-buffered *(ebp+0xc) %edx)
    15941     (write-buffered *(ebp+0xc) "\n")
    15942     (flush *(ebp+0xc))
    15943     (stop *(ebp+0x10) 1)
    15944     # never gets here
    15945
    15946 $parse-mu:error2:
    15947     # error(vars->top " vars not reclaimed after fn '" new-function->name "'\n")
    15948     (write-int32-hex-buffered *(ebp+0xc) *ebx)
    15949     (write-buffered *(ebp+0xc) " vars not reclaimed after fn '")
    15950     (write-slice-buffered *(ebp+0xc) *eax)  # Function-name
    15951     (write-buffered *(ebp+0xc) "'\n")
    15952     (flush *(ebp+0xc))
    15953     (stop *(ebp+0x10) 1)
    15954     # never gets here
    15955
    15956 # scenarios considered:
    15957 # ✗ fn foo  # no block
    15958 # ✓ fn foo {
    15959 # ✗ fn foo { {
    15960 # ✗ fn foo { }
    15961 # ✗ fn foo { } {
    15962 # ✗ fn foo x {
    15963 # ✗ fn foo x: {
    15964 # ✓ fn foo x: int {
    15965 # ✓ fn foo x: int {
    15966 # ✓ fn foo x: int -> _/eax: int {
    15967 # TODO:
    15968 #   disallow outputs of type `(... addr ...)`
    15969 #   disallow inputs of type `(... addr ... addr ...)`
    15970 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)
    15971     # pseudocode:
    15972     #   var word-slice: slice
    15973     #   next-mu-token(first-line, word-slice)
    15974     #   if slice-empty?(word-slice) abort
    15975     #   assert(word-slice not in '{' '}' '->')
    15976     #   out->name = slice-to-string(word-slice)
    15977     #   ## inouts
    15978     #   while true
    15979     #     word-slice = next-mu-token(first-line)
    15980     #     if slice-empty?(word-slice) abort
    15981     #     if (word-slice == '{') goto done
    15982     #     if (word-slice == '->') break
    15983     #     assert(word-slice != '}')
    15984     #     var v: (handle var) = parse-var-with-type(word-slice, first-line)
    15985     #     assert(v->register == null)
    15986     #     # v->block-depth is implicitly 0
    15987     #     out->inouts = append(v, out->inouts)
    15988     #     push(vars, {v, false})
    15989     #   ## outputs
    15990     #   while true
    15991     #     word-slice = next-mu-token(first-line)
    15992     #     if slice-empty?(word-slice) abort
    15993     #     if (word-slice == '{') break
    15994     #     assert(word-slice not in '}' '->')
    15995     #     var v: (handle var) = parse-var-with-type(word-slice, first-line)
    15996     #     assert(v->register != null)
    15997     #     assert(v->name == "_")
    15998     #     out->outputs = append(v, out->outputs)
    15999     #   done:
    16000     #
    16001     # . prologue
    16002     55/push-ebp
    16003     89/<- %ebp 4/r32/esp
    16004     # . save registers
    16005     50/push-eax
    16006     51/push-ecx
    16007     52/push-edx
    16008     53/push-ebx
    16009     57/push-edi
    16010     # edi = out
    16011     8b/-> *(ebp+0xc) 7/r32/edi
    16012     # var word-slice/ecx: slice
    16013     68/push 0/imm32/end
    16014     68/push 0/imm32/start
    16015     89/<- %ecx 4/r32/esp
    16016     # var v/ebx: (handle var)
    16017     68/push 0/imm32
    16018     68/push 0/imm32
    16019     89/<- %ebx 4/r32/esp
    16020     # read function name
    16021     (next-mu-token *(ebp+8) %ecx)
    16022     # error checking
    16023     # if slice-empty?(word-slice) abort
    16024     (slice-empty? %ecx)  # => eax
    16025     3d/compare-eax-and 0/imm32/false
    16026     0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
    16027     # if (word-slice == '{') abort
    16028     (slice-equal? %ecx "{")   # => eax
    16029     3d/compare-eax-and 0/imm32/false
    16030     0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
    16031     # if (word-slice == '->') abort
    16032     (slice-equal? %ecx "->")   # => eax
    16033     3d/compare-eax-and 0/imm32/false
    16034     0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
    16035     # if (word-slice == '}') abort
    16036     (slice-equal? %ecx "}")   # => eax
    16037     3d/compare-eax-and 0/imm32/false
    16038     0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
    16039     # if word-slice already defined, abort
    16040     (function-exists? %ecx)  # => eax
    16041     3d/compare-eax-and 0/imm32/false
    16042     0f 85/jump-if-!= $populate-mu-function-header:error-duplicate/disp32
    16043     #
    16044     (slice-starts-with? %ecx "break")  # => eax
    16045     3d/compare-eax-and 0/imm32/false
    16046     0f 85/jump-if-!= $populate-mu-function-header:error-break/disp32
    16047     (slice-starts-with? %ecx "loop")  # => eax
    16048     3d/compare-eax-and 0/imm32/false
    16049     0f 85/jump-if-!= $populate-mu-function-header:error-loop/disp32
    16050     (slice-equal? %ecx "lookup")  # => eax
    16051     3d/compare-eax-and 0/imm32/false
    16052     0f 85/jump-if-!= $populate-mu-function-header:error-lookup/disp32
    16053     # save function name
    16054     (slice-to-string Heap %ecx %edi)  # Function-name
    16055     # save function inouts
    16056     {
    16057 $populate-mu-function-header:check-for-inout:
    16058       (next-mu-token *(ebp+8) %ecx)
    16059       # if slice-empty?(word-slice) abort
    16060       (slice-empty? %ecx)  # => eax
    16061       3d/compare-eax-and 0/imm32/false
    16062       0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
    16063       # if (word-slice == '{') goto done
    16064       (slice-equal? %ecx "{")   # => eax
    16065       3d/compare-eax-and 0/imm32/false
    16066       0f 85/jump-if-!= $populate-mu-function-header:done/disp32
    16067       # if (word-slice == '->') break
    16068       (slice-equal? %ecx "->")   # => eax
    16069       3d/compare-eax-and 0/imm32/false
    16070       0f 85/jump-if-!= break/disp32
    16071       # if (word-slice == '}') abort
    16072       (slice-equal? %ecx "}")   # => eax
    16073       3d/compare-eax-and 0/imm32/false
    16074       0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
    16075       # v = parse-var-with-type(word-slice, first-line)
    16076       (lookup *edi *(edi+4))  # Function-name Function-name => eax
    16077       (parse-var-with-type %ecx *(ebp+8) %ebx %eax *(ebp+0x14) *(ebp+0x18))
    16078       # if (v->register != null) abort
    16079       # . eax: (addr var) = lookup(v)
    16080       (lookup *ebx *(ebx+4))  # => eax
    16081       81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
    16082       0f 85/jump-if-!= $populate-mu-function-header:error2/disp32
    16083       # if function name is not "main"
    16084       #    and v->type contains an 'addr' anywhere except the start, abort
    16085       {
    16086         (lookup *edi *(edi+4))  # Function-name Function-name => eax
    16087         (string-equal? %eax "main")  # => eax
    16088         3d/compare-eax-and 0/imm32/false
    16089         75/jump-if-!= break/disp8
    16090         (lookup *ebx *(ebx+4))  # => eax
    16091         (addr-payload-contains-addr? %eax)  # => eax
    16092         3d/compare-eax-and 0/imm32/false
    16093         0f 85/jump-if-!= $populate-mu-function-header:error-nested-addr-inout/disp32
    16094       }
    16095       # v->block-depth is implicitly 0
    16096       #
    16097       # out->inouts = append(v, out->inouts)
    16098       8d/copy-address *(edi+8) 0/r32/eax  # Function-inouts
    16099       (append-list Heap  *ebx *(ebx+4)  *(edi+8) *(edi+0xc)  %eax)  # Function-inouts, Function-inouts
    16100       # push(vars, {v, false})
    16101       (push *(ebp+0x10) *ebx)
    16102       (push *(ebp+0x10) *(ebx+4))
    16103       (push *(ebp+0x10) 0)  # false
    16104       #
    16105       e9/jump loop/disp32
    16106     }
    16107     # save function outputs
    16108     {
    16109 $populate-mu-function-header:check-for-out:
    16110       (next-mu-token *(ebp+8) %ecx)
    16111       # if slice-empty?(word-slice) abort
    16112       (slice-empty? %ecx)  # => eax
    16113       3d/compare-eax-and 0/imm32/false
    16114       0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
    16115       # if (word-slice == '{') break
    16116       (slice-equal? %ecx "{")   # => eax
    16117       3d/compare-eax-and 0/imm32/false
    16118       0f 85/jump-if-!= break/disp32
    16119       # if (word-slice == '->') abort
    16120       (slice-equal? %ecx "->")   # => eax
    16121       3d/compare-eax-and 0/imm32/false
    16122       0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
    16123       # if (word-slice == '}') abort
    16124       (slice-equal? %ecx "}")   # => eax
    16125       3d/compare-eax-and 0/imm32/false
    16126       0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
    16127       # v = parse-var-with-type(word-slice, first-line)
    16128       (lookup *edi *(edi+4))  # Function-name Function-name => eax
    16129       (parse-var-with-type %ecx *(ebp+8) %ebx %eax *(ebp+0x14) *(ebp+0x18))
    16130       # assert(var->register != null)
    16131       # . eax: (addr var) = lookup(v)
    16132       (lookup *ebx *(ebx+4))  # => eax
    16133       81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
    16134       0f 84/jump-if-= $populate-mu-function-header:error3/disp32
    16135       # if (var->name != "_") abort
    16136       (lookup *eax *(eax+4))  # Var-name Var-name => eax
    16137       (string-equal? %eax "_")  # => eax
    16138       3d/compare-eax-and 0/imm32/false
    16139       0f 84/jump-if-= $populate-mu-function-header:error4/disp32
    16140       # if v->type is an addr, abort
    16141       (lookup *ebx *(ebx+4))  # => eax
    16142       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    16143       (mu-addr-type? %eax)  # => eax
    16144       3d/compare-eax-and 0/imm32/false
    16145       0f 85/jump-if-!= $populate-mu-function-header:error-addr-output/disp32
    16146       # out->outputs = append(v, out->outputs)
    16147       8d/copy-address *(edi+0x10) 0/r32/eax  # Function-outputs
    16148       (append-list Heap  *ebx *(ebx+4)  *(edi+0x10) *(edi+0x14)  %eax)  # Function-outputs, Function-outputs
    16149       #
    16150       e9/jump loop/disp32
    16151     }
    16152 $populate-mu-function-header:done:
    16153     (check-no-tokens-left *(ebp+8))
    16154 $populate-mu-function-header:end:
    16155     # . reclaim locals
    16156     81 0/subop/add %esp 0x10/imm32
    16157     # . restore registers
    16158     5f/pop-to-edi
    16159     5b/pop-to-ebx
    16160     5a/pop-to-edx
    16161     59/pop-to-ecx
    16162     58/pop-to-eax
    16163     # . epilogue
    16164     89/<- %esp 5/r32/ebp
    16165     5d/pop-to-ebp
    16166     c3/return
    16167
    16168 $populate-mu-function-header:error1:
    16169     # error("function header not in form 'fn <name> {'")
    16170     (write-buffered *(ebp+0x14) "function header not in form 'fn <name> [inouts] [-> outputs] {' -- '")
    16171     (flush *(ebp+0x14))
    16172     (rewind-stream *(ebp+8))
    16173     (write-stream-data *(ebp+0x14) *(ebp+8))
    16174     (write-buffered *(ebp+0x14) "'\n")
    16175     (flush *(ebp+0x14))
    16176     (stop *(ebp+0x18) 1)
    16177     # never gets here
    16178
    16179 $populate-mu-function-header:error2:
    16180     # error("fn " fn ": function inout '" var "' cannot be in a register")
    16181     (write-buffered *(ebp+0x14) "fn ")
    16182     50/push-eax
    16183     (lookup *edi *(edi+4))  # Function-name Function-name => eax
    16184     (write-buffered *(ebp+0x14) %eax)
    16185     58/pop-to-eax
    16186     (write-buffered *(ebp+0x14) ": function inout '")
    16187     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    16188     (write-buffered *(ebp+0x14) %eax)
    16189     (write-buffered *(ebp+0x14) "' cannot be in a register")
    16190     (flush *(ebp+0x14))
    16191     (stop *(ebp+0x18) 1)
    16192     # never gets here
    16193
    16194 $populate-mu-function-header:error3:
    16195     # error("fn " fn ": function output '" var "' must be in a register")
    16196     (write-buffered *(ebp+0x14) "fn ")
    16197     50/push-eax
    16198     (lookup *edi *(edi+4))  # Function-name Function-name => eax
    16199     (write-buffered *(ebp+0x14) %eax)
    16200     58/pop-to-eax
    16201     (write-buffered *(ebp+0x14) ": function output '")
    16202     (lookup *ebx *(ebx+4))  # => eax
    16203     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    16204     (write-buffered *(ebp+0x14) %eax)
    16205     (write-buffered *(ebp+0x14) "' must be in a register, in instruction '")
    16206     (rewind-stream *(ebp+8))
    16207     (write-stream-data *(ebp+0x14) *(ebp+8))
    16208     (write-buffered *(ebp+0x14) "'\n")
    16209     (flush *(ebp+0x14))
    16210     (stop *(ebp+0x18) 1)
    16211     # never gets here
    16212
    16213 $populate-mu-function-header:error4:
    16214     # error("fn " fn ": function outputs cannot be named; rename '" var "' in the header to '_'")
    16215     (write-buffered *(ebp+0x14) "fn ")
    16216     50/push-eax
    16217     (lookup *edi *(edi+4))  # Function-name Function-name => eax
    16218     (write-buffered *(ebp+0x14) %eax)
    16219     58/pop-to-eax
    16220     (write-buffered *(ebp+0x14) ": function outputs cannot be named; rename '")
    16221     (lookup *ebx *(ebx+4))  # => eax
    16222     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    16223     (write-buffered *(ebp+0x14) %eax)
    16224     (write-buffered *(ebp+0x14) "' in the header to '_'\n")
    16225     (flush *(ebp+0x14))
    16226     (stop *(ebp+0x18) 1)
    16227     # never gets here
    16228
    16229 $populate-mu-function-header:error-duplicate:
    16230     (write-buffered *(ebp+0x14) "fn ")
    16231     (write-slice-buffered *(ebp+0x14) %ecx)
    16232     (write-buffered *(ebp+0x14) " defined more than once\n")
    16233     (flush *(ebp+0x14))
    16234     (stop *(ebp+0x18) 1)
    16235     # never gets here
    16236
    16237 $populate-mu-function-header:error-break:
    16238     (write-buffered *(ebp+0x14) "Sorry, I've reserved all function names starting with 'break' for now. Please contact mu@akkartik.com.\n")
    16239     (flush *(ebp+0x14))
    16240     (stop *(ebp+0x18) 1)
    16241     # never gets here
    16242
    16243 $populate-mu-function-header:error-loop:
    16244     (write-buffered *(ebp+0x14) "Sorry, I've reserved all function names starting with 'loop' for now. Please contact mu@akkartik.com.\n")
    16245     (flush *(ebp+0x14))
    16246     (stop *(ebp+0x18) 1)
    16247     # never gets here
    16248
    16249 $populate-mu-function-header:error-lookup:
    16250     (write-buffered *(ebp+0x14) "cannot define a function called 'lookup'\n")
    16251     (flush *(ebp+0x14))
    16252     (stop *(ebp+0x18) 1)
    16253     # never gets here
    16254
    16255 $populate-mu-function-header:error-addr-output:
    16256     # error("fn " fn ": output cannot have an addr type; that could allow unsafe addresses to escape the function")
    16257     (write-buffered *(ebp+0x14) "fn ")
    16258     50/push-eax
    16259     (lookup *edi *(edi+4))  # Function-name Function-name => eax
    16260     (write-buffered *(ebp+0x14) %eax)
    16261     58/pop-to-eax
    16262     (write-buffered *(ebp+0x14) ": output cannot have an addr type; that could allow unsafe addresses to escape the function\n")
    16263     (flush *(ebp+0x14))
    16264     (stop *(ebp+0x18) 1)
    16265     # never gets here
    16266
    16267 $populate-mu-function-header:error-nested-addr-inout:
    16268     # 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")
    16269     (write-buffered *(ebp+0x14) "fn ")
    16270     (lookup *edi *(edi+4))  # Function-name Function-name => eax
    16271     (write-buffered *(ebp+0x14) %eax)
    16272     (write-buffered *(ebp+0x14) ": inout '")
    16273     (lookup *ebx *(ebx+4))  # => eax
    16274     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    16275     (write-buffered *(ebp+0x14) %eax)
    16276     (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")
    16277     (flush *(ebp+0x14))
    16278     (stop *(ebp+0x18) 1)
    16279     # never gets here
    16280
    16281 # scenarios considered:
    16282 # ✓ fn foo
    16283 # ✗ fn foo {
    16284 # ✓ fn foo x
    16285 # ✓ fn foo x: int
    16286 # ✓ fn foo x: int -> _/eax: int
    16287 # TODO:
    16288 #   disallow outputs of type `(... addr ...)`
    16289 #   disallow inputs of type `(... addr ... addr ...)`
    16290 populate-mu-function-signature:  # first-line: (addr stream byte), out: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    16291     # pseudocode:
    16292     #   var word-slice: slice
    16293     #   next-mu-token(first-line, word-slice)
    16294     #   assert(word-slice not in '{' '}' '->')
    16295     #   out->name = slice-to-string(word-slice)
    16296     #   ## inouts
    16297     #   while true
    16298     #     word-slice = next-mu-token(first-line)
    16299     #     if slice-empty?(word-slice) break
    16300     #     if (word-slice == '->') break
    16301     #     assert(word-slice not in '{' '}')
    16302     #     var v: (handle var) = parse-var-with-type(word-slice, first-line)
    16303     #     assert(v->register == null)
    16304     #     # v->block-depth is implicitly 0
    16305     #     out->inouts = append(v, out->inouts)
    16306     #   ## outputs
    16307     #   while true
    16308     #     word-slice = next-mu-token(first-line)
    16309     #     if slice-empty?(word-slice) break
    16310     #     assert(word-slice not in '{' '}' '->')
    16311     #     var v: (handle var) = parse-var-with-type(word-slice, first-line)
    16312     #     assert(v->register != null)
    16313     #     out->outputs = append(v, out->outputs)
    16314     #
    16315     # . prologue
    16316     55/push-ebp
    16317     89/<- %ebp 4/r32/esp
    16318     # . save registers
    16319     50/push-eax
    16320     51/push-ecx
    16321     52/push-edx
    16322     53/push-ebx
    16323     57/push-edi
    16324     # edi = out
    16325     8b/-> *(ebp+0xc) 7/r32/edi
    16326     # var word-slice/ecx: slice
    16327     68/push 0/imm32/end
    16328     68/push 0/imm32/start
    16329     89/<- %ecx 4/r32/esp
    16330     # var v/ebx: (handle var)
    16331     68/push 0/imm32
    16332     68/push 0/imm32
    16333     89/<- %ebx 4/r32/esp
    16334     # read function name
    16335     (next-mu-token *(ebp+8) %ecx)
    16336     # error checking
    16337     # if (word-slice == '{') abort
    16338     (slice-equal? %ecx "{")   # => eax
    16339     3d/compare-eax-and 0/imm32/false
    16340     0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
    16341     # if (word-slice == '->') abort
    16342     (slice-equal? %ecx "->")   # => eax
    16343     3d/compare-eax-and 0/imm32/false
    16344     0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
    16345     # if (word-slice == '}') abort
    16346     (slice-equal? %ecx "}")   # => eax
    16347     3d/compare-eax-and 0/imm32/false
    16348     0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
    16349     # if word-slice already defined, abort
    16350     (function-exists? %ecx)  # => eax
    16351     3d/compare-eax-and 0/imm32/false
    16352     0f 85/jump-if-!= $populate-mu-function-signature:error-duplicate/disp32
    16353     #
    16354     (slice-starts-with? %ecx "break")  # => eax
    16355     3d/compare-eax-and 0/imm32/false
    16356     0f 85/jump-if-!= $populate-mu-function-signature:error-break/disp32
    16357     (slice-starts-with? %ecx "loop")  # => eax
    16358     3d/compare-eax-and 0/imm32/false
    16359     0f 85/jump-if-!= $populate-mu-function-signature:error-loop/disp32
    16360     # save function name
    16361     (slice-to-string Heap %ecx %edi)  # Function-name
    16362     # save function inouts
    16363     {
    16364 $populate-mu-function-signature:check-for-inout:
    16365       (next-mu-token *(ebp+8) %ecx)
    16366       (slice-empty? %ecx)  # => eax
    16367       3d/compare-eax-and 0/imm32/false
    16368       0f 85/jump-if-!= break/disp32
    16369       # if (word-slice == '->') break
    16370       (slice-equal? %ecx "->")   # => eax
    16371       3d/compare-eax-and 0/imm32/false
    16372       0f 85/jump-if-!= break/disp32
    16373       # if (word-slice == '{') abort
    16374       (slice-equal? %ecx "{")   # => eax
    16375       3d/compare-eax-and 0/imm32/false
    16376       0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
    16377       # if (word-slice == '}') abort
    16378       (slice-equal? %ecx "}")   # => eax
    16379       3d/compare-eax-and 0/imm32/false
    16380       0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
    16381       # v = parse-var-with-type(word-slice, first-line)
    16382       (lookup *edi *(edi+4))  # Function-name Function-name => eax
    16383       (parse-var-with-type %ecx *(ebp+8) %ebx %eax *(ebp+0x10) *(ebp+0x14))
    16384       # if (v->register != null) abort
    16385       # . eax: (addr var) = lookup(v)
    16386       (lookup *ebx *(ebx+4))  # => eax
    16387       81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
    16388       0f 85/jump-if-!= $populate-mu-function-signature:error2/disp32
    16389       # if function name is not "main"
    16390       #    and v->type contains an 'addr' anywhere except the start, abort
    16391       {
    16392         (lookup *edi *(edi+4))  # Function-name Function-name => eax
    16393         (string-equal? %eax "main")  # => eax
    16394         3d/compare-eax-and 0/imm32/false
    16395         75/jump-if-!= break/disp8
    16396         (lookup *ebx *(ebx+4))  # => eax
    16397         (addr-payload-contains-addr? %eax)  # => eax
    16398         3d/compare-eax-and 0/imm32/false
    16399         0f 85/jump-if-!= $populate-mu-function-signature:error-nested-addr-inout/disp32
    16400       }
    16401       # assert(v->register == null)
    16402       # . eax: (addr var) = lookup(v)
    16403       (lookup *ebx *(ebx+4))  # => eax
    16404       81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
    16405       0f 85/jump-if-!= $populate-mu-function-signature:error2/disp32
    16406       # v->block-depth is implicitly 0
    16407       #
    16408       # out->inouts = append(v, out->inouts)
    16409       8d/copy-address *(edi+8) 0/r32/eax  # Function-inouts
    16410       (append-list Heap  *ebx *(ebx+4)  *(edi+8) *(edi+0xc)  %eax)  # Function-inouts, Function-inouts
    16411       #
    16412       e9/jump loop/disp32
    16413     }
    16414     # save function outputs
    16415     {
    16416 $populate-mu-function-signature:check-for-out:
    16417       (next-mu-token *(ebp+8) %ecx)
    16418       (slice-empty? %ecx)  # => eax
    16419       3d/compare-eax-and 0/imm32/false
    16420       0f 85/jump-if-!= break/disp32
    16421       # if (word-slice == '{') abort
    16422       (slice-equal? %ecx "{")   # => eax
    16423       3d/compare-eax-and 0/imm32/false
    16424       0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
    16425       # if (word-slice == '->') abort
    16426       (slice-equal? %ecx "->")   # => eax
    16427       3d/compare-eax-and 0/imm32/false
    16428       0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
    16429       # if (word-slice == '}') abort
    16430       (slice-equal? %ecx "}")   # => eax
    16431       3d/compare-eax-and 0/imm32/false
    16432       0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
    16433       # v = parse-var-with-type(word-slice, first-line)
    16434       (lookup *edi *(edi+4))  # Function-name Function-name => eax
    16435       (parse-var-with-type %ecx *(ebp+8) %ebx %eax *(ebp+0x10) *(ebp+0x14))
    16436       # assert(var->register != null)
    16437       # . eax: (addr var) = lookup(v)
    16438       (lookup *ebx *(ebx+4))  # => eax
    16439       81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
    16440       0f 84/jump-if-= $populate-mu-function-signature:error3/disp32
    16441       # if (var->name != "_") abort
    16442       (lookup *eax *(eax+4))  # Var-name Var-name => eax
    16443       (string-equal? %eax "_")  # => eax
    16444       3d/compare-eax-and 0/imm32/false
    16445       0f 84/jump-if-= $populate-mu-function-signature:error4/disp32
    16446       # if function name is not "lookup"
    16447       #    and v->type is an addr, abort
    16448       {
    16449         (lookup *edi *(edi+4))  # Function-name Function-name => eax
    16450         (string-equal? %eax "lookup")  # => eax
    16451         3d/compare-eax-and 0/imm32/false
    16452         75/jump-if-!= break/disp8
    16453         (lookup *ebx *(ebx+4))  # => eax
    16454         (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    16455         (mu-addr-type? %eax)  # => eax
    16456         3d/compare-eax-and 0/imm32/false
    16457         0f 85/jump-if-!= $populate-mu-function-signature:error-addr-output/disp32
    16458       }
    16459       # out->outputs = append(v, out->outputs)
    16460       8d/copy-address *(edi+0x10) 0/r32/eax  # Function-outputs
    16461       (append-list Heap  *ebx *(ebx+4)  *(edi+0x10) *(edi+0x14)  %eax)  # Function-outputs, Function-outputs
    16462       #
    16463       e9/jump loop/disp32
    16464     }
    16465 $populate-mu-function-signature:done:
    16466     (check-no-tokens-left *(ebp+8))
    16467 $populate-mu-function-signature:end:
    16468     # . reclaim locals
    16469     81 0/subop/add %esp 0x10/imm32
    16470     # . restore registers
    16471     5f/pop-to-edi
    16472     5b/pop-to-ebx
    16473     5a/pop-to-edx
    16474     59/pop-to-ecx
    16475     58/pop-to-eax
    16476     # . epilogue
    16477     89/<- %esp 5/r32/ebp
    16478     5d/pop-to-ebp
    16479     c3/return
    16480
    16481 $populate-mu-function-signature:error1:
    16482     # error("function signature not in form 'fn <name> {'")
    16483     (write-buffered *(ebp+0x10) "function signature not in form 'fn <name> [inouts] [-> outputs] {' -- '")
    16484     (flush *(ebp+0x10))
    16485     (rewind-stream *(ebp+8))
    16486     (write-stream-data *(ebp+0x10) *(ebp+8))
    16487     (write-buffered *(ebp+0x10) "'\n")
    16488     (flush *(ebp+0x10))
    16489     (stop *(ebp+0x14) 1)
    16490     # never gets here
    16491
    16492 $populate-mu-function-signature:error2:
    16493     # error("fn " fn ": function inout '" var "' cannot be in a register")
    16494     (write-buffered *(ebp+0x10) "fn ")
    16495     50/push-eax
    16496     (lookup *edi *(edi+4))  # Function-name Function-name => eax
    16497     (write-buffered *(ebp+0x10) %eax)
    16498     58/pop-to-eax
    16499     (write-buffered *(ebp+0x10) ": function inout '")
    16500     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    16501     (write-buffered *(ebp+0x10) %eax)
    16502     (write-buffered *(ebp+0x10) "' cannot be in a register")
    16503     (flush *(ebp+0x10))
    16504     (stop *(ebp+0x14) 1)
    16505     # never gets here
    16506
    16507 $populate-mu-function-signature:error3:
    16508     # error("fn " fn ": function output '" var "' must be in a register")
    16509     (write-buffered *(ebp+0x10) "fn ")
    16510     50/push-eax
    16511     (lookup *edi *(edi+4))  # Function-name Function-name => eax
    16512     (write-buffered *(ebp+0x10) %eax)
    16513     58/pop-to-eax
    16514     (write-buffered *(ebp+0x10) ": function output '")
    16515     (lookup *ebx *(ebx+4))  # => eax
    16516     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    16517     (write-buffered *(ebp+0x10) %eax)
    16518     (write-buffered *(ebp+0x10) "' must be in a register, in instruction '")
    16519     (rewind-stream *(ebp+8))
    16520     (write-stream-data *(ebp+0x10) *(ebp+8))
    16521     (write-buffered *(ebp+0x10) "'\n")
    16522     (flush *(ebp+0x10))
    16523     (stop *(ebp+0x14) 1)
    16524     # never gets here
    16525
    16526 $populate-mu-function-signature:error4:
    16527     # error("fn " fn ": function outputs cannot be named; rename '" var "' in the header to '_'")
    16528     (write-buffered *(ebp+0x10) "fn ")
    16529     50/push-eax
    16530     (lookup *edi *(edi+4))  # Function-name Function-name => eax
    16531     (write-buffered *(ebp+0x10) %eax)
    16532     58/pop-to-eax
    16533     (write-buffered *(ebp+0x10) ": function outputs cannot be named; rename '")
    16534     (lookup *ebx *(ebx+4))  # => eax
    16535     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    16536     (write-buffered *(ebp+0x10) %eax)
    16537     (write-buffered *(ebp+0x10) "' in the header to '_'\n")
    16538     (flush *(ebp+0x10))
    16539     (stop *(ebp+0x14) 1)
    16540     # never gets here
    16541
    16542 $populate-mu-function-signature:error-duplicate:
    16543     (write-buffered *(ebp+0x10) "fn ")
    16544     (write-slice-buffered *(ebp+0x10) %ecx)
    16545     (write-buffered *(ebp+0x10) " defined more than once\n")
    16546     (flush *(ebp+0x10))
    16547     (stop *(ebp+0x14) 1)
    16548     # never gets here
    16549
    16550 $populate-mu-function-signature:error-break:
    16551     (write-buffered *(ebp+0x10) "Sorry, I've reserved all function names starting with 'break' for now. Please contact mu@akkartik.com.\n")
    16552     (flush *(ebp+0x10))
    16553     (stop *(ebp+0x14) 1)
    16554     # never gets here
    16555
    16556 $populate-mu-function-signature:error-loop:
    16557     (write-buffered *(ebp+0x10) "Sorry, I've reserved all function names starting with 'loop' for now. Please contact mu@akkartik.com.\n")
    16558     (flush *(ebp+0x10))
    16559     (stop *(ebp+0x14) 1)
    16560     # never gets here
    16561
    16562 $populate-mu-function-signature:error-addr-output:
    16563     # error("fn " fn ": output cannot have an addr type; that could allow unsafe addresses to escape the function")
    16564     (write-buffered *(ebp+0x10) "fn ")
    16565     50/push-eax
    16566     (lookup *edi *(edi+4))  # Function-name Function-name => eax
    16567     (write-buffered *(ebp+0x10) %eax)
    16568     58/pop-to-eax
    16569     (write-buffered *(ebp+0x10) ": output cannot have an addr type; that could allow unsafe addresses to escape the function\n")
    16570     (flush *(ebp+0x10))
    16571     (stop *(ebp+0x14) 1)
    16572     # never gets here
    16573
    16574 $populate-mu-function-signature:error-nested-addr-inout:
    16575     # 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")
    16576     (write-buffered *(ebp+0x10) "fn ")
    16577     (lookup *edi *(edi+4))  # Function-name Function-name => eax
    16578     (write-buffered *(ebp+0x10) %eax)
    16579     (write-buffered *(ebp+0x10) ": inout '")
    16580     (lookup *ebx *(ebx+4))  # => eax
    16581     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    16582     (write-buffered *(ebp+0x10) %eax)
    16583     (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")
    16584     (flush *(ebp+0x10))
    16585     (stop *(ebp+0x14) 1)
    16586     # never gets here
    16587
    16588 addr-payload-contains-addr?:  # v: (addr var) -> result/eax: boolean
    16589     # . prologue
    16590     55/push-ebp
    16591     89/<- %ebp 4/r32/esp
    16592     # var t/eax: (addr type-tree) = v->type
    16593     8b/-> *(ebp+8) 0/r32/eax
    16594     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    16595     # if t->right contains addr, return true
    16596     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
    16597     (type-tree-contains? %eax 2)  # addr => eax
    16598     # we don't have to look at t->left as long as it's guaranteed to be an atom
    16599 $addr-payload-contains-addr?:end:
    16600     # . epilogue
    16601     89/<- %esp 5/r32/ebp
    16602     5d/pop-to-ebp
    16603     c3/return
    16604
    16605 type-tree-contains?:  # t: (addr type-tree), n: type-id -> result/eax: boolean
    16606     # . prologue
    16607     55/push-ebp
    16608     89/<- %ebp 4/r32/esp
    16609     # . save registers
    16610     51/push-ecx
    16611     # if t is null, return false
    16612     8b/-> *(ebp+8) 0/r32/eax
    16613     3d/compare-eax-and 0/imm32
    16614     0f 84/jump-if-= $type-tree-contains?:end/disp32  # eax changes type
    16615     # if t is an atom, return (t->value == n)
    16616     81 7/subop/compare *eax 0/imm32/false
    16617     {
    16618       74/jump-if-= break/disp8
    16619       8b/-> *(ebp+0xc) 1/r32/ecx
    16620       39/compare *(eax+4) 1/r32/ecx  # Type-tree-value
    16621       0f 94/set-if-= %al
    16622       25/and-eax-with 0xff/imm32
    16623       eb/jump $type-tree-contains?:end/disp8
    16624     }
    16625     # if t->left contains n, return true
    16626     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    16627     (type-tree-contains? %eax *(ebp+0xc))  # => eax
    16628     3d/compare-eax-and 0/imm32/false
    16629     75/jump-if-!= $type-tree-contains?:end/disp8
    16630     # otherwise return whether t->right contains n
    16631     8b/-> *(ebp+8) 0/r32/eax
    16632     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
    16633     (type-tree-contains? %eax *(ebp+0xc))  # => eax
    16634 $type-tree-contains?:end:
    16635     # . restore registers
    16636     59/pop-to-ecx
    16637     # . epilogue
    16638     89/<- %esp 5/r32/ebp
    16639     5d/pop-to-ebp
    16640     c3/return
    16641
    16642 function-exists?:  # s: (addr slice) -> result/eax: boolean
    16643     # . prologue
    16644     55/push-ebp
    16645     89/<- %ebp 4/r32/esp
    16646     # . save registers
    16647     51/push-ecx
    16648     # var curr/ecx: (addr function) = functions
    16649     (lookup *_Program-functions *_Program-functions->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         e9/jump $function-exists?:end/disp32
    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     # var curr/ecx: (addr function) = signatures
    16671     (lookup *_Program-signatures *_Program-signatures->payload)  # => eax
    16672     89/<- %ecx 0/r32/eax
    16673     {
    16674       # if (curr == null) break
    16675       81 7/subop/compare %ecx 0/imm32
    16676       74/jump-if-= break/disp8
    16677       # if (curr->name == s) return true
    16678       {
    16679         (lookup *ecx *(ecx+4))  # Function-name Function-name => eax
    16680         (slice-equal? *(ebp+8) %eax)  # => eax
    16681         3d/compare-eax-and 0/imm32/false
    16682         74/jump-if-= break/disp8
    16683         b8/copy-to-eax 1/imm32/true
    16684         eb/jump $function-exists?:end/disp8
    16685       }
    16686       # curr = curr->next
    16687       (lookup *(ecx+0x20) *(ecx+0x24))  # Function-next Function-next => eax
    16688       89/<- %ecx 0/r32/eax
    16689       #
    16690       eb/jump loop/disp8
    16691     }
    16692     # return false
    16693     b8/copy-to-eax 0/imm32/false
    16694 $function-exists?:end:
    16695     # . restore registers
    16696     59/pop-to-ecx
    16697     # . epilogue
    16698     89/<- %esp 5/r32/ebp
    16699     5d/pop-to-ebp
    16700     c3/return
    16701
    16702 test-function-header-with-arg:
    16703     # . prologue
    16704     55/push-ebp
    16705     89/<- %ebp 4/r32/esp
    16706     # setup
    16707     8b/-> *Primitive-type-ids 0/r32/eax
    16708     89/<- *Type-id 0/r32/eax  # stream-write
    16709     c7 0/subop/copy *_Program-functions 0/imm32
    16710     c7 0/subop/copy *_Program-functions->payload 0/imm32
    16711     c7 0/subop/copy *_Program-types 0/imm32
    16712     c7 0/subop/copy *_Program-types->payload 0/imm32
    16713     c7 0/subop/copy *_Program-signatures 0/imm32
    16714     c7 0/subop/copy *_Program-signatures->payload 0/imm32
    16715     (clear-stream _test-input-stream)
    16716     (write _test-input-stream "foo n: int {\n")
    16717     # var result/ecx: function
    16718     2b/subtract *Function-size 4/r32/esp
    16719     89/<- %ecx 4/r32/esp
    16720     (zero-out %ecx *Function-size)
    16721     # var vars/ebx: (stack live-var 16)
    16722     81 5/subop/subtract %esp 0xc0/imm32
    16723     68/push 0xc0/imm32/size
    16724     68/push 0/imm32/top
    16725     89/<- %ebx 4/r32/esp
    16726     # convert
    16727     (populate-mu-function-header _test-input-stream %ecx %ebx Stderr 0)
    16728     # check result->name
    16729     (lookup *ecx *(ecx+4))  # Function-name Function-name => eax
    16730     (check-strings-equal %eax "foo" "F - test-function-header-with-arg/name")
    16731     # var v/edx: (addr var) = result->inouts->value
    16732     (lookup *(ecx+8) *(ecx+0xc))  # Function-inouts Function-inouts => eax
    16733     (lookup *eax *(eax+4))  # List-value List-value => eax
    16734     89/<- %edx 0/r32/eax
    16735     # check v->name
    16736     (lookup *edx *(edx+4))  # Var-name Var-name => eax
    16737     (check-strings-equal %eax "n" "F - test-function-header-with-arg/inout:0")
    16738     # check v->type
    16739     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
    16740     (check-ints-equal *eax 1 "F - test-function-header-with-arg/inout:0/type:0")  # Type-tree-is-atom
    16741     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-arg/inout:0/type:1")  # Type-tree-value
    16742     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-arg/inout:0/type:2")  # Type-tree-right
    16743     # . epilogue
    16744     89/<- %esp 5/r32/ebp
    16745     5d/pop-to-ebp
    16746     c3/return
    16747
    16748 test-function-header-with-multiple-args:
    16749     # . prologue
    16750     55/push-ebp
    16751     89/<- %ebp 4/r32/esp
    16752     # setup
    16753     8b/-> *Primitive-type-ids 0/r32/eax
    16754     89/<- *Type-id 0/r32/eax  # stream-write
    16755     c7 0/subop/copy *_Program-functions 0/imm32
    16756     c7 0/subop/copy *_Program-functions->payload 0/imm32
    16757     c7 0/subop/copy *_Program-types 0/imm32
    16758     c7 0/subop/copy *_Program-types->payload 0/imm32
    16759     c7 0/subop/copy *_Program-signatures 0/imm32
    16760     c7 0/subop/copy *_Program-signatures->payload 0/imm32
    16761     (clear-stream _test-input-stream)
    16762     (write _test-input-stream "foo a: int, b: int c: int {\n")
    16763     # result/ecx: function
    16764     2b/subtract *Function-size 4/r32/esp
    16765     89/<- %ecx 4/r32/esp
    16766     (zero-out %ecx *Function-size)
    16767     # var vars/ebx: (stack live-var 16)
    16768     81 5/subop/subtract %esp 0xc0/imm32
    16769     68/push 0xc0/imm32/size
    16770     68/push 0/imm32/top
    16771     89/<- %ebx 4/r32/esp
    16772     # convert
    16773     (populate-mu-function-header _test-input-stream %ecx %ebx Stderr 0)
    16774     # check result->name
    16775     (lookup *ecx *(ecx+4))  # Function-name Function-name => eax
    16776     (check-strings-equal %eax "foo" "F - test-function-header-with-multiple-args/name")
    16777     # var inouts/edx: (addr list var) = lookup(result->inouts)
    16778     (lookup *(ecx+8) *(ecx+0xc))  # Function-inouts Function-inouts => eax
    16779     89/<- %edx 0/r32/eax
    16780 $test-function-header-with-multiple-args:inout0:
    16781     # var v/ebx: (addr var) = lookup(inouts->value)
    16782     (lookup *edx *(edx+4))  # List-value List-value => eax
    16783     89/<- %ebx 0/r32/eax
    16784     # check v->name
    16785     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
    16786     (check-strings-equal %eax "a" "F - test-function-header-with-multiple-args/inout:0")  # Var-name
    16787     # check v->type
    16788     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
    16789     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args/inout:0/type:0")  # Type-tree-is-atom
    16790     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args/inout:0/type:1")  # Type-tree-value
    16791     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args/inout:0/type:2")  # Type-tree-right
    16792 $test-function-header-with-multiple-args:inout1:
    16793     # inouts = lookup(inouts->next)
    16794     (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
    16795     89/<- %edx 0/r32/eax
    16796     # v = lookup(inouts->value)
    16797     (lookup *edx *(edx+4))  # List-value List-value => eax
    16798     89/<- %ebx 0/r32/eax
    16799     # check v->name
    16800     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
    16801     (check-strings-equal %eax "b" "F - test-function-header-with-multiple-args/inout:1")  # Var-name
    16802     # check v->type
    16803     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
    16804     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args/inout:1/type:0")  # Type-tree-is-atom
    16805     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args/inout:1/type:1")  # Type-tree-value
    16806     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args/inout:1/type:2")  # Type-tree-right
    16807 $test-function-header-with-multiple-args:inout2:
    16808     # inouts = lookup(inouts->next)
    16809     (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
    16810     89/<- %edx 0/r32/eax
    16811     # v = lookup(inouts->value)
    16812     (lookup *edx *(edx+4))  # List-value List-value => eax
    16813     89/<- %ebx 0/r32/eax
    16814     # check v->name
    16815     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
    16816     (check-strings-equal %eax "c" "F - test-function-header-with-multiple-args/inout:2")  # Var-name
    16817     # check v->type
    16818     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
    16819     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args/inout:2/type:0")  # Type-tree-is-atom
    16820     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args/inout:2/type:1")  # Type-tree-value
    16821     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args/inout:2/type:2")  # Type-tree-right
    16822     # . epilogue
    16823     89/<- %esp 5/r32/ebp
    16824     5d/pop-to-ebp
    16825     c3/return
    16826
    16827 test-function-header-with-multiple-args-and-outputs:
    16828     # . prologue
    16829     55/push-ebp
    16830     89/<- %ebp 4/r32/esp
    16831     # setup
    16832     8b/-> *Primitive-type-ids 0/r32/eax
    16833     89/<- *Type-id 0/r32/eax  # stream-write
    16834     c7 0/subop/copy *_Program-functions 0/imm32
    16835     c7 0/subop/copy *_Program-functions->payload 0/imm32
    16836     c7 0/subop/copy *_Program-types 0/imm32
    16837     c7 0/subop/copy *_Program-types->payload 0/imm32
    16838     c7 0/subop/copy *_Program-signatures 0/imm32
    16839     c7 0/subop/copy *_Program-signatures->payload 0/imm32
    16840     (clear-stream _test-input-stream)
    16841     (write _test-input-stream "foo a: int, b: int, c: int -> _/ecx: int _/edx: int {\n")
    16842     # result/ecx: function
    16843     2b/subtract *Function-size 4/r32/esp
    16844     89/<- %ecx 4/r32/esp
    16845     (zero-out %ecx *Function-size)
    16846     # var vars/ebx: (stack live-var 16)
    16847     81 5/subop/subtract %esp 0xc0/imm32
    16848     68/push 0xc0/imm32/size
    16849     68/push 0/imm32/top
    16850     89/<- %ebx 4/r32/esp
    16851     # convert
    16852     (populate-mu-function-header _test-input-stream %ecx %ebx Stderr 0)
    16853     # check result->name
    16854     (lookup *ecx *(ecx+4))  # Function-name Function-name => eax
    16855     (check-strings-equal %eax "foo" "F - test-function-header-with-multiple-args-and-outputs/name")
    16856     # var inouts/edx: (addr list var) = lookup(result->inouts)
    16857     (lookup *(ecx+8) *(ecx+0xc))  # Function-inouts Function-inouts => eax
    16858     89/<- %edx 0/r32/eax
    16859 $test-function-header-with-multiple-args-and-outputs:inout0:
    16860     # var v/ebx: (addr var) = lookup(inouts->value)
    16861     (lookup *edx *(edx+4))  # List-value List-value => eax
    16862     89/<- %ebx 0/r32/eax
    16863     # check v->name
    16864     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
    16865     (check-strings-equal %eax "a" "F - test-function-header-with-multiple-args-and-outputs/inout:0")
    16866     # check v->type
    16867     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
    16868     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args-and-outputs/inout:0/type:0")  # Type-tree-is-atom
    16869     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args-and-outputs/inout:0/type:1")  # Type-tree-value
    16870     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args-and-outputs/inout:0/type:2")  # Type-tree-right
    16871 $test-function-header-with-multiple-args-and-outputs:inout1:
    16872     # inouts = lookup(inouts->next)
    16873     (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
    16874     89/<- %edx 0/r32/eax
    16875     # v = lookup(inouts->value)
    16876     (lookup *edx *(edx+4))  # List-value List-value => eax
    16877     89/<- %ebx 0/r32/eax
    16878     # check v->name
    16879     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
    16880     (check-strings-equal %eax "b" "F - test-function-header-with-multiple-args-and-outputs/inout:1")
    16881     # check v->type
    16882     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
    16883     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args-and-outputs/inout:1/type:0")  # Type-tree-is-atom
    16884     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args-and-outputs/inout:1/type:1")  # Type-tree-value
    16885     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args-and-outputs/inout:1/type:2")  # Type-tree-right
    16886 $test-function-header-with-multiple-args-and-outputs:inout2:
    16887     # inouts = lookup(inouts->next)
    16888     (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
    16889     89/<- %edx 0/r32/eax
    16890     # v = lookup(inouts->value)
    16891     (lookup *edx *(edx+4))  # List-value List-value => eax
    16892     89/<- %ebx 0/r32/eax
    16893     # check v->name
    16894     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
    16895     (check-strings-equal %eax "c" "F - test-function-header-with-multiple-args-and-outputs/inout:2")
    16896     # check v->type
    16897     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
    16898     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args-and-outputs/inout:2/type:0")  # Type-tree-is-atom
    16899     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args-and-outputs/inout:2/type:1")  # Type-tree-value
    16900     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args-and-outputs/inout:2/type:2")  # Type-tree-right
    16901 $test-function-header-with-multiple-args-and-outputs:out0:
    16902     # var outputs/edx: (addr list var) = lookup(result->outputs)
    16903     (lookup *(ecx+0x10) *(ecx+0x14))  # Function-outputs Function-outputs => eax
    16904     89/<- %edx 0/r32/eax
    16905     # v = lookup(outputs->value)
    16906     (lookup *edx *(edx+4))  # List-value List-value => eax
    16907     89/<- %ebx 0/r32/eax
    16908     # check v->name
    16909     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
    16910     (check-strings-equal %eax "_" "F - test-function-header-with-multiple-args-and-outputs/output:0")
    16911     # check v->register
    16912     (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
    16913     (check-strings-equal %eax "ecx" "F - test-function-header-with-multiple-args-and-outputs/output:0/register")
    16914     # check v->type
    16915     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
    16916     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args-and-outputs/output:0/type:0")  # Type-tree-is-atom
    16917     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args-and-outputs/output:0/type:1")  # Type-tree-value
    16918     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args-and-outputs/output:0/type:2")  # Type-tree-right
    16919 $test-function-header-with-multiple-args-and-outputs:out1:
    16920     # outputs = lookup(outputs->next)
    16921     (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
    16922     89/<- %edx 0/r32/eax
    16923     # v = lookup(inouts->value)
    16924     (lookup *edx *(edx+4))  # List-value List-value => eax
    16925     89/<- %ebx 0/r32/eax
    16926     # check v->name
    16927     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
    16928     (check-strings-equal %eax "_" "F - test-function-header-with-multiple-args-and-outputs/output:1")
    16929     # check v->register
    16930     (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
    16931     (check-strings-equal %eax "edx" "F - test-function-header-with-multiple-args-and-outputs/output:1/register")
    16932     # check v->type
    16933     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
    16934     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args-and-outputs/output:1/type:0")  # Type-tree-is-atom
    16935     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args-and-outputs/output:1/type:1")  # Type-tree-value
    16936     (check-ints-equal *(eax+0c) 0 "F - test-function-header-with-multiple-args-and-outputs/output:1/type:2")  # Type-tree-right
    16937     # . epilogue
    16938     89/<- %esp 5/r32/ebp
    16939     5d/pop-to-ebp
    16940     c3/return
    16941
    16942 # format for variables with types
    16943 #   x: int
    16944 #   x: int,
    16945 #   x/eax: int
    16946 #   x/eax: int,
    16947 # ignores at most one trailing comma
    16948 # does not support other, non-register metadata
    16949 # WARNING: modifies name
    16950 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)
    16951     # pseudocode:
    16952     #   var s: slice
    16953     #   if (!slice-ends-with(name, ":"))
    16954     #     abort
    16955     #   --name->end to skip ':'
    16956     #   next-token-from-slice(name->start, name->end, '/', s)
    16957     #   new-var-from-slice(s, out)
    16958     #   ## register
    16959     #   next-token-from-slice(s->end, name->end, '/', s)
    16960     #   if (!slice-empty?(s))
    16961     #     out->register = slice-to-string(s)
    16962     #   ## type
    16963     #   var type: (handle type-tree) = parse-type(first-line)
    16964     #   out->type = type
    16965     #
    16966     # . prologue
    16967     55/push-ebp
    16968     89/<- %ebp 4/r32/esp
    16969     # . save registers
    16970     50/push-eax
    16971     51/push-ecx
    16972     52/push-edx
    16973     53/push-ebx
    16974     56/push-esi
    16975     57/push-edi
    16976     # esi = name
    16977     8b/-> *(ebp+8) 6/r32/esi
    16978     # if (!slice-ends-with?(name, ":")) abort
    16979     8b/-> *(esi+4) 1/r32/ecx  # Slice-end
    16980     49/decrement-ecx
    16981     8a/copy-byte *ecx 1/r32/CL
    16982     81 4/subop/and %ecx 0xff/imm32
    16983     81 7/subop/compare %ecx 0x3a/imm32/colon
    16984     0f 85/jump-if-!= $parse-var-with-type:abort/disp32
    16985     # --name->end to skip ':'
    16986     ff 1/subop/decrement *(esi+4)
    16987     # var s/ecx: slice
    16988     68/push 0/imm32/end
    16989     68/push 0/imm32/start
    16990     89/<- %ecx 4/r32/esp
    16991 $parse-var-with-type:parse-name:
    16992     (next-token-from-slice *esi *(esi+4) 0x2f %ecx)  # Slice-start, Slice-end, '/'
    16993 $parse-var-with-type:create-var:
    16994     # new-var-from-slice(s, out)
    16995     (new-var-from-slice Heap %ecx *(ebp+0x10))
    16996     # save out->register
    16997 $parse-var-with-type:save-register:
    16998     # . var out-addr/edi: (addr var) = lookup(*out)
    16999     8b/-> *(ebp+0x10) 7/r32/edi
    17000     (lookup *edi *(edi+4))  # => eax
    17001     89/<- %edi 0/r32/eax
    17002     # . s = next-token(...)
    17003     (next-token-from-slice *(ecx+4) *(esi+4) 0x2f %ecx)  # s->end, name->end, '/'
    17004     # . if (!slice-empty?(s)) out->register = slice-to-string(s)
    17005     {
    17006 $parse-var-with-type:write-register:
    17007       (slice-empty? %ecx)  # => eax
    17008       3d/compare-eax-and 0/imm32/false
    17009       75/jump-if-!= break/disp8
    17010       # out->register = slice-to-string(s)
    17011       8d/copy-address *(edi+0x18) 0/r32/eax  # Var-register
    17012       (slice-to-string Heap %ecx %eax)
    17013     }
    17014 $parse-var-with-type:save-type:
    17015     8d/copy-address *(edi+8) 0/r32/eax  # Var-type
    17016     (parse-type Heap *(ebp+0xc) %eax *(ebp+0x18) *(ebp+0x1c))
    17017 $parse-var-with-type:check-register:
    17018     (lookup *(edi+0x18) *(edi+0x1c))  # Var-register Var-register => eax
    17019     3d/compare-eax-and 0/imm32
    17020     74/jump-if-= $parse-var-with-type:end/disp8
    17021     (float-register? %eax)  # => eax
    17022     {
    17023       3d/compare-eax-and 0/imm32/false
    17024       74/jump-if-= break/disp8
    17025       # var is in a float register; ensure type is float
    17026       (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
    17027       (simple-mu-type? %eax 0xf)  # float => eax
    17028       3d/compare-eax-and 0/imm32/false
    17029       0f 84/jump-if-= $parse-var-with-type:error-non-float-in-floating-point-register/disp32
    17030       eb/jump $parse-var-with-type:end/disp8
    17031     }
    17032     # var is not in a float register; ensure type is not float
    17033     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
    17034     (simple-mu-type? %eax 0xf)  # float => eax
    17035     3d/compare-eax-and 0/imm32/false
    17036     0f 85/jump-if-!= $parse-var-with-type:error-float-in-integer-register/disp32
    17037 $parse-var-with-type:end:
    17038     # . reclaim locals
    17039     81 0/subop/add %esp 8/imm32
    17040     # . restore registers
    17041     5f/pop-to-edi
    17042     5e/pop-to-esi
    17043     5b/pop-to-ebx
    17044     5a/pop-to-edx
    17045     59/pop-to-ecx
    17046     58/pop-to-eax
    17047     # . epilogue
    17048     89/<- %esp 5/r32/ebp
    17049     5d/pop-to-ebp
    17050     c3/return
    17051
    17052 $parse-var-with-type:abort:
    17053     # error("fn " fn ": var should have form 'name: type' in '" line "'\n")
    17054     (write-buffered *(ebp+0x18) "fn ")
    17055     (write-buffered *(ebp+0x18) *(ebp+0x14))
    17056     (write-buffered *(ebp+0x18) ": var should have form 'name: type' in '")
    17057     (flush *(ebp+0x18))
    17058     (rewind-stream *(ebp+0xc))
    17059     (write-stream-data *(ebp+0x18) *(ebp+0xc))
    17060     (write-buffered *(ebp+0x18) "'\n")
    17061     (flush *(ebp+0x18))
    17062     (stop *(ebp+0x1c) 1)
    17063     # never gets here
    17064
    17065 $parse-var-with-type:error-float-in-integer-register:
    17066     # error("fn " fn ": float var '" var "' should be in a floating-point register\n")
    17067     (write-buffered *(ebp+0x18) "fn ")
    17068     (write-buffered *(ebp+0x18) *(ebp+0x14))
    17069     (write-buffered *(ebp+0x18) ": float var '")
    17070     (lookup *edi *(edi+4))  # Var-name Var-name => eax
    17071     (write-buffered *(ebp+0x18) %eax)
    17072     (write-buffered *(ebp+0x18) "' should be in a floating-point register\n")
    17073     (flush *(ebp+0x18))
    17074     (stop *(ebp+0x1c) 1)
    17075     # never gets here
    17076
    17077 $parse-var-with-type:error-non-float-in-floating-point-register:
    17078     # error("fn " fn ": non-float var '" var "' should be in an integer register\n")
    17079     (write-buffered *(ebp+0x18) "fn ")
    17080     (write-buffered *(ebp+0x18) *(ebp+0x14))
    17081     (write-buffered *(ebp+0x18) ": non-float var '")
    17082     (lookup *edi *(edi+4))  # Var-name Var-name => eax
    17083     (write-buffered *(ebp+0x18) %eax)
    17084     (write-buffered *(ebp+0x18) "' should be in an integer register\n")
    17085     (flush *(ebp+0x18))
    17086     (stop *(ebp+0x1c) 1)
    17087     # never gets here
    17088
    17089 float-register?:  # r: (addr array byte) -> result/eax: boolean
    17090     # . prologue
    17091     55/push-ebp
    17092     89/<- %ebp 4/r32/esp
    17093     #
    17094     (get Mu-registers-unique *(ebp+8) 0xc "Mu-registers-unique")  # => eax
    17095     81 7/subop/compare *eax 8/imm32/start-of-floating-point-registers
    17096     0f 9d/set-if->= %al
    17097     25/and-eax-with 0xff/imm32
    17098 $float-register?:end:
    17099     # . epilogue
    17100     89/<- %esp 5/r32/ebp
    17101     5d/pop-to-ebp
    17102     c3/return
    17103
    17104 parse-type:  # ad: (addr allocation-descriptor), in: (addr stream byte), out: (addr handle type-tree), err: (addr buffered-file), ed: (addr exit-descriptor)
    17105     # pseudocode:
    17106     #   var s: slice = next-mu-token(in)
    17107     #   assert s != ""
    17108     #   assert s != "->"
    17109     #   assert s != "{"
    17110     #   assert s != "}"
    17111     #   if s == ")"
    17112     #     return
    17113     #   out = allocate(Type-tree)
    17114     #   if s != "("
    17115     #     HACK: if s is an int, parse and return it
    17116     #     out->is-atom? = true
    17117     #     if (s[0] == "_")
    17118     #       out->value = type-parameter
    17119     #       out->parameter-name = slice-to-string(ad, s)
    17120     #     else
    17121     #       out->value = pos-or-insert-slice(Type-id, s)
    17122     #     return
    17123     #   out->left = parse-type(ad, in)
    17124     #   out->right = parse-type-tree(ad, in)
    17125     #
    17126     # . prologue
    17127     55/push-ebp
    17128     89/<- %ebp 4/r32/esp
    17129     # . save registers
    17130     50/push-eax
    17131     51/push-ecx
    17132     52/push-edx
    17133     # clear out
    17134     (zero-out *(ebp+0x10) *Handle-size)
    17135     # var s/ecx: slice
    17136     68/push 0/imm32
    17137     68/push 0/imm32
    17138     89/<- %ecx 4/r32/esp
    17139     # s = next-mu-token(in)
    17140     (next-mu-token *(ebp+0xc) %ecx)
    17141 #?     (write-buffered Stderr "tok: ")
    17142 #?     (write-slice-buffered Stderr %ecx)
    17143 #?     (write-buffered Stderr "$\n")
    17144 #?     (flush Stderr)
    17145     # assert s != ""
    17146     (slice-equal? %ecx "")  # => eax
    17147     3d/compare-eax-and 0/imm32/false
    17148     0f 85/jump-if-!= $parse-type:abort/disp32
    17149     # assert s != "{"
    17150     (slice-equal? %ecx "{")  # => eax
    17151     3d/compare-eax-and 0/imm32/false
    17152     0f 85/jump-if-!= $parse-type:abort/disp32
    17153     # assert s != "}"
    17154     (slice-equal? %ecx "}")  # => eax
    17155     3d/compare-eax-and 0/imm32/false
    17156     0f 85/jump-if-!= $parse-type:abort/disp32
    17157     # assert s != "->"
    17158     (slice-equal? %ecx "->")  # => eax
    17159     3d/compare-eax-and 0/imm32/false
    17160     0f 85/jump-if-!= $parse-type:abort/disp32
    17161     # if (s == ")") return
    17162     (slice-equal? %ecx ")")  # => eax
    17163     3d/compare-eax-and 0/imm32/false
    17164     0f 85/jump-if-!= $parse-type:end/disp32
    17165     # out = new tree
    17166     (allocate *(ebp+8) *Type-tree-size *(ebp+0x10))
    17167     # var out-addr/edx: (addr type-tree) = lookup(*out)
    17168     8b/-> *(ebp+0x10) 2/r32/edx
    17169     (lookup *edx *(edx+4))  # => eax
    17170     89/<- %edx 0/r32/eax
    17171     {
    17172       # if (s != "(") break
    17173       (slice-equal? %ecx "(")  # => eax
    17174       3d/compare-eax-and 0/imm32/false
    17175       0f 85/jump-if-!= break/disp32
    17176       # if s is a number, store it in the type's size field
    17177       {
    17178 $parse-type:check-for-int:
    17179         # var tmp/eax: byte = *s->slice
    17180         8b/-> *ecx 0/r32/eax
    17181         8a/copy-byte *eax 0/r32/AL
    17182         25/and-eax-with 0xff/imm32
    17183         # TODO: raise an error on `var x: (array int a)`
    17184         (decimal-digit? %eax)  # => eax
    17185         3d/compare-eax-and 0/imm32/false
    17186         74/jump-if-= break/disp8
    17187 $parse-type:int:
    17188         # strip out metadata
    17189         (next-token-from-slice *ecx *(ecx+4) 0x2f %ecx)
    17190         #
    17191         (check-mu-hex-int %ecx *(ebp+0x14) *(ebp+0x18))
    17192         (parse-hex-int-from-slice %ecx)  # => eax
    17193         c7 0/subop/copy *(edx+4) 9/imm32/type-id-array-capacity  # Type-tree-value
    17194         89/<- *(edx+8) 0/r32/eax  # Type-tree-value-size
    17195         e9/jump $parse-type:end/disp32
    17196       }
    17197 $parse-type:atom:
    17198       # out->is-atom? = true
    17199       c7 0/subop/copy *edx 1/imm32/true  # Type-tree-is-atom
    17200       {
    17201 $parse-type:check-for-type-parameter:
    17202         # var tmp/eax: byte = *s->slice
    17203         8b/-> *ecx 0/r32/eax
    17204         8a/copy-byte *eax 0/r32/AL
    17205         25/and-eax-with 0xff/imm32
    17206         # if (tmp != '_') break
    17207         3d/compare-eax-and 0x5f/imm32/_
    17208         75/jump-if-!= break/disp8
    17209 $parse-type:type-parameter:
    17210         # out->value = type-parameter
    17211         c7 0/subop/copy *(edx+4) 0xa/imm32/type-parameter  # Type-tree-value
    17212         # out->parameter-name = slice-to-string(ad, s)
    17213         8d/copy-address *(edx+8) 0/r32/eax  # Type-tree-parameter-name
    17214         (slice-to-string *(ebp+8) %ecx %eax)
    17215         e9/jump $parse-type:end/disp32
    17216       }
    17217 $parse-type:non-type-parameter:
    17218       # out->value = pos-or-insert-slice(Type-id, s)
    17219       (pos-or-insert-slice Type-id %ecx)  # => eax
    17220       89/<- *(edx+4) 0/r32/eax  # Type-tree-value
    17221       e9/jump $parse-type:end/disp32
    17222     }
    17223 $parse-type:non-atom:
    17224     # otherwise s == "("
    17225     # out->left = parse-type(ad, in)
    17226     8d/copy-address *(edx+4) 0/r32/eax  # Type-tree-left
    17227     (parse-type *(ebp+8) *(ebp+0xc) %eax *(ebp+0x14) *(ebp+0x18))
    17228     # out->right = parse-type-tree(ad, in)
    17229     8d/copy-address *(edx+0xc) 0/r32/eax  # Type-tree-right
    17230     (parse-type-tree *(ebp+8) *(ebp+0xc) %eax *(ebp+0x14) *(ebp+0x18))
    17231 $parse-type:end:
    17232     # . reclaim locals
    17233     81 0/subop/add %esp 8/imm32
    17234     # . restore registers
    17235     5a/pop-to-edx
    17236     59/pop-to-ecx
    17237     58/pop-to-eax
    17238     # . epilogue
    17239     89/<- %esp 5/r32/ebp
    17240     5d/pop-to-ebp
    17241     c3/return
    17242
    17243 $parse-type:abort:
    17244     # error("unexpected token when parsing type: '" s "'\n")
    17245     (write-buffered *(ebp+0x14) "unexpected token when parsing type: '")
    17246     (write-slice-buffered *(ebp+0x14) %ecx)
    17247     (write-buffered *(ebp+0x14) "'\n")
    17248     (flush *(ebp+0x14))
    17249     (stop *(ebp+0x18) 1)
    17250     # never gets here
    17251
    17252 parse-type-tree:  # ad: (addr allocation-descriptor), in: (addr stream byte), out: (addr handle type-tree), err: (addr buffered-file), ed: (addr exit-descriptor)
    17253     # pseudocode:
    17254     #   var tmp: (handle type-tree) = parse-type(ad, in)
    17255     #   if tmp == 0
    17256     #     return 0
    17257     #   out = allocate(Type-tree)
    17258     #   out->left = tmp
    17259     #   out->right = parse-type-tree(ad, in)
    17260     #
    17261     # . prologue
    17262     55/push-ebp
    17263     89/<- %ebp 4/r32/esp
    17264     # . save registers
    17265     50/push-eax
    17266     51/push-ecx
    17267     52/push-edx
    17268     #
    17269     (zero-out *(ebp+0x10) *Handle-size)
    17270     # var tmp/ecx: (handle type-tree)
    17271     68/push 0/imm32
    17272     68/push 0/imm32
    17273     89/<- %ecx 4/r32/esp
    17274     # tmp = parse-type(ad, in)
    17275     (parse-type *(ebp+8) *(ebp+0xc) %ecx *(ebp+0x14) *(ebp+0x18))
    17276     # if (tmp == 0) return
    17277     81 7/subop/compare *ecx 0/imm32
    17278     74/jump-if-= $parse-type-tree:end/disp8
    17279     # out = new tree
    17280     (allocate *(ebp+8) *Type-tree-size *(ebp+0x10))
    17281     # var out-addr/edx: (addr tree) = lookup(*out)
    17282     8b/-> *(ebp+0x10) 2/r32/edx
    17283     (lookup *edx *(edx+4))  # => eax
    17284     89/<- %edx 0/r32/eax
    17285     # out->left = tmp
    17286     8b/-> *ecx 0/r32/eax
    17287     89/<- *(edx+4) 0/r32/eax  # Type-tree-left
    17288     8b/-> *(ecx+4) 0/r32/eax
    17289     89/<- *(edx+8) 0/r32/eax  # Type-tree-left
    17290     # out->right = parse-type-tree(ad, in)
    17291     8d/copy-address *(edx+0xc) 0/r32/eax  # Type-tree-right
    17292     (parse-type-tree *(ebp+8) *(ebp+0xc) %eax *(ebp+0x14) *(ebp+0x18))
    17293 $parse-type-tree:end:
    17294     # . reclaim locals
    17295     81 0/subop/add %esp 8/imm32
    17296     # . restore registers
    17297     5a/pop-to-edx
    17298     59/pop-to-ecx
    17299     58/pop-to-eax
    17300     # . epilogue
    17301     89/<- %esp 5/r32/ebp
    17302     5d/pop-to-ebp
    17303     c3/return
    17304
    17305 next-mu-token:  # in: (addr stream byte), out: (addr slice)
    17306     # pseudocode:
    17307     # start:
    17308     #   skip-chars-matching-whitespace(in)
    17309     #   if in->read >= in->write              # end of in
    17310     #     out = {0, 0}
    17311     #     return
    17312     #   out->start = &in->data[in->read]
    17313     #   var curr-byte/eax: byte = in->data[in->read]
    17314     #   if curr->byte == ','                  # comment token
    17315     #     ++in->read
    17316     #     goto start
    17317     #   if curr-byte == '#'                   # comment
    17318     #     goto done                             # treat as eof
    17319     #   if curr-byte == '"'                   # string literal
    17320     #     skip-string(in)
    17321     #     goto done                           # no metadata
    17322     #   if curr-byte == '('
    17323     #     ++in->read
    17324     #     goto done
    17325     #   if curr-byte == ')'
    17326     #     ++in->read
    17327     #     goto done
    17328     #   # read a word
    17329     #   while true
    17330     #     if in->read >= in->write
    17331     #       break
    17332     #     curr-byte = in->data[in->read]
    17333     #     if curr-byte == ' '
    17334     #       break
    17335     #     if curr-byte == '\r'
    17336     #       break
    17337     #     if curr-byte == '\n'
    17338     #       break
    17339     #     if curr-byte == '('
    17340     #       break
    17341     #     if curr-byte == ')'
    17342     #       break
    17343     #     if curr-byte == ','
    17344     #       break
    17345     #     ++in->read
    17346     # done:
    17347     #   out->end = &in->data[in->read]
    17348     #
    17349     # . prologue
    17350     55/push-ebp
    17351     89/<- %ebp 4/r32/esp
    17352     # . save registers
    17353     50/push-eax
    17354     51/push-ecx
    17355     56/push-esi
    17356     57/push-edi
    17357     # esi = in
    17358     8b/-> *(ebp+8) 6/r32/esi
    17359     # edi = out
    17360     8b/-> *(ebp+0xc) 7/r32/edi
    17361 $next-mu-token:start:
    17362     (skip-chars-matching-whitespace %esi)
    17363 $next-mu-token:check0:
    17364     # if (in->read >= in->write) return out = {0, 0}
    17365     # . ecx = in->read
    17366     8b/-> *(esi+4) 1/r32/ecx
    17367     # . if (ecx >= in->write) return out = {0, 0}
    17368     3b/compare<- *esi 1/r32/ecx
    17369     c7 0/subop/copy *edi 0/imm32
    17370     c7 0/subop/copy *(edi+4) 0/imm32
    17371     0f 8d/jump-if->= $next-mu-token:end/disp32
    17372     # out->start = &in->data[in->read]
    17373     8d/copy-address *(esi+ecx+0xc) 0/r32/eax
    17374     89/<- *edi 0/r32/eax
    17375     # var curr-byte/eax: byte = in->data[in->read]
    17376     31/xor-with %eax 0/r32/eax
    17377     8a/copy-byte *(esi+ecx+0xc) 0/r32/AL
    17378     {
    17379 $next-mu-token:check-for-comma:
    17380       # if (curr-byte != ',') break
    17381       3d/compare-eax-and 0x2c/imm32/comma
    17382       75/jump-if-!= break/disp8
    17383       # ++in->read
    17384       ff 0/subop/increment *(esi+4)
    17385       # restart
    17386       e9/jump $next-mu-token:start/disp32
    17387     }
    17388     {
    17389 $next-mu-token:check-for-comment:
    17390       # if (curr-byte != '#') break
    17391       3d/compare-eax-and 0x23/imm32/pound
    17392       75/jump-if-!= break/disp8
    17393       # return eof
    17394       e9/jump $next-mu-token:done/disp32
    17395     }
    17396     {
    17397 $next-mu-token:check-for-string-literal:
    17398       # if (curr-byte != '"') break
    17399       3d/compare-eax-and 0x22/imm32/dquote
    17400       75/jump-if-!= break/disp8
    17401       (skip-string %esi)
    17402       # return
    17403       e9/jump $next-mu-token:done/disp32
    17404     }
    17405     {
    17406 $next-mu-token:check-for-open-paren:
    17407       # if (curr-byte != '(') break
    17408       3d/compare-eax-and 0x28/imm32/open-paren
    17409       75/jump-if-!= break/disp8
    17410       # ++in->read
    17411       ff 0/subop/increment *(esi+4)
    17412       # return
    17413       e9/jump $next-mu-token:done/disp32
    17414     }
    17415     {
    17416 $next-mu-token:check-for-close-paren:
    17417       # if (curr-byte != ')') break
    17418       3d/compare-eax-and 0x29/imm32/close-paren
    17419       75/jump-if-!= break/disp8
    17420       # ++in->read
    17421       ff 0/subop/increment *(esi+4)
    17422       # return
    17423       e9/jump $next-mu-token:done/disp32
    17424     }
    17425     {
    17426 $next-mu-token:regular-word-without-metadata:
    17427       # if (in->read >= in->write) break
    17428       # . ecx = in->read
    17429       8b/-> *(esi+4) 1/r32/ecx
    17430       # . if (ecx >= in->write) break
    17431       3b/compare<- *esi 1/r32/ecx
    17432       7d/jump-if->= break/disp8
    17433       # var c/eax: byte = in->data[in->read]
    17434       31/xor-with %eax 0/r32/eax
    17435       8a/copy-byte *(esi+ecx+0xc) 0/r32/AL
    17436       # if (c == ' ') break
    17437       3d/compare-eax-and 0x20/imm32/space
    17438       74/jump-if-= break/disp8
    17439       # if (c == '\r') break
    17440       3d/compare-eax-and 0xd/imm32/carriage-return
    17441       74/jump-if-= break/disp8
    17442       # if (c == '\n') break
    17443       3d/compare-eax-and 0xa/imm32/newline
    17444       74/jump-if-= break/disp8
    17445       # if (c == '(') break
    17446       3d/compare-eax-and 0x28/imm32/open-paren
    17447       0f 84/jump-if-= break/disp32
    17448       # if (c == ')') break
    17449       3d/compare-eax-and 0x29/imm32/close-paren
    17450       0f 84/jump-if-= break/disp32
    17451       # if (c == ',') break
    17452       3d/compare-eax-and 0x2c/imm32/comma
    17453       0f 84/jump-if-= break/disp32
    17454       # ++in->read
    17455       ff 0/subop/increment *(esi+4)
    17456       #
    17457       e9/jump loop/disp32
    17458     }
    17459 $next-mu-token:done:
    17460     # out->end = &in->data[in->read]
    17461     8b/-> *(esi+4) 1/r32/ecx
    17462     8d/copy-address *(esi+ecx+0xc) 0/r32/eax
    17463     89/<- *(edi+4) 0/r32/eax
    17464 $next-mu-token:end:
    17465     # . restore registers
    17466     5f/pop-to-edi
    17467     5e/pop-to-esi
    17468     59/pop-to-ecx
    17469     58/pop-to-eax
    17470     # . epilogue
    17471     89/<- %esp 5/r32/ebp
    17472     5d/pop-to-ebp
    17473     c3/return
    17474
    17475 pos-or-insert-slice:  # arr: (addr stream (addr array byte)), s: (addr slice) -> index/eax: int
    17476     # . prologue
    17477     55/push-ebp
    17478     89/<- %ebp 4/r32/esp
    17479     # if (pos-slice(arr, s) != -1) return it
    17480     (pos-slice *(ebp+8) *(ebp+0xc))  # => eax
    17481     3d/compare-eax-and -1/imm32
    17482     75/jump-if-!= $pos-or-insert-slice:end/disp8
    17483 $pos-or-insert-slice:insert:
    17484     # var s2/eax: (handle array byte)
    17485     68/push 0/imm32
    17486     68/push 0/imm32
    17487     89/<- %eax 4/r32/esp
    17488     (slice-to-string Heap *(ebp+0xc) %eax)
    17489     # throw away alloc-id
    17490     (lookup *eax *(eax+4))  # => eax
    17491     (write-int *(ebp+8) %eax)
    17492     (pos-slice *(ebp+8) *(ebp+0xc))  # => eax
    17493 $pos-or-insert-slice:end:
    17494     # . reclaim locals
    17495     81 0/subop/add %esp 8/imm32
    17496     # . epilogue
    17497     89/<- %esp 5/r32/ebp
    17498     5d/pop-to-ebp
    17499     c3/return
    17500
    17501 # return the index in an array of strings matching 's', -1 if not found
    17502 # index is denominated in elements, not bytes
    17503 pos-slice:  # arr: (addr stream (addr array byte)), s: (addr slice) -> index/eax: int
    17504     # . prologue
    17505     55/push-ebp
    17506     89/<- %ebp 4/r32/esp
    17507     # . save registers
    17508     51/push-ecx
    17509     52/push-edx
    17510     53/push-ebx
    17511     56/push-esi
    17512 #?     (write-buffered Stderr "pos-slice: ")
    17513 #?     (write-slice-buffered Stderr *(ebp+0xc))
    17514 #?     (write-buffered Stderr "\n")
    17515 #?     (flush Stderr)
    17516     # esi = arr
    17517     8b/-> *(ebp+8) 6/r32/esi
    17518     # var index/ecx: int = 0
    17519     b9/copy-to-ecx 0/imm32
    17520     # var curr/edx: (addr (addr array byte)) = arr->data
    17521     8d/copy-address *(esi+0xc) 2/r32/edx
    17522     # var max/ebx: (addr (addr array byte)) = &arr->data[arr->write]
    17523     8b/-> *esi 3/r32/ebx
    17524     8d/copy-address *(esi+ebx+0xc) 3/r32/ebx
    17525     {
    17526 #?       (write-buffered Stderr "  ")
    17527 #?       (write-int32-hex-buffered Stderr %ecx)
    17528 #?       (write-buffered Stderr "\n")
    17529 #?       (flush Stderr)
    17530       # if (curr >= max) return -1
    17531       39/compare %edx 3/r32/ebx
    17532       b8/copy-to-eax -1/imm32
    17533       73/jump-if-addr>= $pos-slice:end/disp8
    17534       # if (slice-equal?(s, *curr)) break
    17535       (slice-equal? *(ebp+0xc) *edx)  # => eax
    17536       3d/compare-eax-and 0/imm32/false
    17537       75/jump-if-!= break/disp8
    17538       # ++index
    17539       41/increment-ecx
    17540       # curr += 4
    17541       81 0/subop/add %edx 4/imm32
    17542       #
    17543       eb/jump loop/disp8
    17544     }
    17545     # return index
    17546     89/<- %eax 1/r32/ecx
    17547 $pos-slice:end:
    17548 #?     (write-buffered Stderr "=> ")
    17549 #?     (write-int32-hex-buffered Stderr %eax)
    17550 #?     (write-buffered Stderr "\n")
    17551     # . restore registers
    17552     5e/pop-to-esi
    17553     5b/pop-to-ebx
    17554     5a/pop-to-edx
    17555     59/pop-to-ecx
    17556     # . epilogue
    17557     89/<- %esp 5/r32/ebp
    17558     5d/pop-to-ebp
    17559     c3/return
    17560
    17561 test-parse-var-with-type:
    17562     # . prologue
    17563     55/push-ebp
    17564     89/<- %ebp 4/r32/esp
    17565     # setup
    17566     8b/-> *Primitive-type-ids 0/r32/eax
    17567     89/<- *Type-id 0/r32/eax  # stream-write
    17568     # (eax..ecx) = "x:"
    17569     b8/copy-to-eax "x:"/imm32
    17570     8b/-> *eax 1/r32/ecx
    17571     8d/copy-address *(eax+ecx+4) 1/r32/ecx
    17572     05/add-to-eax 4/imm32
    17573     # var slice/ecx: slice = {eax, ecx}
    17574     51/push-ecx
    17575     50/push-eax
    17576     89/<- %ecx 4/r32/esp
    17577     # _test-input-stream contains "int"
    17578     (clear-stream _test-input-stream)
    17579     (write _test-input-stream "int")
    17580     # var v/edx: (handle var)
    17581     68/push 0/imm32
    17582     68/push 0/imm32
    17583     89/<- %edx 4/r32/esp
    17584     #
    17585     (parse-var-with-type %ecx _test-input-stream %edx 0 Stderr 0)
    17586     # var v-addr/edx: (addr var) = lookup(v)
    17587     (lookup *edx *(edx+4))  # => eax
    17588     89/<- %edx 0/r32/eax
    17589     # check v-addr->name
    17590     (lookup *edx *(edx+4))  # Var-name Var-name => eax
    17591     (check-strings-equal %eax "x" "F - test-parse-var-with-type/name")
    17592     # check v-addr->type
    17593     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
    17594     (check-ints-equal *eax 1 "F - test-parse-var-with-type/type:0")  # Type-tree-is-atom
    17595     (check-ints-equal *(eax+4) 1 "F - test-parse-var-with-type/type:1")  # Type-tree-value
    17596     (check-ints-equal *(eax+0xc) 0 "F - test-parse-var-with-type/type:2")  # Type-tree-right
    17597     # . epilogue
    17598     89/<- %esp 5/r32/ebp
    17599     5d/pop-to-ebp
    17600     c3/return
    17601
    17602 test-parse-var-with-type-and-register:
    17603     # . prologue
    17604     55/push-ebp
    17605     89/<- %ebp 4/r32/esp
    17606     # setup
    17607     8b/-> *Primitive-type-ids 0/r32/eax
    17608     89/<- *Type-id 0/r32/eax  # stream-write
    17609     # (eax..ecx) = "x/eax:"
    17610     b8/copy-to-eax "x/eax:"/imm32
    17611     8b/-> *eax 1/r32/ecx
    17612     8d/copy-address *(eax+ecx+4) 1/r32/ecx
    17613     05/add-to-eax 4/imm32
    17614     # var slice/ecx: slice = {eax, ecx}
    17615     51/push-ecx
    17616     50/push-eax
    17617     89/<- %ecx 4/r32/esp
    17618     # _test-input-stream contains "int"
    17619     (clear-stream _test-input-stream)
    17620     (write _test-input-stream "int")
    17621     # var v/edx: (handle var)
    17622     68/push 0/imm32
    17623     68/push 0/imm32
    17624     89/<- %edx 4/r32/esp
    17625     #
    17626     (parse-var-with-type %ecx _test-input-stream %edx 0 Stderr 0)
    17627     # var v-addr/edx: (addr var) = lookup(v)
    17628     (lookup *edx *(edx+4))  # => eax
    17629     89/<- %edx 0/r32/eax
    17630     # check v-addr->name
    17631     (lookup *edx *(edx+4))  # Var-name Var-name => eax
    17632     (check-strings-equal %eax "x" "F - test-parse-var-with-type-and-register/name")
    17633     # check v-addr->register
    17634     (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
    17635     (check-strings-equal %eax "eax" "F - test-parse-var-with-type-and-register/register")
    17636     # check v-addr->type
    17637     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
    17638     (check-ints-equal *eax 1 "F - test-parse-var-with-type-and-register/type:0")  # Type-tree-is-atom
    17639     (check-ints-equal *(eax+4) 1 "F - test-parse-var-with-type-and-register/type:1")  # Type-tree-left
    17640     (check-ints-equal *(eax+0xc) 0 "F - test-parse-var-with-type-and-register/type:2")  # Type-tree-right
    17641     # . epilogue
    17642     89/<- %esp 5/r32/ebp
    17643     5d/pop-to-ebp
    17644     c3/return
    17645
    17646 test-parse-var-with-trailing-characters:
    17647     # . prologue
    17648     55/push-ebp
    17649     89/<- %ebp 4/r32/esp
    17650     # setup
    17651     8b/-> *Primitive-type-ids 0/r32/eax
    17652     89/<- *Type-id 0/r32/eax  # stream-write
    17653     # (eax..ecx) = "x:"
    17654     b8/copy-to-eax "x:"/imm32
    17655     8b/-> *eax 1/r32/ecx
    17656     8d/copy-address *(eax+ecx+4) 1/r32/ecx
    17657     05/add-to-eax 4/imm32
    17658     # var slice/ecx: slice = {eax, ecx}
    17659     51/push-ecx
    17660     50/push-eax
    17661     89/<- %ecx 4/r32/esp
    17662     # _test-input-stream contains "int,"
    17663     (clear-stream _test-input-stream)
    17664     (write _test-input-stream "int,")
    17665     # var v/edx: (handle var)
    17666     68/push 0/imm32
    17667     68/push 0/imm32
    17668     89/<- %edx 4/r32/esp
    17669     #
    17670     (parse-var-with-type %ecx _test-input-stream %edx 0 Stderr 0)
    17671     # var v-addr/edx: (addr var) = lookup(v)
    17672     (lookup *edx *(edx+4))  # => eax
    17673     89/<- %edx 0/r32/eax
    17674     # check v-addr->name
    17675     (lookup *edx *(edx+4))  # Var-name Var-name => eax
    17676     (check-strings-equal %eax "x" "F - test-parse-var-with-trailing-characters/name")
    17677     # check v-addr->register
    17678     (check-ints-equal *(edx+0x18) 0 "F - test-parse-var-with-trailing-characters/register")  # Var-register
    17679     # check v-addr->type
    17680     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
    17681     (check-ints-equal *eax 1 "F - test-parse-var-with-trailing-characters/type:0")  # Type-tree-is-atom
    17682     (check-ints-equal *(eax+4) 1 "F - test-parse-var-with-trailing-characters/type:1")  # Type-tree-left
    17683     (check-ints-equal *(eax+0xc) 0 "F - test-parse-var-with-trailing-characters/type:1")  # Type-tree-right
    17684     # . epilogue
    17685     89/<- %esp 5/r32/ebp
    17686     5d/pop-to-ebp
    17687     c3/return
    17688
    17689 test-parse-var-with-register-and-trailing-characters:
    17690     # . prologue
    17691     55/push-ebp
    17692     89/<- %ebp 4/r32/esp
    17693     # setup
    17694     8b/-> *Primitive-type-ids 0/r32/eax
    17695     89/<- *Type-id 0/r32/eax  # stream-write
    17696     # (eax..ecx) = "x/eax:"
    17697     b8/copy-to-eax "x/eax:"/imm32
    17698     8b/-> *eax 1/r32/ecx
    17699     8d/copy-address *(eax+ecx+4) 1/r32/ecx
    17700     05/add-to-eax 4/imm32
    17701     # var slice/ecx: slice = {eax, ecx}
    17702     51/push-ecx
    17703     50/push-eax
    17704     89/<- %ecx 4/r32/esp
    17705     # _test-input-stream contains "int,"
    17706     (clear-stream _test-input-stream)
    17707     (write _test-input-stream "int,")
    17708     # var v/edx: (handle var)
    17709     68/push 0/imm32
    17710     68/push 0/imm32
    17711     89/<- %edx 4/r32/esp
    17712     #
    17713     (parse-var-with-type %ecx _test-input-stream %edx 0 Stderr 0)
    17714     # var v-addr/edx: (addr var) = lookup(v)
    17715     (lookup *edx *(edx+4))  # => eax
    17716     89/<- %edx 0/r32/eax
    17717     # check v-addr->name
    17718     (lookup *edx *(edx+4))  # Var-name Var-name => eax
    17719     (check-strings-equal %eax "x" "F - test-parse-var-with-register-and-trailing-characters/name")
    17720     # check v-addr->register
    17721     (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
    17722     (check-strings-equal %eax "eax" "F - test-parse-var-with-register-and-trailing-characters/register")
    17723     # check v-addr->type
    17724     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
    17725     (check-ints-equal *eax 1 "F - test-parse-var-with-register-and-trailing-characters/type:0")  # Type-tree-is-atom
    17726     (check-ints-equal *(eax+4) 1 "F - test-parse-var-with-register-and-trailing-characters/type:1")  # Type-tree-left
    17727     (check-ints-equal *(eax+0xc) 0 "F - test-parse-var-with-register-and-trailing-characters/type:2")  # Type-tree-right
    17728     # . epilogue
    17729     89/<- %esp 5/r32/ebp
    17730     5d/pop-to-ebp
    17731     c3/return
    17732
    17733 test-parse-var-with-compound-type:
    17734     # . prologue
    17735     55/push-ebp
    17736     89/<- %ebp 4/r32/esp
    17737     # setup
    17738     8b/-> *Primitive-type-ids 0/r32/eax
    17739     89/<- *Type-id 0/r32/eax  # stream-write
    17740     # (eax..ecx) = "x:"
    17741     b8/copy-to-eax "x:"/imm32
    17742     8b/-> *eax 1/r32/ecx
    17743     8d/copy-address *(eax+ecx+4) 1/r32/ecx
    17744     05/add-to-eax 4/imm32
    17745     # var slice/ecx: slice = {eax, ecx}
    17746     51/push-ecx
    17747     50/push-eax
    17748     89/<- %ecx 4/r32/esp
    17749     # _test-input-stream contains "(addr int)"
    17750     (clear-stream _test-input-stream)
    17751     (write _test-input-stream "(addr int)")
    17752     # var v/edx: (handle var)
    17753     68/push 0/imm32
    17754     68/push 0/imm32
    17755     89/<- %edx 4/r32/esp
    17756     #
    17757     (parse-var-with-type %ecx _test-input-stream %edx 0 Stderr 0)
    17758     # var v-addr/edx: (addr var) = lookup(v)
    17759     (lookup *edx *(edx+4))  # => eax
    17760     89/<- %edx 0/r32/eax
    17761     # check v-addr->name
    17762     (lookup *edx *(edx+4))  # Var-name Var-name => eax
    17763     (check-strings-equal %eax "x" "F - test-parse-var-with-compound-type/name")
    17764     # check v-addr->register
    17765     (check-ints-equal *(edx+0x18) 0 "F - test-parse-var-with-compound-type/register")  # Var-register
    17766     # - check v-addr->type
    17767     # var type/edx: (addr type-tree) = var->type
    17768     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
    17769     89/<- %edx 0/r32/eax
    17770     # type is a non-atom
    17771     (check-ints-equal *edx 0 "F - test-parse-var-with-compound-type/type:0")  # Type-tree-is-atom
    17772     # type->left == atom(addr)
    17773     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
    17774     (check-ints-equal *eax 1 "F - test-parse-var-with-compound-type/type:1")  # Type-tree-is-atom
    17775     (check-ints-equal *(eax+4) 2 "F - test-parse-var-with-compound-type/type:2")  # Type-tree-value
    17776     # type->right->left == atom(int)
    17777     (lookup *(edx+0xc) *(edx+0x10))  # Type-tree-right Type-tree-right => eax
    17778     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    17779     (check-ints-equal *eax 1 "F - test-parse-var-with-compound-type/type:3")  # Type-tree-is-atom
    17780     (check-ints-equal *(eax+4) 1 "F - test-parse-var-with-compound-type/type:4")  # Type-tree-value
    17781     # type->right->right == null
    17782     (check-ints-equal *(eax+0xc) 0 "F - test-parse-var-with-compound-type/type:5")  # Type-tree-right
    17783     # . epilogue
    17784     89/<- %esp 5/r32/ebp
    17785     5d/pop-to-ebp
    17786     c3/return
    17787
    17788 # identifier starts with a letter or '$' or '_'
    17789 # no constraints at the moment on later letters
    17790 # all we really want to do so far is exclude '{', '}' and '->'
    17791 identifier?:  # in: (addr slice) -> result/eax: boolean
    17792     # . prologue
    17793     55/push-ebp
    17794     89/<- %ebp 4/r32/esp
    17795     # if (slice-empty?(in)) return false
    17796     (slice-empty? *(ebp+8))  # => eax
    17797     3d/compare-eax-and 0/imm32/false
    17798     75/jump-if-!= $identifier?:false/disp8
    17799     # var c/eax: byte = *in->start
    17800     8b/-> *(ebp+8) 0/r32/eax
    17801     8b/-> *eax 0/r32/eax
    17802     8a/copy-byte *eax 0/r32/AL
    17803     25/and-eax-with 0xff/imm32
    17804     # if (c == '$') return true
    17805     3d/compare-eax-and 0x24/imm32/$
    17806     74/jump-if-= $identifier?:true/disp8
    17807     # if (c == '_') return true
    17808     3d/compare-eax-and 0x5f/imm32/_
    17809     74/jump-if-= $identifier?:true/disp8
    17810     # drop case
    17811     25/and-eax-with 0x5f/imm32
    17812     # if (c < 'A') return false
    17813     3d/compare-eax-and 0x41/imm32/A
    17814     7c/jump-if-< $identifier?:false/disp8
    17815     # if (c > 'Z') return false
    17816     3d/compare-eax-and 0x5a/imm32/Z
    17817     7f/jump-if-> $identifier?:false/disp8
    17818     # otherwise return true
    17819 $identifier?:true:
    17820     b8/copy-to-eax 1/imm32/true
    17821     eb/jump $identifier?:end/disp8
    17822 $identifier?:false:
    17823     b8/copy-to-eax 0/imm32/false
    17824 $identifier?:end:
    17825     # . epilogue
    17826     89/<- %esp 5/r32/ebp
    17827     5d/pop-to-ebp
    17828     c3/return
    17829
    17830 test-is-identifier-dollar:
    17831     # . prologue
    17832     55/push-ebp
    17833     89/<- %ebp 4/r32/esp
    17834     # (eax..ecx) = "$a"
    17835     b8/copy-to-eax "$a"/imm32
    17836     8b/-> *eax 1/r32/ecx
    17837     8d/copy-address *(eax+ecx+4) 1/r32/ecx
    17838     05/add-to-eax 4/imm32
    17839     # var slice/ecx: slice = {eax, ecx}
    17840     51/push-ecx
    17841     50/push-eax
    17842     89/<- %ecx 4/r32/esp
    17843     #
    17844     (identifier? %ecx)
    17845     (check-ints-equal %eax 1 "F - test-is-identifier-dollar")
    17846     # . epilogue
    17847     89/<- %esp 5/r32/ebp
    17848     5d/pop-to-ebp
    17849     c3/return
    17850
    17851 test-is-identifier-underscore:
    17852     # . prologue
    17853     55/push-ebp
    17854     89/<- %ebp 4/r32/esp
    17855     # (eax..ecx) = "_a"
    17856     b8/copy-to-eax "_a"/imm32
    17857     8b/-> *eax 1/r32/ecx
    17858     8d/copy-address *(eax+ecx+4) 1/r32/ecx
    17859     05/add-to-eax 4/imm32
    17860     # var slice/ecx: slice = {eax, ecx}
    17861     51/push-ecx
    17862     50/push-eax
    17863     89/<- %ecx 4/r32/esp
    17864     #
    17865     (identifier? %ecx)
    17866     (check-ints-equal %eax 1 "F - test-is-identifier-underscore")
    17867     # . epilogue
    17868     89/<- %esp 5/r32/ebp
    17869     5d/pop-to-ebp
    17870     c3/return
    17871
    17872 test-is-identifier-a:
    17873     # . prologue
    17874     55/push-ebp
    17875     89/<- %ebp 4/r32/esp
    17876     # (eax..ecx) = "a$"
    17877     b8/copy-to-eax "a$"/imm32
    17878     8b/-> *eax 1/r32/ecx
    17879     8d/copy-address *(eax+ecx+4) 1/r32/ecx
    17880     05/add-to-eax 4/imm32
    17881     # var slice/ecx: slice = {eax, ecx}
    17882     51/push-ecx
    17883     50/push-eax
    17884     89/<- %ecx 4/r32/esp
    17885     #
    17886     (identifier? %ecx)
    17887     (check-ints-equal %eax 1 "F - test-is-identifier-a")
    17888     # . epilogue
    17889     89/<- %esp 5/r32/ebp
    17890     5d/pop-to-ebp
    17891     c3/return
    17892
    17893 test-is-identifier-z:
    17894     # . prologue
    17895     55/push-ebp
    17896     89/<- %ebp 4/r32/esp
    17897     # (eax..ecx) = "z$"
    17898     b8/copy-to-eax "z$"/imm32
    17899     8b/-> *eax 1/r32/ecx
    17900     8d/copy-address *(eax+ecx+4) 1/r32/ecx
    17901     05/add-to-eax 4/imm32
    17902     # var slice/ecx: slice = {eax, ecx}
    17903     51/push-ecx
    17904     50/push-eax
    17905     89/<- %ecx 4/r32/esp
    17906     #
    17907     (identifier? %ecx)
    17908     (check-ints-equal %eax 1 "F - test-is-identifier-z")
    17909     # . epilogue
    17910     89/<- %esp 5/r32/ebp
    17911     5d/pop-to-ebp
    17912     c3/return
    17913
    17914 test-is-identifier-A:
    17915     # . prologue
    17916     55/push-ebp
    17917     89/<- %ebp 4/r32/esp
    17918     # (eax..ecx) = "A$"
    17919     b8/copy-to-eax "A$"/imm32
    17920     8b/-> *eax 1/r32/ecx
    17921     8d/copy-address *(eax+ecx+4) 1/r32/ecx
    17922     05/add-to-eax 4/imm32
    17923     # var slice/ecx: slice = {eax, ecx}
    17924     51/push-ecx
    17925     50/push-eax
    17926     89/<- %ecx 4/r32/esp
    17927     #
    17928     (identifier? %ecx)
    17929     (check-ints-equal %eax 1 "F - test-is-identifier-A")
    17930     # . epilogue
    17931     89/<- %esp 5/r32/ebp
    17932     5d/pop-to-ebp
    17933     c3/return
    17934
    17935 test-is-identifier-Z:
    17936     # . prologue
    17937     55/push-ebp
    17938     89/<- %ebp 4/r32/esp
    17939     # (eax..ecx) = "Z$"
    17940     b8/copy-to-eax "Z$"/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 1 "F - test-is-identifier-Z")
    17951     # . epilogue
    17952     89/<- %esp 5/r32/ebp
    17953     5d/pop-to-ebp
    17954     c3/return
    17955
    17956 test-is-identifier-at:
    17957     # character before 'A' 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-square-bracket:
    17979     # character after 'Z' 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-@")
    17995     # . epilogue
    17996     89/<- %esp 5/r32/ebp
    17997     5d/pop-to-ebp
    17998     c3/return
    17999
    18000 test-is-identifier-backtick:
    18001     # character before 'a' is invalid
    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-backtick")
    18017     # . epilogue
    18018     89/<- %esp 5/r32/ebp
    18019     5d/pop-to-ebp
    18020     c3/return
    18021
    18022 test-is-identifier-curly-brace-open:
    18023     # character after 'z' is invalid; also used for blocks
    18024     # . prologue
    18025     55/push-ebp
    18026     89/<- %ebp 4/r32/esp
    18027     # (eax..ecx) = "{a"
    18028     b8/copy-to-eax "{a"/imm32
    18029     8b/-> *eax 1/r32/ecx
    18030     8d/copy-address *(eax+ecx+4) 1/r32/ecx
    18031     05/add-to-eax 4/imm32
    18032     # var slice/ecx: slice = {eax, ecx}
    18033     51/push-ecx
    18034     50/push-eax
    18035     89/<- %ecx 4/r32/esp
    18036     #
    18037     (identifier? %ecx)
    18038     (check-ints-equal %eax 0 "F - test-is-identifier-curly-brace-open")
    18039     # . epilogue
    18040     89/<- %esp 5/r32/ebp
    18041     5d/pop-to-ebp
    18042     c3/return
    18043
    18044 test-is-identifier-curly-brace-close:
    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-curly-brace-close")
    18060     # . epilogue
    18061     89/<- %esp 5/r32/ebp
    18062     5d/pop-to-ebp
    18063     c3/return
    18064
    18065 test-is-identifier-hyphen:
    18066     # disallow leading '-' since '->' has special meaning
    18067     # . prologue
    18068     55/push-ebp
    18069     89/<- %ebp 4/r32/esp
    18070     # (eax..ecx) = "-a"
    18071     b8/copy-to-eax "-a"/imm32
    18072     8b/-> *eax 1/r32/ecx
    18073     8d/copy-address *(eax+ecx+4) 1/r32/ecx
    18074     05/add-to-eax 4/imm32
    18075     # var slice/ecx: slice = {eax, ecx}
    18076     51/push-ecx
    18077     50/push-eax
    18078     89/<- %ecx 4/r32/esp
    18079     #
    18080     (identifier? %ecx)
    18081     (check-ints-equal %eax 0 "F - test-is-identifier-hyphen")
    18082     # . epilogue
    18083     89/<- %esp 5/r32/ebp
    18084     5d/pop-to-ebp
    18085     c3/return
    18086
    18087 populate-mu-function-body:  # in: (addr buffered-file), out: (addr function), vars: (addr stack live-var), err: (addr buffered-file), ed: (addr exit-descriptor)
    18088     # . prologue
    18089     55/push-ebp
    18090     89/<- %ebp 4/r32/esp
    18091     # . save registers
    18092     50/push-eax
    18093     56/push-esi
    18094     57/push-edi
    18095     # esi = in
    18096     8b/-> *(ebp+8) 6/r32/esi
    18097     # edi = out
    18098     8b/-> *(ebp+0xc) 7/r32/edi
    18099     # initialize some global state
    18100     c7 0/subop/copy *Curr-block-depth 1/imm32
    18101     # parse-mu-block(in, vars, out, out->body)
    18102     8d/copy-address *(edi+0x18) 0/r32/eax  # Function-body
    18103     (parse-mu-block %esi *(ebp+0x10) %edi %eax *(ebp+0x14) *(ebp+0x18))
    18104 $populate-mu-function-body:end:
    18105     # . restore registers
    18106     5f/pop-to-edi
    18107     5e/pop-to-esi
    18108     58/pop-to-eax
    18109     # . epilogue
    18110     89/<- %esp 5/r32/ebp
    18111     5d/pop-to-ebp
    18112     c3/return
    18113
    18114 # parses a block, assuming that the leading '{' has already been read by the caller
    18115 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)
    18116     # pseudocode:
    18117     #   var line: (stream byte 512)
    18118     #   var word-slice: slice
    18119     #   allocate(Heap, Stmt-size, out)
    18120     #   var out-addr: (addr block) = lookup(*out)
    18121     #   out-addr->tag = 0/block
    18122     #   out-addr->var = some unique name
    18123     #   push(vars, {out-addr->var, false})
    18124     #   while true                                  # line loop
    18125     #     clear-stream(line)
    18126     #     read-line-buffered(in, line)
    18127     #     if (line->write == 0) break               # end of file
    18128     #     word-slice = next-mu-token(line)
    18129     #     if slice-empty?(word-slice)               # end of line
    18130     #       continue
    18131     #     else if slice-starts-with?(word-slice, "#")
    18132     #       continue
    18133     #     else if slice-equal?(word-slice, "{")
    18134     #       assert(no-tokens-in(line))
    18135     #       block = parse-mu-block(in, vars, fn)
    18136     #       append-to-block(out-addr, block)
    18137     #     else if slice-equal?(word-slice, "}")
    18138     #       break
    18139     #     else if slice-ends-with?(word-slice, ":")
    18140     #       # TODO: error-check the rest of 'line'
    18141     #       --word-slice->end to skip ':'
    18142     #       named-block = parse-mu-named-block(word-slice, in, vars, fn)
    18143     #       append-to-block(out-addr, named-block)
    18144     #     else if slice-equal?(word-slice, "var")
    18145     #       var-def = parse-mu-var-def(line, vars, fn)
    18146     #       append-to-block(out-addr, var-def)
    18147     #     else
    18148     #       stmt = parse-mu-stmt(line, vars, fn)
    18149     #       append-to-block(out-addr, stmt)
    18150     #   pop(vars)
    18151     #
    18152     # . prologue
    18153     55/push-ebp
    18154     89/<- %ebp 4/r32/esp
    18155     # . save registers
    18156     50/push-eax
    18157     51/push-ecx
    18158     52/push-edx
    18159     53/push-ebx
    18160     57/push-edi
    18161     # var line/ecx: (stream byte 512)
    18162     81 5/subop/subtract %esp 0x200/imm32
    18163     68/push 0x200/imm32/size
    18164     68/push 0/imm32/read
    18165     68/push 0/imm32/write
    18166     89/<- %ecx 4/r32/esp
    18167     # var word-slice/edx: slice
    18168     68/push 0/imm32/end
    18169     68/push 0/imm32/start
    18170     89/<- %edx 4/r32/esp
    18171     # allocate into out
    18172     (allocate Heap *Stmt-size *(ebp+0x14))
    18173     # var out-addr/edi: (addr block) = lookup(*out)
    18174     8b/-> *(ebp+0x14) 7/r32/edi
    18175     (lookup *edi *(edi+4))  # => eax
    18176     89/<- %edi 0/r32/eax
    18177     # out-addr->tag is 0 (block) by default
    18178     # set out-addr->var
    18179     8d/copy-address *(edi+0xc) 0/r32/eax  # Block-var
    18180     (new-block-name *(ebp+0x10) %eax)
    18181     # push(vars, out-addr->var)
    18182     (push *(ebp+0xc) *(edi+0xc))  # Block-var
    18183     (push *(ebp+0xc) *(edi+0x10))  # Block-var
    18184     (push *(ebp+0xc) 0)  # false
    18185     # increment *Curr-block-depth
    18186     ff 0/subop/increment *Curr-block-depth
    18187     {
    18188 $parse-mu-block:line-loop:
    18189       # line = read-line-buffered(in)
    18190       (clear-stream %ecx)
    18191       (read-line-buffered *(ebp+8) %ecx)
    18192 #?       (write-buffered Stderr "line: ")
    18193 #?       (write-stream-data Stderr %ecx)
    18194 #? #?       (write-buffered Stderr Newline)  # line has its own newline
    18195 #?       (flush Stderr)
    18196 #?       (rewind-stream %ecx)
    18197       # if (line->write == 0) break
    18198       81 7/subop/compare *ecx 0/imm32
    18199       0f 84/jump-if-= break/disp32
    18200 #?       (write-buffered Stderr "vars:\n")
    18201 #?       (dump-vars *(ebp+0xc))
    18202       # word-slice = next-mu-token(line)
    18203       (next-mu-token %ecx %edx)
    18204 #?       (write-buffered Stderr "word: ")
    18205 #?       (write-slice-buffered Stderr %edx)
    18206 #?       (write-buffered Stderr Newline)
    18207 #?       (flush Stderr)
    18208       # if slice-empty?(word-slice) continue
    18209       (slice-empty? %edx)
    18210       3d/compare-eax-and 0/imm32/false
    18211       0f 85/jump-if-!= loop/disp32
    18212       # if (slice-starts-with?(word-slice, '#') continue
    18213       # . eax = *word-slice->start
    18214       8b/-> *edx 0/r32/eax
    18215       8a/copy-byte *eax 0/r32/AL
    18216       25/and-eax-with 0xff/imm32
    18217       # . if (eax == '#') continue
    18218       3d/compare-eax-and 0x23/imm32/hash
    18219       0f 84/jump-if-= loop/disp32
    18220       # if slice-equal?(word-slice, "{")
    18221       {
    18222 $parse-mu-block:check-for-block:
    18223         (slice-equal? %edx "{")
    18224         3d/compare-eax-and 0/imm32/false
    18225         74/jump-if-= break/disp8
    18226         (check-no-tokens-left %ecx)
    18227         # parse new block and append
    18228         # . var tmp/eax: (handle block)
    18229         68/push 0/imm32
    18230         68/push 0/imm32
    18231         89/<- %eax 4/r32/esp
    18232         # .
    18233         (parse-mu-block *(ebp+8) *(ebp+0xc) *(ebp+0x10) %eax *(ebp+0x18) *(ebp+0x1c))
    18234         (append-to-block Heap %edi  *eax *(eax+4))
    18235         # . reclaim tmp
    18236         81 0/subop/add %esp 8/imm32
    18237         # .
    18238         e9/jump $parse-mu-block:line-loop/disp32
    18239       }
    18240       # if slice-equal?(word-slice, "}") break
    18241 $parse-mu-block:check-for-end:
    18242       (slice-equal? %edx "}")
    18243       3d/compare-eax-and 0/imm32/false
    18244       0f 85/jump-if-!= break/disp32
    18245       # if slice-ends-with?(word-slice, ":") parse named block and append
    18246       {
    18247 $parse-mu-block:check-for-named-block:
    18248         # . eax = *(word-slice->end-1)
    18249         8b/-> *(edx+4) 0/r32/eax
    18250         48/decrement-eax
    18251         8a/copy-byte *eax 0/r32/AL
    18252         25/and-eax-with 0xff/imm32
    18253         # . if (eax != ':') break
    18254         3d/compare-eax-and 0x3a/imm32/colon
    18255         0f 85/jump-if-!= break/disp32
    18256         # TODO: error-check the rest of 'line'
    18257         #
    18258         # skip ':'
    18259         ff 1/subop/decrement *(edx+4)  # Slice-end
    18260         # var tmp/eax: (handle block)
    18261         68/push 0/imm32
    18262         68/push 0/imm32
    18263         89/<- %eax 4/r32/esp
    18264         #
    18265         (parse-mu-named-block %edx *(ebp+8) *(ebp+0xc) *(ebp+0x10) %eax *(ebp+0x18) *(ebp+0x1c))
    18266         (append-to-block Heap %edi  *eax *(eax+4))
    18267         # reclaim tmp
    18268         81 0/subop/add %esp 8/imm32
    18269         #
    18270         e9/jump $parse-mu-block:line-loop/disp32
    18271       }
    18272       # if slice-equal?(word-slice, "var")
    18273       {
    18274 $parse-mu-block:check-for-var:
    18275         (slice-equal? %edx "var")
    18276         3d/compare-eax-and 0/imm32/false
    18277         74/jump-if-= break/disp8
    18278         # var tmp/eax: (handle block)
    18279         68/push 0/imm32
    18280         68/push 0/imm32
    18281         89/<- %eax 4/r32/esp
    18282         #
    18283         (parse-mu-var-def %ecx *(ebp+0xc) %eax *(ebp+0x10) *(ebp+0x18) *(ebp+0x1c))
    18284         (append-to-block Heap %edi  *eax *(eax+4))
    18285         # reclaim tmp
    18286         81 0/subop/add %esp 8/imm32
    18287         #
    18288         e9/jump $parse-mu-block:line-loop/disp32
    18289       }
    18290 $parse-mu-block:regular-stmt:
    18291       # otherwise
    18292       # var tmp/eax: (handle block)
    18293       68/push 0/imm32
    18294       68/push 0/imm32
    18295       89/<- %eax 4/r32/esp
    18296       #
    18297       (parse-mu-stmt %ecx *(ebp+0xc) *(ebp+0x10) %eax *(ebp+0x18) *(ebp+0x1c))
    18298       (append-to-block Heap %edi  *eax *(eax+4))
    18299       # reclaim tmp
    18300       81 0/subop/add %esp 8/imm32
    18301       #
    18302       e9/jump loop/disp32
    18303     } # end line loop
    18304     (clean-up-blocks *(ebp+0xc) *Curr-block-depth *(ebp+0x10))
    18305     # decrement *Curr-block-depth
    18306     ff 1/subop/decrement *Curr-block-depth
    18307     # pop(vars)
    18308     (pop *(ebp+0xc))  # => eax
    18309     (pop *(ebp+0xc))  # => eax
    18310     (pop *(ebp+0xc))  # => eax
    18311 $parse-mu-block:end:
    18312     # . reclaim locals
    18313     81 0/subop/add %esp 0x214/imm32
    18314     # . restore registers
    18315     5f/pop-to-edi
    18316     5b/pop-to-ebx
    18317     5a/pop-to-edx
    18318     59/pop-to-ecx
    18319     58/pop-to-eax
    18320     # . epilogue
    18321     89/<- %esp 5/r32/ebp
    18322     5d/pop-to-ebp
    18323     c3/return
    18324
    18325 $parse-mu-block:abort:
    18326     # error("'{' or '}' should be on its own line, but got '")
    18327     (write-buffered *(ebp+0x18) "'{' or '}' should be on its own line, but got '")
    18328     (rewind-stream %ecx)
    18329     (write-stream-data *(ebp+0x18) %ecx)
    18330     (write-buffered *(ebp+0x18) "'\n")
    18331     (flush *(ebp+0x18))
    18332     (stop *(ebp+0x1c) 1)
    18333     # never gets here
    18334
    18335 new-block-name:  # fn: (addr function), out: (addr handle var)
    18336     # . prologue
    18337     55/push-ebp
    18338     89/<- %ebp 4/r32/esp
    18339     # . save registers
    18340     50/push-eax
    18341     51/push-ecx
    18342     52/push-edx
    18343     # var n/ecx: int = len(fn->name) + 10 for an int + 2 for '$:'
    18344     8b/-> *(ebp+8) 0/r32/eax
    18345     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    18346     8b/-> *eax 0/r32/eax  # String-size
    18347     05/add-to-eax 0xd/imm32  # 10 + 2 for '$:'
    18348     89/<- %ecx 0/r32/eax
    18349     # var name/edx: (stream byte n)
    18350     29/subtract-from %esp 1/r32/ecx
    18351     ff 6/subop/push %ecx
    18352     68/push 0/imm32/read
    18353     68/push 0/imm32/write
    18354     89/<- %edx 4/r32/esp
    18355     (clear-stream %edx)
    18356     # eax = fn->name
    18357     8b/-> *(ebp+8) 0/r32/eax
    18358     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    18359     # construct result using Next-block-index (and increment it)
    18360     (write %edx "$")
    18361     (write %edx %eax)
    18362     (write %edx ":")
    18363     (write-int32-hex %edx *Next-block-index)
    18364     ff 0/subop/increment *Next-block-index
    18365     # var s/eax: slice = {name->data, name->data + name->write}  (clobbering edx)
    18366     # . eax = name->write
    18367     8b/-> *edx 0/r32/eax
    18368     # . edx = name->data
    18369     8d/copy-address *(edx+0xc) 2/r32/edx
    18370     # . eax = name->write + name->data
    18371     01/add-to %eax 2/r32/edx
    18372     # . push {edx, eax}
    18373     ff 6/subop/push %eax
    18374     ff 6/subop/push %edx
    18375     89/<- %eax 4/r32/esp
    18376     # out = new literal(s)
    18377     (new-literal Heap %eax *(ebp+0xc))
    18378 #?     8b/-> *(ebp+0xc) 0/r32/eax
    18379 #?     (write-buffered Stderr "type allocid in caller after new-literal: ")
    18380 #?     (write-int32-hex-buffered Stderr *(eax+8))
    18381 #?     (write-buffered Stderr " for var ")
    18382 #?     (write-int32-hex-buffered Stderr %eax)
    18383 #?     (write-buffered Stderr Newline)
    18384 #?     (flush Stderr)
    18385 $new-block-name:end:
    18386     # . reclaim locals
    18387     81 0/subop/add %ecx 0xc/imm32  # name.{read/write/len}
    18388     81 0/subop/add %ecx 8/imm32  # slice
    18389     01/add-to %esp 1/r32/ecx
    18390     # . restore registers
    18391     5a/pop-to-edx
    18392     59/pop-to-ecx
    18393     58/pop-to-eax
    18394     # . epilogue
    18395     89/<- %esp 5/r32/ebp
    18396     5d/pop-to-ebp
    18397     c3/return
    18398
    18399 check-no-tokens-left:  # line: (addr stream byte)
    18400     # . prologue
    18401     55/push-ebp
    18402     89/<- %ebp 4/r32/esp
    18403     # . save registers
    18404     50/push-eax
    18405     51/push-ecx
    18406     # var s/ecx: slice
    18407     68/push 0/imm32/end
    18408     68/push 0/imm32/start
    18409     89/<- %ecx 4/r32/esp
    18410     #
    18411     (next-mu-token *(ebp+8) %ecx)
    18412     # if slice-empty?(s) return
    18413     (slice-empty? %ecx)
    18414     3d/compare-eax-and 0/imm32/false
    18415     75/jump-if-!= $check-no-tokens-left:end/disp8
    18416     # if (slice-starts-with?(s, '#') return
    18417     # . eax = *s->start
    18418     8b/-> *edx 0/r32/eax
    18419     8a/copy-byte *eax 0/r32/AL
    18420     25/and-eax-with 0xff/imm32
    18421     # . if (eax == '#') continue
    18422     3d/compare-eax-and 0x23/imm32/hash
    18423     74/jump-if-= $check-no-tokens-left:end/disp8
    18424     # abort
    18425     (write-buffered Stderr "'{' or '}' should be on its own line, but got '")
    18426     (rewind-stream %ecx)
    18427     (write-stream 2 %ecx)
    18428     (write-buffered Stderr "'\n")
    18429     (flush Stderr)
    18430     # . syscall(exit, 1)
    18431     bb/copy-to-ebx  1/imm32
    18432     e8/call syscall_exit/disp32
    18433     # never gets here
    18434 $check-no-tokens-left:end:
    18435     # . reclaim locals
    18436     81 0/subop/add %esp 8/imm32
    18437     # . restore registers
    18438     59/pop-to-ecx
    18439     58/pop-to-eax
    18440     # . epilogue
    18441     89/<- %esp 5/r32/ebp
    18442     5d/pop-to-ebp
    18443     c3/return
    18444
    18445 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)
    18446     # pseudocode:
    18447     #   var v: (handle var)
    18448     #   new-literal(name, v)
    18449     #   push(vars, {v, false})
    18450     #   parse-mu-block(in, vars, fn, out)
    18451     #   pop(vars)
    18452     #   out->tag = block
    18453     #   out->var = v
    18454     #
    18455     # . prologue
    18456     55/push-ebp
    18457     89/<- %ebp 4/r32/esp
    18458     # . save registers
    18459     50/push-eax
    18460     51/push-ecx
    18461     57/push-edi
    18462     # var v/ecx: (handle var)
    18463     68/push 0/imm32
    18464     68/push 0/imm32
    18465     89/<- %ecx 4/r32/esp
    18466     #
    18467     (new-literal Heap *(ebp+8) %ecx)
    18468     # push(vars, v)
    18469     (push *(ebp+0x10) *ecx)
    18470     (push *(ebp+0x10) *(ecx+4))
    18471     (push *(ebp+0x10) 0)  # false
    18472     #
    18473     (parse-mu-block *(ebp+0xc) *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c) *(ebp+0x20))
    18474     # pop v off vars
    18475     (pop *(ebp+0x10))  # => eax
    18476     (pop *(ebp+0x10))  # => eax
    18477     (pop *(ebp+0x10))  # => eax
    18478     # var out-addr/edi: (addr stmt) = lookup(*out)
    18479     8b/-> *(ebp+0x18) 7/r32/edi
    18480     (lookup *edi *(edi+4))  # => eax
    18481     89/<- %edi 0/r32/eax
    18482     # out-addr->tag = named-block
    18483     c7 0/subop/copy *edi 0/imm32/block  # Stmt-tag
    18484     # out-addr->var = v
    18485     8b/-> *ecx 0/r32/eax
    18486     89/<- *(edi+0xc) 0/r32/eax  # Block-var
    18487     8b/-> *(ecx+4) 0/r32/eax
    18488     89/<- *(edi+0x10) 0/r32/eax  # Block-var
    18489 $parse-mu-named-block:end:
    18490     # . reclaim locals
    18491     81 0/subop/add %esp 8/imm32
    18492     # . restore registers
    18493     5f/pop-to-edi
    18494     59/pop-to-ecx
    18495     58/pop-to-eax
    18496     # . epilogue
    18497     89/<- %esp 5/r32/ebp
    18498     5d/pop-to-ebp
    18499     c3/return
    18500
    18501 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)
    18502     # . prologue
    18503     55/push-ebp
    18504     89/<- %ebp 4/r32/esp
    18505     # . save registers
    18506     50/push-eax
    18507     51/push-ecx
    18508     52/push-edx
    18509     56/push-esi
    18510     57/push-edi
    18511     # edi = out
    18512     8b/-> *(ebp+0x10) 7/r32/edi
    18513     # var word-slice/ecx: slice
    18514     68/push 0/imm32/end
    18515     68/push 0/imm32/start
    18516     89/<- %ecx 4/r32/esp
    18517     # var v/edx: (handle var)
    18518     68/push 0/imm32
    18519     68/push 0/imm32
    18520     89/<- %edx 4/r32/esp
    18521     # v = parse-var-with-type(next-mu-token(line))
    18522     (next-mu-token *(ebp+8) %ecx)
    18523     {
    18524       # just for tests, support null fn
    18525       8b/-> *(ebp+0x14) 0/r32/eax
    18526       3d/compare-eax-and 0/imm32
    18527       74/jump-if-= break/disp8
    18528       (lookup *eax *(eax+4))  # Var-name Var-name => eax
    18529     }
    18530     (parse-var-with-type %ecx *(ebp+8) %edx %eax *(ebp+0x18) *(ebp+0x1c))
    18531     # var v-addr/esi: (addr var)
    18532     (lookup *edx *(edx+4))  # => eax
    18533     89/<- %esi 0/r32/eax
    18534     # v->block-depth = *Curr-block-depth
    18535     8b/-> *Curr-block-depth 0/r32/eax
    18536     89/<- *(esi+0x10) 0/r32/eax  # Var-block-depth
    18537     # either v has no register and there's no more to this line
    18538     81 7/subop/compare *(esi+0x18) 0/imm32
    18539     {
    18540       75/jump-if-!= break/disp8
    18541       # if v-addr->type == byte, abort
    18542       (lookup *(esi+8) *(esi+0xc))  # Var-type Var-type => eax
    18543       (simple-mu-type? %eax 8)  # byte => eax
    18544       3d/compare-eax-and 0/imm32/false
    18545       0f 85/jump-if-!= $parse-mu-var-def:error-byte-on-stack/disp32
    18546       # ensure that there's nothing else on this line
    18547       (next-mu-token *(ebp+8) %ecx)
    18548       (slice-empty? %ecx)  # => eax
    18549       3d/compare-eax-and 0/imm32/false
    18550       0f 84/jump-if-= $parse-mu-var-def:error2/disp32
    18551       #
    18552       (new-var-def Heap  *edx *(edx+4)  %edi)
    18553       e9/jump $parse-mu-var-def:update-vars/disp32
    18554     }
    18555     # or v has a register and there's more to this line
    18556     {
    18557       0f 84/jump-if-= break/disp32
    18558       # if v-addr->type == byte, check for unsupported registers
    18559       {
    18560         (lookup *(esi+8) *(esi+0xc))  # Var-type Var-type => eax
    18561         (simple-mu-type? %eax 8)  # byte => eax
    18562         3d/compare-eax-and 0/imm32/false
    18563         74/jump-if-= break/disp8
    18564         (lookup *(esi+0x18) *(esi+0x1c))  # => eax
    18565         (string-equal? %eax "esi")  # => eax
    18566         3d/compare-eax-and 0/imm32/false
    18567         0f 85/jump-if-!= $parse-mu-var-def:error-byte-registers/disp32
    18568         (lookup *(esi+0x18) *(esi+0x1c))  # => eax
    18569         (string-equal? %eax "edi")  # => eax
    18570         3d/compare-eax-and 0/imm32/false
    18571         0f 85/jump-if-!= $parse-mu-var-def:error-byte-registers/disp32
    18572       }
    18573       # TODO: vars of type 'byte' should only be initialized by clearing to 0
    18574       # ensure that the next word is '<-'
    18575       (next-mu-token *(ebp+8) %ecx)
    18576       (slice-equal? %ecx "<-")  # => eax
    18577       3d/compare-eax-and 0/imm32/false
    18578       0f 84/jump-if-= $parse-mu-var-def:error1/disp32
    18579       #
    18580       (new-reg-var-def Heap  *edx *(edx+4)  %edi)
    18581       (lookup *edi *(edi+4))  # => eax
    18582       (add-operation-and-inputs-to-stmt %eax *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
    18583     }
    18584 $parse-mu-var-def:update-vars:
    18585     # push 'v' at end of function
    18586     (push *(ebp+0xc) *edx)
    18587     (push *(ebp+0xc) *(edx+4))
    18588     (push *(ebp+0xc) 0)  # Live-var-register-spilled is unused during parsing
    18589 $parse-mu-var-def:end:
    18590     # . reclaim locals
    18591     81 0/subop/add %esp 0x10/imm32
    18592     # . restore registers
    18593     5f/pop-to-edi
    18594     5e/pop-to-esi
    18595     5a/pop-to-edx
    18596     59/pop-to-ecx
    18597     58/pop-to-eax
    18598     # . epilogue
    18599     89/<- %esp 5/r32/ebp
    18600     5d/pop-to-ebp
    18601     c3/return
    18602
    18603 $parse-mu-var-def:error1:
    18604     (rewind-stream *(ebp+8))
    18605     # error("register variable requires a valid instruction to initialize but got '" line "'\n")
    18606     (write-buffered *(ebp+0x18) "register variable requires a valid instruction to initialize but got '")
    18607     (flush *(ebp+0x18))
    18608     (write-stream-data *(ebp+0x18) *(ebp+8))
    18609     (write-buffered *(ebp+0x18) "'\n")
    18610     (flush *(ebp+0x18))
    18611     (stop *(ebp+0x1c) 1)
    18612     # never gets here
    18613
    18614 $parse-mu-var-def:error2:
    18615     # error("fn " fn ": var " var ": variables on the stack can't take an initializer\n")
    18616     (write-buffered *(ebp+0x18) "fn ")
    18617     8b/-> *(ebp+0x14) 0/r32/eax
    18618     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    18619     (write-buffered *(ebp+0x18) %eax)
    18620     (write-buffered *(ebp+0x18) ": var ")
    18621     # var v-addr/eax: (addr var) = lookup(v)
    18622     (lookup *edx *(edx+4))  # => eax
    18623     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    18624     (write-buffered *(ebp+0x18) %eax)
    18625     (write-buffered *(ebp+0x18) ": variables on the stack can't take an initializer\n")
    18626     (flush *(ebp+0x18))
    18627     (stop *(ebp+0x1c) 1)
    18628     # never gets here
    18629
    18630 $parse-mu-var-def:error-byte-on-stack:
    18631     # error("fn " fn ": var '" var "' of type 'byte' cannot be on the stack\n")
    18632     (write-buffered *(ebp+0x18) "fn ")
    18633     8b/-> *(ebp+0x14) 0/r32/eax
    18634     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    18635     (write-buffered *(ebp+0x18) %eax)
    18636     (write-buffered *(ebp+0x18) ": var '")
    18637     # var v-addr/eax: (addr var) = lookup(v)
    18638     (lookup *edx *(edx+4))  # => eax
    18639     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    18640     (write-buffered *(ebp+0x18) %eax)
    18641     (write-buffered *(ebp+0x18) "' of type 'byte' cannot be on the stack\n")
    18642     (flush *(ebp+0x18))
    18643     (stop *(ebp+0x1c) 1)
    18644     # never gets here
    18645
    18646 $parse-mu-var-def:error-byte-registers:
    18647     # error("fn " fn ": var '" var "' of type 'byte' cannot be in esi or edi\n")
    18648     (write-buffered *(ebp+0x18) "fn ")
    18649     8b/-> *(ebp+0x14) 0/r32/eax
    18650     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    18651     (write-buffered *(ebp+0x18) %eax)
    18652     (write-buffered *(ebp+0x18) ": var '")
    18653     # var v-addr/eax: (addr var) = lookup(v)
    18654     (lookup *edx *(edx+4))  # => eax
    18655     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    18656     (write-buffered *(ebp+0x18) %eax)
    18657     (write-buffered *(ebp+0x18) "' of type 'byte' cannot be in esi or edi\n")
    18658     (flush *(ebp+0x18))
    18659     (stop *(ebp+0x1c) 1)
    18660     # never gets here
    18661
    18662 test-parse-mu-var-def:
    18663     # 'var n: int'
    18664     # . prologue
    18665     55/push-ebp
    18666     89/<- %ebp 4/r32/esp
    18667     # setup
    18668     8b/-> *Primitive-type-ids 0/r32/eax
    18669     89/<- *Type-id 0/r32/eax  # stream-write
    18670     (clear-stream _test-input-stream)
    18671     (write _test-input-stream "n: int\n")  # caller has consumed the 'var'
    18672     c7 0/subop/copy *Curr-block-depth 1/imm32
    18673     # var out/esi: (handle stmt)
    18674     68/push 0/imm32
    18675     68/push 0/imm32
    18676     89/<- %esi 4/r32/esp
    18677     # var vars/ecx: (stack (addr var) 16)
    18678     81 5/subop/subtract %esp 0xc0/imm32
    18679     68/push 0xc0/imm32/size
    18680     68/push 0/imm32/top
    18681     89/<- %ecx 4/r32/esp
    18682     (clear-stack %ecx)
    18683     # convert
    18684     (parse-mu-var-def _test-input-stream %ecx %esi 0 Stderr 0)
    18685     # var out-addr/esi: (addr stmt)
    18686     (lookup *esi *(esi+4))  # => eax
    18687     89/<- %esi 0/r32/eax
    18688     #
    18689     (check-ints-equal *esi 2 "F - test-parse-mu-var-def/tag")  # Stmt-tag is var-def
    18690     # var v/ecx: (addr var) = lookup(out->var)
    18691     (lookup *(esi+4) *(esi+8))  # Vardef-var Vardef-var => eax
    18692     89/<- %ecx 0/r32/eax
    18693     # v->name
    18694     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    18695     (check-strings-equal %eax "n" "F - test-parse-mu-var-def/var-name")
    18696     # v->register
    18697     (check-ints-equal *(ecx+0x18) 0 "F - test-parse-mu-var-def/var-register")  # Var-register
    18698     # v->block-depth
    18699     (check-ints-equal *(ecx+0x10) 1 "F - test-parse-mu-var-def/output-block-depth")  # Var-block-depth
    18700     # v->type == int
    18701     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
    18702     (check-ints-equal *eax 1 "F - test-parse-mu-var-def/var-type:0")  # Type-tree-is-atom
    18703     (check-ints-equal *(eax+4) 1 "F - test-parse-mu-var-def/var-type:1")  # Type-tree-value
    18704     (check-ints-equal *(eax+0xc) 0 "F - test-parse-mu-var-def/var-type:2")  # Type-tree-right
    18705     # . epilogue
    18706     89/<- %esp 5/r32/ebp
    18707     5d/pop-to-ebp
    18708     c3/return
    18709
    18710 test-parse-mu-reg-var-def:
    18711     # 'var n/eax: int <- copy 0'
    18712     # . prologue
    18713     55/push-ebp
    18714     89/<- %ebp 4/r32/esp
    18715     # setup
    18716     8b/-> *Primitive-type-ids 0/r32/eax
    18717     89/<- *Type-id 0/r32/eax  # stream-write
    18718     (clear-stream _test-input-stream)
    18719     (write _test-input-stream "n/eax: int <- copy 0\n")  # caller has consumed the 'var'
    18720     c7 0/subop/copy *Curr-block-depth 1/imm32
    18721     # var out/esi: (handle stmt)
    18722     68/push 0/imm32
    18723     68/push 0/imm32
    18724     89/<- %esi 4/r32/esp
    18725     # var vars/ecx: (stack (addr var) 16)
    18726     81 5/subop/subtract %esp 0xc0/imm32
    18727     68/push 0xc0/imm32/size
    18728     68/push 0/imm32/top
    18729     89/<- %ecx 4/r32/esp
    18730     (clear-stack %ecx)
    18731     # convert
    18732     (parse-mu-var-def _test-input-stream %ecx %esi 0 Stderr 0)
    18733     # var out-addr/esi: (addr stmt)
    18734     (lookup *esi *(esi+4))  # => eax
    18735     89/<- %esi 0/r32/eax
    18736     #
    18737     (check-ints-equal *esi 3 "F - test-parse-mu-reg-var-def/tag")  # Stmt-tag is reg-var-def
    18738     # var v/ecx: (addr var) = lookup(out->outputs->value)
    18739     # . eax: (addr stmt-var) = lookup(out->outputs)
    18740     (lookup *(esi+0x14) *(esi+0x18))  # Regvardef-outputs Regvardef-outputs => eax
    18741     # .
    18742     (check-ints-equal *(eax+8) 0 "F - test-parse-mu-reg-var-def/single-output")  # Stmt-var-next
    18743     # . eax: (addr var) = lookup(eax->value)
    18744     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    18745     # . ecx = eax
    18746     89/<- %ecx 0/r32/eax
    18747     # v->name
    18748     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    18749     (check-strings-equal %eax "n" "F - test-parse-mu-reg-var-def/output-name")  # Var-name
    18750     # v->register
    18751     (lookup *(ecx+0x18) *(ecx+0x1c))  # Var-register Var-register => eax
    18752     (check-strings-equal %eax "eax" "F - test-parse-mu-reg-var-def/output-register")
    18753     # v->block-depth
    18754     (check-ints-equal *(ecx+0x10) 1 "F - test-parse-mu-reg-var-def/output-block-depth")  # Var-block-depth
    18755     # v->type == int
    18756     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
    18757     (check-ints-equal *eax 1 "F - test-parse-mu-reg-var-def/output-type:0")  # Type-tree-is-atom
    18758     (check-ints-equal *(eax+4) 1 "F - test-parse-mu-reg-var-def/output-type:1")  # Type-tree-value
    18759     (check-ints-equal *(eax+0xc) 0 "F - test-parse-mu-reg-var-def/output-type:2")  # Type-tree-right
    18760     # . epilogue
    18761     89/<- %esp 5/r32/ebp
    18762     5d/pop-to-ebp
    18763     c3/return
    18764
    18765 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)
    18766     # pseudocode:
    18767     #   var name: slice
    18768     #   allocate(Heap, Stmt-size, out)
    18769     #   var out-addr: (addr stmt) = lookup(*out)
    18770     #   out-addr->tag = stmt
    18771     #   if stmt-has-outputs?(line)
    18772     #     while true
    18773     #       name = next-mu-token(line)
    18774     #       if (name == '<-') break
    18775     #       assert(identifier?(name))
    18776     #       var v: (handle var) = lookup-var(name, vars)
    18777     #       out-addr->outputs = append(v, out-addr->outputs)
    18778     #   add-operation-and-inputs-to-stmt(out-addr, line, vars)
    18779     #
    18780     # . prologue
    18781     55/push-ebp
    18782     89/<- %ebp 4/r32/esp
    18783     # . save registers
    18784     50/push-eax
    18785     51/push-ecx
    18786     52/push-edx
    18787     53/push-ebx
    18788     57/push-edi
    18789     # var name/ecx: slice
    18790     68/push 0/imm32/end
    18791     68/push 0/imm32/start
    18792     89/<- %ecx 4/r32/esp
    18793     # var is-deref?/edx: boolean = false
    18794     ba/copy-to-edx 0/imm32/false
    18795     # var v: (handle var)
    18796     68/push 0/imm32
    18797     68/push 0/imm32
    18798     89/<- %ebx 4/r32/esp
    18799     #
    18800     (allocate Heap *Stmt-size *(ebp+0x14))
    18801     # var out-addr/edi: (addr stmt) = lookup(*out)
    18802     8b/-> *(ebp+0x14) 7/r32/edi
    18803     (lookup *edi *(edi+4))  # => eax
    18804     89/<- %edi 0/r32/eax
    18805     # out-addr->tag = 1/stmt
    18806     c7 0/subop/copy *edi 1/imm32/stmt1  # Stmt-tag
    18807     {
    18808       (stmt-has-outputs? *(ebp+8))
    18809       3d/compare-eax-and 0/imm32/false
    18810       0f 84/jump-if-= break/disp32
    18811       {
    18812 $parse-mu-stmt:read-outputs:
    18813         # name = next-mu-token(line)
    18814         (next-mu-token *(ebp+8) %ecx)
    18815         # if slice-empty?(word-slice) break
    18816         (slice-empty? %ecx)  # => eax
    18817         3d/compare-eax-and 0/imm32/false
    18818         0f 85/jump-if-!= break/disp32
    18819         # if (name == "<-") break
    18820         (slice-equal? %ecx "<-")  # => eax
    18821         3d/compare-eax-and 0/imm32/false
    18822         0f 85/jump-if-!= break/disp32
    18823         # if slice-starts-with?(name, "*") abort
    18824         8b/-> *ecx 0/r32/eax  # Slice-start
    18825         8a/copy-byte *eax 0/r32/AL
    18826         25/and-eax-with 0xff/imm32
    18827         3d/compare-eax-and 0x2a/imm32/asterisk
    18828         0f 84/jump-if-= $parse-mu-stmt:error-output-dereferenced/disp32
    18829         # assert(identifier?(name))
    18830         (identifier? %ecx)  # => eax
    18831         3d/compare-eax-and 0/imm32/false
    18832         0f 84/jump-if-= $parse-mu-stmt:abort/disp32
    18833         #
    18834         (lookup-var %ecx *(ebp+0xc) %ebx *(ebp+0x10) *(ebp+0x18) *(ebp+0x1c))
    18835         8d/copy-address *(edi+0x14) 0/r32/eax  # Stmt1-outputs
    18836         (append-stmt-var Heap  *ebx *(ebx+4)  *(edi+0x14) *(edi+0x18)  0  %eax)  # Stmt1-outputs
    18837         #
    18838         e9/jump loop/disp32
    18839       }
    18840     }
    18841     (add-operation-and-inputs-to-stmt %edi *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x18) *(ebp+0x1c))
    18842 $parse-mu-stmt:end:
    18843     # . reclaim locals
    18844     81 0/subop/add %esp 0x10/imm32
    18845     # . restore registers
    18846     5f/pop-to-edi
    18847     5b/pop-to-ebx
    18848     5a/pop-to-edx
    18849     59/pop-to-ecx
    18850     58/pop-to-eax
    18851     # . epilogue
    18852     89/<- %esp 5/r32/ebp
    18853     5d/pop-to-ebp
    18854     c3/return
    18855
    18856 $parse-mu-stmt:abort:
    18857     # error("invalid identifier '" name "'\n")
    18858     (write-buffered *(ebp+0x18) "fn ")
    18859     8b/-> *(ebp+0x10) 0/r32/eax
    18860     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    18861     (write-buffered *(ebp+0x18) %eax)
    18862     (write-buffered *(ebp+0x18) ": invalid identifier '")
    18863     (write-slice-buffered *(ebp+0x18) %ecx)
    18864     (write-buffered *(ebp+0x18) "'\n")
    18865     (flush *(ebp+0x18))
    18866     (stop *(ebp+0x1c) 1)
    18867     # never gets here
    18868
    18869 $parse-mu-stmt:error-output-dereferenced:
    18870     # error("invalid identifier '" name "'\n")
    18871     (write-buffered *(ebp+0x18) "fn ")
    18872     8b/-> *(ebp+0x10) 0/r32/eax
    18873     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    18874     (write-buffered *(ebp+0x18) %eax)
    18875     (write-buffered *(ebp+0x18) ": output '")
    18876     (write-slice-buffered *(ebp+0x18) %ecx)
    18877     (write-buffered *(ebp+0x18) "' should write to a register, and therefore cannot be dereferenced\n")
    18878     (flush *(ebp+0x18))
    18879     (stop *(ebp+0x1c) 1)
    18880     # never gets here
    18881
    18882 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)
    18883     # pseudocode:
    18884     #   stmt->name = slice-to-string(next-mu-token(line))
    18885     #   while true
    18886     #     name = next-mu-token(line)
    18887     #     v = lookup-var-or-literal(name)
    18888     #     stmt->inouts = append(v, stmt->inouts)
    18889     #
    18890     # . prologue
    18891     55/push-ebp
    18892     89/<- %ebp 4/r32/esp
    18893     # . save registers
    18894     50/push-eax
    18895     51/push-ecx
    18896     52/push-edx
    18897     53/push-ebx
    18898     56/push-esi
    18899     57/push-edi
    18900     # edi = stmt
    18901     8b/-> *(ebp+8) 7/r32/edi
    18902     # var name/ecx: slice
    18903     68/push 0/imm32/end
    18904     68/push 0/imm32/start
    18905     89/<- %ecx 4/r32/esp
    18906     # var is-deref?/edx: boolean = false
    18907     ba/copy-to-edx 0/imm32/false
    18908     # var v/esi: (handle var)
    18909     68/push 0/imm32
    18910     68/push 0/imm32
    18911     89/<- %esi 4/r32/esp
    18912 $add-operation-and-inputs-to-stmt:read-operation:
    18913     (next-mu-token *(ebp+0xc) %ecx)
    18914     8d/copy-address *(edi+4) 0/r32/eax  # Stmt1-operation or Regvardef-operationStmt1-operation or Regvardef-operation
    18915     (slice-to-string Heap %ecx %eax)
    18916     # var is-get?/ebx: boolean = (name == "get")
    18917     (slice-equal? %ecx "get")  # => eax
    18918     89/<- %ebx 0/r32/eax
    18919     {
    18920 $add-operation-and-inputs-to-stmt:read-inouts:
    18921       # name = next-mu-token(line)
    18922       (next-mu-token *(ebp+0xc) %ecx)
    18923       # if slice-empty?(word-slice) break
    18924       (slice-empty? %ecx)  # => eax
    18925       3d/compare-eax-and 0/imm32/false
    18926       0f 85/jump-if-!= break/disp32
    18927       # if (name == "<-") abort
    18928       (slice-equal? %ecx "<-")
    18929       3d/compare-eax-and 0/imm32/false
    18930       0f 85/jump-if-!= $add-operation-and-inputs-to-stmt:abort/disp32
    18931       # if (get? && second operand) lookup or create offset
    18932       {
    18933         81 7/subop/compare %ebx 0/imm32/false
    18934         74/jump-if-= break/disp8
    18935         (lookup *(edi+0xc) *(edi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    18936         3d/compare-eax-and 0/imm32
    18937         74/jump-if-= break/disp8
    18938         (lookup-or-create-constant %eax %ecx %esi)
    18939 #?         (lookup *esi *(esi+4))
    18940 #?         (write-buffered Stderr "creating new output var ")
    18941 #?         (write-int32-hex-buffered Stderr %eax)
    18942 #?         (write-buffered Stderr " for field called ")
    18943 #?         (write-slice-buffered Stderr %ecx)
    18944 #?         (write-buffered Stderr "; var name ")
    18945 #?         (lookup *eax *(eax+4))  # Var-name
    18946 #?         (write-buffered Stderr %eax)
    18947 #?         (write-buffered Stderr Newline)
    18948 #?         (flush Stderr)
    18949         e9/jump $add-operation-and-inputs-to-stmt:save-var/disp32
    18950       }
    18951       # is-deref? = false
    18952       ba/copy-to-edx 0/imm32/false
    18953       # if (slice-starts-with?(name, '*')) ++name->start and set is-deref?
    18954       8b/-> *ecx 0/r32/eax  # Slice-start
    18955       8a/copy-byte *eax 0/r32/AL
    18956       25/and-eax-with 0xff/imm32
    18957       3d/compare-eax-and 0x2a/imm32/asterisk
    18958       {
    18959         75/jump-if-!= break/disp8
    18960 $add-operation-and-inputs-to-stmt:inout-is-deref:
    18961         ff 0/subop/increment *ecx
    18962         ba/copy-to-edx 1/imm32/true
    18963       }
    18964       (lookup-var-or-literal %ecx *(ebp+0x10) %esi *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
    18965       # if (deref?) some additional checks
    18966       81 7/subop/compare %edx 0/imm32/false
    18967       {
    18968         74/jump-if-= break/disp8
    18969         # if var is not in register, abort
    18970         (lookup *esi *(esi+4))  # => eax
    18971         81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
    18972         0f 84/jump-if-= $add-operation-and-inputs-to-stmt:error-deref-on-stack/disp32
    18973         # if var is not an address, abort
    18974         (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    18975         (mu-addr-type? %eax)  # => eax
    18976         3d/compare-eax-and 0/imm32/false
    18977         0f 84/jump-if-= $add-operation-and-inputs-to-stmt:error-deref-non-addr/disp32
    18978       }
    18979 $add-operation-and-inputs-to-stmt:save-var:
    18980       8d/copy-address *(edi+0xc) 0/r32/eax
    18981       (append-stmt-var Heap  *esi *(esi+4)  *(edi+0xc) *(edi+0x10)  %edx  %eax)  # Stmt1-inouts or Regvardef-inouts
    18982       #
    18983       e9/jump loop/disp32
    18984     }
    18985 $add-operation-and-inputs-to-stmt:end:
    18986     # . reclaim locals
    18987     81 0/subop/add %esp 0x10/imm32
    18988     # . restore registers
    18989     5f/pop-to-edi
    18990     5e/pop-to-esi
    18991     5b/pop-to-ebx
    18992     5a/pop-to-edx
    18993     59/pop-to-ecx
    18994     58/pop-to-eax
    18995     # . epilogue
    18996     89/<- %esp 5/r32/ebp
    18997     5d/pop-to-ebp
    18998     c3/return
    18999
    19000 $add-operation-and-inputs-to-stmt:abort:
    19001     # error("fn ___: invalid identifier in '" line "'\n")
    19002     (write-buffered *(ebp+0x18) "fn ")
    19003     8b/-> *(ebp+0x14) 0/r32/eax
    19004     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    19005     (write-buffered *(ebp+0x18) %eax)
    19006     (rewind-stream *(ebp+0xc))
    19007     (write-buffered *(ebp+0x18) ": invalid identifier in '")
    19008     (write-stream-data *(ebp+0x18) *(ebp+0xc))
    19009     (write-buffered *(ebp+0x18) "'\n")
    19010     (flush *(ebp+0x18))
    19011     (stop *(ebp+0x1c) 1)
    19012     # never gets here
    19013
    19014 $add-operation-and-inputs-to-stmt:error-deref-on-stack:
    19015     # error("fn ___: cannot dereference var ___ on stack\n")
    19016     (write-buffered *(ebp+0x18) "fn ")
    19017     8b/-> *(ebp+0x14) 0/r32/eax
    19018     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    19019     (write-buffered *(ebp+0x18) %eax)
    19020     (rewind-stream *(ebp+0xc))
    19021     (write-buffered *(ebp+0x18) ": cannot dereference var '")
    19022     (lookup *esi *(esi+4))  # => eax
    19023     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    19024     (write-buffered *(ebp+0x18) %eax)
    19025     (write-buffered *(ebp+0x18) "' on stack\n")
    19026     (flush *(ebp+0x18))
    19027     (stop *(ebp+0x1c) 1)
    19028     # never gets here
    19029
    19030 $add-operation-and-inputs-to-stmt:error-deref-non-addr:
    19031     # error("fn ___: cannot dereference non-addr var ___\n")
    19032     (write-buffered *(ebp+0x18) "fn ")
    19033     8b/-> *(ebp+0x14) 0/r32/eax
    19034     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    19035     (write-buffered *(ebp+0x18) %eax)
    19036     (rewind-stream *(ebp+0xc))
    19037     (write-buffered *(ebp+0x18) ": cannot dereference non-addr var '")
    19038     (lookup *esi *(esi+4))  # => eax
    19039     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    19040     (write-buffered *(ebp+0x18) %eax)
    19041     (write-buffered *(ebp+0x18) "'\n")
    19042     (flush *(ebp+0x18))
    19043     (stop *(ebp+0x1c) 1)
    19044     # never gets here
    19045
    19046 stmt-has-outputs?:  # line: (addr stream byte) -> result/eax: boolean
    19047     # . prologue
    19048     55/push-ebp
    19049     89/<- %ebp 4/r32/esp
    19050     # . save registers
    19051     51/push-ecx
    19052     # var word-slice/ecx: slice
    19053     68/push 0/imm32/end
    19054     68/push 0/imm32/start
    19055     89/<- %ecx 4/r32/esp
    19056     # result = false
    19057     b8/copy-to-eax 0/imm32/false
    19058     (rewind-stream *(ebp+8))
    19059     {
    19060       (next-mu-token *(ebp+8) %ecx)
    19061       # if slice-empty?(word-slice) break
    19062       (slice-empty? %ecx)
    19063       3d/compare-eax-and 0/imm32/false
    19064       b8/copy-to-eax 0/imm32/false/result  # restore result (if we're here it's still false)
    19065       0f 85/jump-if-!= break/disp32
    19066       # if slice-starts-with?(word-slice, '#') break
    19067       # . eax = *word-slice->start
    19068       8b/-> *ecx 0/r32/eax
    19069       8a/copy-byte *eax 0/r32/AL
    19070       25/and-eax-with 0xff/imm32
    19071       # . if (eax == '#') break
    19072       3d/compare-eax-and 0x23/imm32/hash
    19073       b8/copy-to-eax 0/imm32/false/result  # restore result (if we're here it's still false)
    19074       0f 84/jump-if-= break/disp32
    19075       # if slice-equal?(word-slice, '<-') return true
    19076       (slice-equal? %ecx "<-")
    19077       3d/compare-eax-and 0/imm32/false
    19078       74/jump-if-= loop/disp8
    19079       b8/copy-to-eax 1/imm32/true
    19080     }
    19081 $stmt-has-outputs:end:
    19082     (rewind-stream *(ebp+8))
    19083     # . reclaim locals
    19084     81 0/subop/add %esp 8/imm32
    19085     # . restore registers
    19086     59/pop-to-ecx
    19087     # . epilogue
    19088     89/<- %esp 5/r32/ebp
    19089     5d/pop-to-ebp
    19090     c3/return
    19091
    19092 # if 'name' starts with a digit, create a new literal var for it
    19093 # otherwise return first 'name' from the top (back) of 'vars' and abort if not found
    19094 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)
    19095     # . prologue
    19096     55/push-ebp
    19097     89/<- %ebp 4/r32/esp
    19098     # . save registers
    19099     50/push-eax
    19100     51/push-ecx
    19101     56/push-esi
    19102     # esi = name
    19103     8b/-> *(ebp+8) 6/r32/esi
    19104     # if slice-empty?(name) abort
    19105     (slice-empty? %esi)  # => eax
    19106     3d/compare-eax-and 0/imm32/false
    19107     0f 85/jump-if-!= $lookup-var-or-literal:abort/disp32
    19108     # var c/ecx: byte = *name->start
    19109     8b/-> *esi 1/r32/ecx
    19110     8a/copy-byte *ecx 1/r32/CL
    19111     81 4/subop/and %ecx 0xff/imm32
    19112     # if (decimal-digit?(c) || c == '-') return new var(name)
    19113     {
    19114       81 7/subop/compare %ecx 0x2d/imm32/dash
    19115       74/jump-if-= $lookup-var-or-literal:literal/disp8
    19116       (decimal-digit? %ecx)  # => eax
    19117       3d/compare-eax-and 0/imm32/false
    19118       74/jump-if-= break/disp8
    19119 $lookup-var-or-literal:literal:
    19120       (new-literal-integer Heap %esi *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
    19121       eb/jump $lookup-var-or-literal:end/disp8
    19122     }
    19123     # else if (c == '"') return new var(name)
    19124     {
    19125       81 7/subop/compare %ecx 0x22/imm32/dquote
    19126       75/jump-if-!= break/disp8
    19127 $lookup-var-or-literal:literal-string:
    19128       (new-literal-string Heap %esi *(ebp+0x10))
    19129       eb/jump $lookup-var-or-literal:end/disp8
    19130     }
    19131     # otherwise return lookup-var(name, vars)
    19132     {
    19133 $lookup-var-or-literal:var:
    19134       (lookup-var %esi *(ebp+0xc) *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
    19135     }
    19136 $lookup-var-or-literal:end:
    19137     # . restore registers
    19138     5e/pop-to-esi
    19139     59/pop-to-ecx
    19140     58/pop-to-eax
    19141     # . epilogue
    19142     89/<- %esp 5/r32/ebp
    19143     5d/pop-to-ebp
    19144     c3/return
    19145
    19146 $lookup-var-or-literal:abort:
    19147     (write-buffered *(ebp+0x18) "fn ")
    19148     8b/-> *(ebp+0x14) 0/r32/eax
    19149     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    19150     (write-buffered *(ebp+0x18) %eax)
    19151     (write-buffered *(ebp+0x18) ": empty variable!")
    19152     (flush *(ebp+0x18))
    19153     (stop *(ebp+0x1c) 1)
    19154     # never gets here
    19155
    19156 # return first 'name' from the top (back) of 'vars' and abort if not found
    19157 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)
    19158     # . prologue
    19159     55/push-ebp
    19160     89/<- %ebp 4/r32/esp
    19161     # . save registers
    19162     50/push-eax
    19163     #
    19164     (lookup-var-helper *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
    19165     # if (*out == 0) abort
    19166     8b/-> *(ebp+0x10) 0/r32/eax
    19167     81 7/subop/compare *eax 0/imm32
    19168     74/jump-if-= $lookup-var:abort/disp8
    19169 $lookup-var:end:
    19170     # . restore registers
    19171     58/pop-to-eax
    19172     # . epilogue
    19173     89/<- %esp 5/r32/ebp
    19174     5d/pop-to-ebp
    19175     c3/return
    19176
    19177 $lookup-var:abort:
    19178     (write-buffered *(ebp+0x18) "fn ")
    19179     8b/-> *(ebp+0x14) 0/r32/eax
    19180     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    19181     (write-buffered *(ebp+0x18) %eax)
    19182     (write-buffered *(ebp+0x18) ": unknown variable '")
    19183     (write-slice-buffered *(ebp+0x18) *(ebp+8))
    19184     (write-buffered *(ebp+0x18) "'\n")
    19185     (flush *(ebp+0x18))
    19186     (stop *(ebp+0x1c) 1)
    19187     # never gets here
    19188
    19189 # return first 'name' from the top (back) of 'vars', and 0/null if not found
    19190 # ensure that 'name' if in a register is the topmost variable in that register
    19191 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)
    19192     # pseudocode:
    19193     #   var curr: (addr handle var) = &vars->data[vars->top - 12]
    19194     #   var min = vars->data
    19195     #   while curr >= min
    19196     #     var v: (handle var) = *curr
    19197     #     if v->name == name
    19198     #       return
    19199     #     curr -= 12
    19200     #
    19201     # . prologue
    19202     55/push-ebp
    19203     89/<- %ebp 4/r32/esp
    19204     # . save registers
    19205     50/push-eax
    19206     51/push-ecx
    19207     52/push-edx
    19208     53/push-ebx
    19209     56/push-esi
    19210     57/push-edi
    19211     # clear out
    19212     (zero-out *(ebp+0x10) *Handle-size)
    19213     # esi = vars
    19214     8b/-> *(ebp+0xc) 6/r32/esi
    19215     # ebx = vars->top
    19216     8b/-> *esi 3/r32/ebx
    19217     # if (vars->top > vars->size) abort
    19218     3b/compare<- *(esi+4) 0/r32/eax
    19219     0f 8f/jump-if-> $lookup-var-helper:error1/disp32
    19220     # var min/edx: (addr handle var) = vars->data
    19221     8d/copy-address *(esi+8) 2/r32/edx
    19222     # var curr/ebx: (addr handle var) = &vars->data[vars->top - 12]
    19223     8d/copy-address *(esi+ebx-4) 3/r32/ebx  # vars + 8 + vars->type - 12
    19224     # var var-in-reg/edi: 16 addrs
    19225     68/push 0/imm32
    19226     68/push 0/imm32
    19227     68/push 0/imm32
    19228     68/push 0/imm32
    19229     68/push 0/imm32
    19230     68/push 0/imm32
    19231     68/push 0/imm32
    19232     68/push 0/imm32
    19233     68/push 0/imm32
    19234     68/push 0/imm32
    19235     68/push 0/imm32
    19236     68/push 0/imm32
    19237     68/push 0/imm32
    19238     68/push 0/imm32
    19239     68/push 0/imm32
    19240     68/push 0/imm32
    19241     89/<- %edi 4/r32/esp
    19242     {
    19243 $lookup-var-helper:loop:
    19244       # if (curr < min) return
    19245       39/compare %ebx 2/r32/edx
    19246       0f 82/jump-if-addr< break/disp32
    19247       # var v/ecx: (addr var) = lookup(*curr)
    19248       (lookup *ebx *(ebx+4))  # => eax
    19249       89/<- %ecx 0/r32/eax
    19250       # var vn/eax: (addr array byte) = lookup(v->name)
    19251       (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    19252       # if (vn == name) return curr
    19253       (slice-equal? *(ebp+8) %eax)  # => eax
    19254       3d/compare-eax-and 0/imm32/false
    19255       {
    19256         74/jump-if-= break/disp8
    19257 $lookup-var-helper:found:
    19258         # var vr/eax: (addr array byte) = lookup(v->register)
    19259         (lookup *(ecx+0x18) *(ecx+0x1c))  # Var-register Var-register => eax
    19260         3d/compare-eax-and 0/imm32
    19261         {
    19262           74/jump-if-= break/disp8
    19263 $lookup-var-helper:found-register:
    19264           # var reg/eax: int = get(Registers, vr)
    19265           (get Mu-registers-unique %eax 0xc "Mu-registers-unique")  # => eax
    19266           8b/-> *eax 0/r32/eax
    19267           # if (var-in-reg[reg]) error
    19268           8b/-> *(edi+eax<<2) 0/r32/eax
    19269           3d/compare-eax-and 0/imm32
    19270           0f 85/jump-if-!= $lookup-var-helper:error2/disp32
    19271         }
    19272 $lookup-var-helper:return:
    19273         # esi = out
    19274         8b/-> *(ebp+0x10) 6/r32/esi
    19275         # *out = *curr
    19276         8b/-> *ebx 0/r32/eax
    19277         89/<- *esi 0/r32/eax
    19278         8b/-> *(ebx+4) 0/r32/eax
    19279         89/<- *(esi+4) 0/r32/eax
    19280         # return
    19281         eb/jump $lookup-var-helper:end/disp8
    19282       }
    19283       # 'name' not yet found; update var-in-reg if v in register
    19284       # . var vr/eax: (addr array byte) = lookup(v->register)
    19285       (lookup *(ecx+0x18) *(ecx+0x1c))  # Var-register Var-register => eax
    19286       # . if (vr == 0) continue
    19287       3d/compare-eax-and 0/imm32
    19288       74/jump-if-= $lookup-var-helper:continue/disp8
    19289       # . var reg/eax: int = get(Registers, vr)
    19290       (get Mu-registers-unique %eax 0xc "Mu-registers-unique")  # => eax
    19291       8b/-> *eax 0/r32/eax
    19292       # . var-in-reg[reg] = v
    19293       89/<- *(edi+eax<<2) 1/r32/ecx
    19294 $lookup-var-helper:continue:
    19295       # curr -= 12
    19296       81 5/subop/subtract %ebx 0xc/imm32
    19297       e9/jump loop/disp32
    19298     }
    19299 $lookup-var-helper:end:
    19300     # . reclaim locals
    19301     81 0/subop/add %esp 0x40/imm32
    19302     # . restore registers
    19303     5f/pop-to-edi
    19304     5e/pop-to-esi
    19305     5b/pop-to-ebx
    19306     5a/pop-to-edx
    19307     59/pop-to-ecx
    19308     58/pop-to-eax
    19309     # . epilogue
    19310     89/<- %esp 5/r32/ebp
    19311     5d/pop-to-ebp
    19312     c3/return
    19313
    19314 $lookup-var-helper:error1:
    19315     (write-buffered *(ebp+0x18) "fn ")
    19316     8b/-> *(ebp+0x14) 0/r32/eax
    19317     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    19318     (write-buffered *(ebp+0x18) %eax)
    19319     (write-buffered *(ebp+0x18) ": malformed stack when looking up '")
    19320     (write-slice-buffered *(ebp+0x18) *(ebp+8))
    19321     (write-buffered *(ebp+0x18) "'\n")
    19322     (flush *(ebp+0x18))
    19323     (stop *(ebp+0x1c) 1)
    19324     # never gets here
    19325
    19326 $lookup-var-helper:error2:
    19327     # eax contains the conflicting var at this point
    19328     (write-buffered *(ebp+0x18) "fn ")
    19329     50/push-eax
    19330     8b/-> *(ebp+0x14) 0/r32/eax
    19331     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    19332     (write-buffered *(ebp+0x18) %eax)
    19333     58/pop-eax
    19334     (write-buffered *(ebp+0x18) ": register ")
    19335     50/push-eax
    19336     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    19337     (write-buffered *(ebp+0x18) %eax)
    19338     58/pop-to-eax
    19339     (write-buffered *(ebp+0x18) " reads var '")
    19340     (write-slice-buffered *(ebp+0x18) *(ebp+8))
    19341     (write-buffered *(ebp+0x18) "' after writing var '")
    19342     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    19343     (write-buffered *(ebp+0x18) %eax)
    19344     (write-buffered *(ebp+0x18) "'\n")
    19345     (flush *(ebp+0x18))
    19346     (stop *(ebp+0x1c) 1)
    19347     # never gets here
    19348
    19349 dump-vars:  # vars: (addr stack live-var)
    19350     # pseudocode:
    19351     #   var curr: (addr handle var) = &vars->data[vars->top - 12]
    19352     #   var min = vars->data
    19353     #   while curr >= min
    19354     #     var v: (handle var) = *curr
    19355     #     print v
    19356     #     curr -= 12
    19357     #
    19358     # . prologue
    19359     55/push-ebp
    19360     89/<- %ebp 4/r32/esp
    19361     # . save registers
    19362     52/push-edx
    19363     53/push-ebx
    19364     56/push-esi
    19365     # esi = vars
    19366     8b/-> *(ebp+8) 6/r32/esi
    19367     # ebx = vars->top
    19368     8b/-> *esi 3/r32/ebx
    19369     # var min/edx: (addr handle var) = vars->data
    19370     8d/copy-address *(esi+8) 2/r32/edx
    19371     # var curr/ebx: (addr handle var) = &vars->data[vars->top - 12]
    19372     8d/copy-address *(esi+ebx-4) 3/r32/ebx  # vars + 8 + vars->type - 12
    19373     {
    19374 $dump-vars:loop:
    19375       # if (curr < min) return
    19376       39/compare %ebx 2/r32/edx
    19377       0f 82/jump-if-addr< break/disp32
    19378       #
    19379       (write-buffered Stderr "  var@")
    19380       (dump-var 2 %ebx)
    19381       # curr -= 12
    19382       81 5/subop/subtract %ebx 0xc/imm32
    19383       e9/jump loop/disp32
    19384     }
    19385 $dump-vars:end:
    19386     # . restore registers
    19387     5e/pop-to-esi
    19388     5b/pop-to-ebx
    19389     5a/pop-to-edx
    19390     # . epilogue
    19391     89/<- %esp 5/r32/ebp
    19392     5d/pop-to-ebp
    19393     c3/return
    19394
    19395 == data
    19396 # Like Registers, but no esp or ebp
    19397 Mu-registers:  # (addr stream {(handle array byte), int})
    19398   # a table is a stream
    19399   0xa8/imm32/write
    19400   0/imm32/read
    19401   0xa8/imm32/length
    19402   # data
    19403   # general-purpose registers
    19404   # it is perfectly ok to use fake alloc-ids -- as long as you never try to reclaim them
    19405   0x11/imm32/alloc-id $Mu-register-eax/imm32 0/imm32
    19406   0x11/imm32/alloc-id $Mu-register-ecx/imm32 1/imm32
    19407   0x11/imm32/alloc-id $Mu-register-edx/imm32 2/imm32
    19408   0x11/imm32/alloc-id $Mu-register-ebx/imm32 3/imm32
    19409   0x11/imm32/alloc-id $Mu-register-esi/imm32 6/imm32
    19410   0x11/imm32/alloc-id $Mu-register-edi/imm32 7/imm32
    19411   # floating-point registers
    19412   0x11/imm32/alloc-id $Mu-register-xmm0/imm32 0/imm32
    19413   0x11/imm32/alloc-id $Mu-register-xmm1/imm32 1/imm32
    19414   0x11/imm32/alloc-id $Mu-register-xmm2/imm32 2/imm32
    19415   0x11/imm32/alloc-id $Mu-register-xmm3/imm32 3/imm32
    19416   0x11/imm32/alloc-id $Mu-register-xmm4/imm32 4/imm32
    19417   0x11/imm32/alloc-id $Mu-register-xmm5/imm32 5/imm32
    19418   0x11/imm32/alloc-id $Mu-register-xmm6/imm32 6/imm32
    19419   0x11/imm32/alloc-id $Mu-register-xmm7/imm32 7/imm32
    19420
    19421 # Like Mu-registers, but with unique codes for integer and floating-point
    19422 # registers.
    19423 # Don't use this for code-generation, only for checking.
    19424 Mu-registers-unique:  # (addr stream {(handle array byte), int})
    19425   # a table is a stream
    19426   0xa8/imm32/write
    19427   0/imm32/read
    19428   0xa8/imm32/length
    19429   # data
    19430   # general-purpose registers
    19431   0x11/imm32/alloc-id $Mu-register-eax/imm32 0/imm32
    19432   0x11/imm32/alloc-id $Mu-register-ecx/imm32 1/imm32
    19433   0x11/imm32/alloc-id $Mu-register-edx/imm32 2/imm32
    19434   0x11/imm32/alloc-id $Mu-register-ebx/imm32 3/imm32
    19435   0x11/imm32/alloc-id $Mu-register-esi/imm32 6/imm32
    19436   0x11/imm32/alloc-id $Mu-register-edi/imm32 7/imm32
    19437   # floating-point registers
    19438   0x11/imm32/alloc-id $Mu-register-xmm0/imm32 8/imm32
    19439   0x11/imm32/alloc-id $Mu-register-xmm1/imm32 9/imm32
    19440   0x11/imm32/alloc-id $Mu-register-xmm2/imm32 0xa/imm32
    19441   0x11/imm32/alloc-id $Mu-register-xmm3/imm32 0xb/imm32
    19442   0x11/imm32/alloc-id $Mu-register-xmm4/imm32 0xc/imm32
    19443   0x11/imm32/alloc-id $Mu-register-xmm5/imm32 0xd/imm32
    19444   0x11/imm32/alloc-id $Mu-register-xmm6/imm32 0xe/imm32
    19445   0x11/imm32/alloc-id $Mu-register-xmm7/imm32 0xf/imm32
    19446
    19447 $Mu-register-eax:
    19448   0x11/imm32/alloc-id
    19449   3/imm32/size
    19450   0x65/e 0x61/a 0x78/x
    19451
    19452 $Mu-register-ecx:
    19453   0x11/imm32/alloc-id
    19454   3/imm32/size
    19455   0x65/e 0x63/c 0x78/x
    19456
    19457 $Mu-register-edx:
    19458   0x11/imm32/alloc-id
    19459   3/imm32/size
    19460   0x65/e 0x64/d 0x78/x
    19461
    19462 $Mu-register-ebx:
    19463   0x11/imm32/alloc-id
    19464   3/imm32/size
    19465   0x65/e 0x62/b 0x78/x
    19466
    19467 $Mu-register-esi:
    19468   0x11/imm32/alloc-id
    19469   3/imm32/size
    19470   0x65/e 0x73/s 0x69/i
    19471
    19472 $Mu-register-edi:
    19473   0x11/imm32/alloc-id
    19474   3/imm32/size
    19475   0x65/e 0x64/d 0x69/i
    19476
    19477 $Mu-register-xmm0:
    19478   0x11/imm32/alloc-id:fake:payload
    19479   # "xmm0"
    19480   0x4/imm32/size
    19481   0x78/x 0x6d/m 0x6d/m 0x30/0
    19482
    19483 $Mu-register-xmm1:
    19484   0x11/imm32/alloc-id:fake:payload
    19485   # "xmm1"
    19486   0x4/imm32/size
    19487   0x78/x 0x6d/m 0x6d/m 0x31/1
    19488
    19489 $Mu-register-xmm2:
    19490   0x11/imm32/alloc-id:fake:payload
    19491   # "xmm2"
    19492   0x4/imm32/size
    19493   0x78/x 0x6d/m 0x6d/m 0x32/2
    19494
    19495 $Mu-register-xmm3:
    19496   0x11/imm32/alloc-id:fake:payload
    19497   # "xmm3"
    19498   0x4/imm32/size
    19499   0x78/x 0x6d/m 0x6d/m 0x33/3
    19500
    19501 $Mu-register-xmm4:
    19502   0x11/imm32/alloc-id:fake:payload
    19503   # "xmm4"
    19504   0x4/imm32/size
    19505   0x78/x 0x6d/m 0x6d/m 0x34/4
    19506
    19507 $Mu-register-xmm5:
    19508   0x11/imm32/alloc-id:fake:payload
    19509   # "xmm5"
    19510   0x4/imm32/size
    19511   0x78/x 0x6d/m 0x6d/m 0x35/5
    19512
    19513 $Mu-register-xmm6:
    19514   0x11/imm32/alloc-id:fake:payload
    19515   # "xmm6"
    19516   0x4/imm32/size
    19517   0x78/x 0x6d/m 0x6d/m 0x36/6
    19518
    19519 $Mu-register-xmm7:
    19520   0x11/imm32/alloc-id:fake:payload
    19521   # "xmm7"
    19522   0x4/imm32/size
    19523   0x78/x 0x6d/m 0x6d/m 0x37/7
    19524
    19525 == code
    19526
    19527 # push 'out' to 'vars' if not already there; it's assumed to be a fn output
    19528 maybe-define-var:  # out: (handle var), vars: (addr stack live-var)
    19529     # . prologue
    19530     55/push-ebp
    19531     89/<- %ebp 4/r32/esp
    19532     # . save registers
    19533     50/push-eax
    19534     # var out-addr/eax: (addr var)
    19535     (lookup *(ebp+8) *(ebp+0xc))  # => eax
    19536     #
    19537     (binding-exists? %eax *(ebp+0x10))  # => eax
    19538     3d/compare-eax-and 0/imm32/false
    19539     75/jump-if-!= $maybe-define-var:end/disp8
    19540     # otherwise update vars
    19541     (push *(ebp+0x10) *(ebp+8))
    19542     (push *(ebp+0x10) *(ebp+0xc))
    19543     (push *(ebp+0x10) 0)  # 'out' is always a fn output; never spill it
    19544 $maybe-define-var:end:
    19545     # . restore registers
    19546     58/pop-to-eax
    19547     # . epilogue
    19548     89/<- %esp 5/r32/ebp
    19549     5d/pop-to-ebp
    19550     c3/return
    19551
    19552 # simpler version of lookup-var-helper
    19553 binding-exists?:  # target: (addr var), vars: (addr stack live-var) -> result/eax: boolean
    19554     # pseudocode:
    19555     #   var curr: (addr handle var) = &vars->data[vars->top - 12]
    19556     #   var min = vars->data
    19557     #   while curr >= min
    19558     #     var v: (handle var) = *curr
    19559     #     if v->name == target->name
    19560     #       return true
    19561     #     curr -= 12
    19562     #   return false
    19563     #
    19564     # . prologue
    19565     55/push-ebp
    19566     89/<- %ebp 4/r32/esp
    19567     # . save registers
    19568     51/push-ecx
    19569     52/push-edx
    19570     56/push-esi
    19571     # var target-name/ecx: (addr array byte) = lookup(target->name)
    19572     8b/-> *(ebp+8) 0/r32/eax
    19573     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    19574     89/<- %ecx 0/r32/eax
    19575     # esi = vars
    19576     8b/-> *(ebp+0xc) 6/r32/esi
    19577     # eax = vars->top
    19578     8b/-> *esi 0/r32/eax
    19579     # var min/edx: (addr handle var) = vars->data
    19580     8d/copy-address *(esi+8) 2/r32/edx
    19581     # var curr/esi: (addr handle var) = &vars->data[vars->top - 12]
    19582     8d/copy-address *(esi+eax-4) 6/r32/esi  # vars + 8 + vars->type - 12
    19583     {
    19584 $binding-exists?:loop:
    19585       # if (curr < min) return
    19586       39/compare %esi 2/r32/edx
    19587       0f 82/jump-if-addr< break/disp32
    19588       # var v/eax: (addr var) = lookup(*curr)
    19589       (lookup *esi *(esi+4))  # => eax
    19590       # var vn/eax: (addr array byte) = lookup(v->name)
    19591       (lookup *eax *(eax+4))  # Var-name Var-name => eax
    19592       # if (vn == target-name) return true
    19593       (string-equal? %ecx %eax)  # => eax
    19594       3d/compare-eax-and 0/imm32/false
    19595       75/jump-if-!= $binding-exists?:end/disp8  # eax already contains true
    19596       # curr -= 12
    19597       81 5/subop/subtract %esi 0xc/imm32
    19598       e9/jump loop/disp32
    19599     }
    19600     b8/copy-to-eax 0/imm32/false
    19601 $binding-exists?:end:
    19602     # . restore registers
    19603     5e/pop-to-esi
    19604     5a/pop-to-edx
    19605     59/pop-to-ecx
    19606     # . epilogue
    19607     89/<- %esp 5/r32/ebp
    19608     5d/pop-to-ebp
    19609     c3/return
    19610
    19611 test-parse-mu-stmt:
    19612     # . prologue
    19613     55/push-ebp
    19614     89/<- %ebp 4/r32/esp
    19615     # setup
    19616     8b/-> *Primitive-type-ids 0/r32/eax
    19617     89/<- *Type-id 0/r32/eax  # stream-write
    19618     (clear-stream _test-input-stream)
    19619     (write _test-input-stream "increment n\n")
    19620     # var vars/ecx: (stack (addr var) 16)
    19621     81 5/subop/subtract %esp 0xc0/imm32
    19622     68/push 0xc0/imm32/size
    19623     68/push 0/imm32/top
    19624     89/<- %ecx 4/r32/esp
    19625     (clear-stack %ecx)
    19626     # var v/edx: (handle var)
    19627     68/push 0/imm32
    19628     68/push 0/imm32
    19629     89/<- %edx 4/r32/esp
    19630     # var s/eax: (handle array byte)
    19631     68/push 0/imm32
    19632     68/push 0/imm32
    19633     89/<- %eax 4/r32/esp
    19634     # v = new var("n")
    19635     (copy-array Heap "n" %eax)
    19636     (new-var Heap *eax *(eax+4) %edx)
    19637     #
    19638     (push %ecx *edx)
    19639     (push %ecx *(edx+4))
    19640     (push %ecx 0)
    19641     # var out/eax: (handle stmt)
    19642     68/push 0/imm32
    19643     68/push 0/imm32
    19644     89/<- %eax 4/r32/esp
    19645     # convert
    19646     (parse-mu-stmt _test-input-stream %ecx 0 %eax Stderr 0)
    19647     # var out-addr/edx: (addr stmt) = lookup(*out)
    19648     (lookup *eax *(eax+4))  # => eax
    19649     89/<- %edx 0/r32/eax
    19650     # out->tag
    19651     (check-ints-equal *edx 1 "F - test-parse-mu-stmt/tag")  # Stmt-tag is Stmt1
    19652     # out->operation
    19653     (lookup *(edx+4) *(edx+8))  # Stmt1-operation Stmt1-operation => eax
    19654     (check-strings-equal %eax "increment" "F - test-parse-mu-stmt/name")  # Stmt1-operation
    19655     # out->inouts->value->name
    19656     # . eax = out->inouts
    19657     (lookup *(edx+0xc) *(edx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    19658     # . eax = out->inouts->value
    19659     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    19660     # . eax = out->inouts->value->name
    19661     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    19662     # .
    19663     (check-strings-equal %eax "n" "F - test-parse-mu-stmt/inout:0")
    19664     # . epilogue
    19665     89/<- %esp 5/r32/ebp
    19666     5d/pop-to-ebp
    19667     c3/return
    19668
    19669 test-parse-mu-stmt-with-comma:
    19670     # . prologue
    19671     55/push-ebp
    19672     89/<- %ebp 4/r32/esp
    19673     # setup
    19674     8b/-> *Primitive-type-ids 0/r32/eax
    19675     89/<- *Type-id 0/r32/eax  # stream-write
    19676     (clear-stream _test-input-stream)
    19677     (write _test-input-stream "copy-to n, 3\n")
    19678     # var vars/ecx: (stack (addr var) 16)
    19679     81 5/subop/subtract %esp 0xc0/imm32
    19680     68/push 0xc0/imm32/size
    19681     68/push 0/imm32/top
    19682     89/<- %ecx 4/r32/esp
    19683     (clear-stack %ecx)
    19684     # var v/edx: (handle var)
    19685     68/push 0/imm32
    19686     68/push 0/imm32
    19687     89/<- %edx 4/r32/esp
    19688     # var s/eax: (handle array byte)
    19689     68/push 0/imm32
    19690     68/push 0/imm32
    19691     89/<- %eax 4/r32/esp
    19692     # v = new var("n")
    19693     (copy-array Heap "n" %eax)
    19694     (new-var Heap *eax *(eax+4) %edx)
    19695     #
    19696     (push %ecx *edx)
    19697     (push %ecx *(edx+4))
    19698     (push %ecx 0)
    19699     # var out/eax: (handle stmt)
    19700     68/push 0/imm32
    19701     68/push 0/imm32
    19702     89/<- %eax 4/r32/esp
    19703     # convert
    19704     (parse-mu-stmt _test-input-stream %ecx 0 %eax Stderr 0)
    19705     # var out-addr/edx: (addr stmt) = lookup(*out)
    19706     (lookup *eax *(eax+4))  # => eax
    19707     89/<- %edx 0/r32/eax
    19708     # out->tag
    19709     (check-ints-equal *edx 1 "F - test-parse-mu-stmt-with-comma/tag")  # Stmt-tag is Stmt1
    19710     # out->operation
    19711     (lookup *(edx+4) *(edx+8))  # Stmt1-operation Stmt1-operation => eax
    19712     (check-strings-equal %eax "copy-to" "F - test-parse-mu-stmt-with-comma/name")  # Stmt1-operation
    19713     # out->inouts->value->name
    19714     # . eax = out->inouts
    19715     (lookup *(edx+0xc) *(edx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    19716     # . eax = out->inouts->value
    19717     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    19718     # . eax = out->inouts->value->name
    19719     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    19720     # .
    19721     (check-strings-equal %eax "n" "F - test-parse-mu-stmt-with-comma/inout:0")
    19722     # . epilogue
    19723     89/<- %esp 5/r32/ebp
    19724     5d/pop-to-ebp
    19725     c3/return
    19726
    19727 new-var:  # ad: (addr allocation-descriptor), name: (handle array byte), out: (addr handle var)
    19728     # . prologue
    19729     55/push-ebp
    19730     89/<- %ebp 4/r32/esp
    19731     # . save registers
    19732     50/push-eax
    19733     51/push-ecx
    19734     # ecx = out
    19735     8b/-> *(ebp+0x14) 1/r32/ecx
    19736     #
    19737     (allocate *(ebp+8) *Var-size %ecx)
    19738     # var out-addr/eax: (addr var)
    19739     (lookup *ecx *(ecx+4))  # => eax
    19740     # out-addr->name = name
    19741     8b/-> *(ebp+0xc) 1/r32/ecx
    19742     89/<- *eax 1/r32/ecx  # Var-name
    19743     8b/-> *(ebp+0x10) 1/r32/ecx
    19744     89/<- *(eax+4) 1/r32/ecx  # Var-name
    19745 #?     (write-buffered Stderr "var ")
    19746 #?     (lookup *(ebp+0xc) *(ebp+0x10))
    19747 #?     (write-buffered Stderr %eax)
    19748 #?     (write-buffered Stderr " at ")
    19749 #?     8b/-> *(ebp+0x14) 1/r32/ecx
    19750 #?     (lookup *ecx *(ecx+4))  # => eax
    19751 #?     (write-int32-hex-buffered Stderr %eax)
    19752 #?     (write-buffered Stderr Newline)
    19753 #?     (flush Stderr)
    19754 $new-var:end:
    19755     # . restore registers
    19756     59/pop-to-ecx
    19757     58/pop-to-eax
    19758     # . epilogue
    19759     89/<- %esp 5/r32/ebp
    19760     5d/pop-to-ebp
    19761     c3/return
    19762
    19763 # WARNING: modifies name
    19764 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)
    19765     # . prologue
    19766     55/push-ebp
    19767     89/<- %ebp 4/r32/esp
    19768     # . save registers
    19769     50/push-eax
    19770     51/push-ecx
    19771     # first strip out metadata
    19772     8b/-> *(ebp+0xc) 1/r32/ecx
    19773     (next-token-from-slice *ecx *(ecx+4) 0x2f *(ebp+0xc))
    19774     # if (!is-hex-int?(name)) abort
    19775     (hex-int? *(ebp+0xc))  # => eax
    19776     3d/compare-eax-and 0/imm32/false
    19777     0f 84/jump-if-= $new-literal-integer:abort/disp32
    19778     # a little more error-checking
    19779     (check-mu-hex-int *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
    19780     # out = new var(s)
    19781     (new-var-from-slice *(ebp+8) *(ebp+0xc) *(ebp+0x10))
    19782     # var out-addr/ecx: (addr var) = lookup(*out)
    19783     8b/-> *(ebp+0x10) 0/r32/eax
    19784     (lookup *eax *(eax+4))  # => eax
    19785     89/<- %ecx 0/r32/eax
    19786     # out-addr->block-depth = *Curr-block-depth
    19787     8b/-> *Curr-block-depth 0/r32/eax
    19788     89/<- *(ecx+0x10) 0/r32/eax  # Var-block-depth
    19789     # out-addr->type = new tree()
    19790     8d/copy-address *(ecx+8) 0/r32/eax  # Var-type
    19791     (allocate *(ebp+8) *Type-tree-size %eax)
    19792     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
    19793     c7 0/subop/copy *eax 1/imm32/true  # Type-tree-is-atom
    19794     # nothing else to do; default type is 'literal'
    19795 $new-literal-integer:end:
    19796     # . reclaim locals
    19797     81 0/subop/add %esp 8/imm32
    19798     # . restore registers
    19799     59/pop-to-ecx
    19800     58/pop-to-eax
    19801     # . epilogue
    19802     89/<- %esp 5/r32/ebp
    19803     5d/pop-to-ebp
    19804     c3/return
    19805
    19806 $new-literal-integer:abort:
    19807     (write-buffered *(ebp+0x18) "fn ")
    19808     8b/-> *(ebp+0x14) 0/r32/eax
    19809     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    19810     (write-buffered *(ebp+0x18) %eax)
    19811     (write-buffered *(ebp+0x18) ": variable '")
    19812     (write-slice-buffered *(ebp+0x18) *(ebp+0xc))
    19813     (write-buffered *(ebp+0x18) "' cannot begin with a digit (or do you have a typo in a number?)\n")
    19814     (flush *(ebp+0x18))
    19815     (stop *(ebp+0x1c) 1)
    19816     # never gets here
    19817
    19818 # precondition: name is a valid hex integer; require a '0x' prefix
    19819 check-mu-hex-int:  # name: (addr slice), err: (addr buffered-file), ed: (addr exit-descriptor)
    19820     # . prologue
    19821     55/push-ebp
    19822     89/<- %ebp 4/r32/esp
    19823     # . save registers
    19824     50/push-eax
    19825     51/push-ecx
    19826     52/push-edx
    19827     # ecx = name
    19828     8b/-> *(ebp+8) 1/r32/ecx
    19829     # var start/edx: (addr byte) = name->start
    19830     8b/-> *ecx 2/r32/edx
    19831     # if (*start == '-') ++start
    19832     b8/copy-to-eax 0/imm32
    19833     8a/copy-byte *edx 0/r32/AL
    19834     3d/compare-eax-and 0x2d/imm32/dash
    19835     {
    19836       75/jump-if-!= break/disp8
    19837       42/increment-edx
    19838     }
    19839     # var end/ecx: (addr byte) = name->end
    19840     8b/-> *(ecx+4) 1/r32/ecx
    19841     # var len/eax: int = name->end - name->start
    19842     89/<- %eax 1/r32/ecx
    19843     29/subtract-from %eax 2/r32/edx
    19844     # if (len <= 1) return
    19845     3d/compare-eax-with 1/imm32
    19846     0f 8e/jump-if-<= $check-mu-hex-int:end/disp32
    19847 $check-mu-hex-int:length->-1:
    19848     # if slice-starts-with?({start, end}, "0x") return
    19849     # . var tmp = {start, end}
    19850     51/push-ecx
    19851     52/push-edx
    19852     89/<- %eax 4/r32/esp
    19853     # .
    19854     (slice-starts-with? %eax "0x")  # => eax
    19855     # . reclaim tmp
    19856     81 0/subop/add %esp 8/imm32
    19857     # .
    19858     3d/compare-eax-with 0/imm32/false
    19859     75/jump-if-!= $check-mu-hex-int:end/disp8
    19860 $check-mu-hex-int:abort:
    19861     # otherwise abort
    19862     (write-buffered *(ebp+0xc) "literal integers are always hex in Mu; start '")
    19863     (write-slice-buffered *(ebp+0xc) *(ebp+8))
    19864     (write-buffered *(ebp+0xc) "' with a '0x' to be unambiguous, converting it to hexadecimal as necessary.\n")
    19865     (flush *(ebp+0xc))
    19866     (stop *(ebp+0x10) 1)
    19867 $check-mu-hex-int:end:
    19868     # . restore registers
    19869     5a/pop-to-edx
    19870     59/pop-to-ecx
    19871     58/pop-to-eax
    19872     # . epilogue
    19873     89/<- %esp 5/r32/ebp
    19874     5d/pop-to-ebp
    19875     c3/return
    19876
    19877 new-literal:  # ad: (addr allocation-descriptor), name: (addr slice), out: (addr handle var)
    19878     # . prologue
    19879     55/push-ebp
    19880     89/<- %ebp 4/r32/esp
    19881     # . save registers
    19882     50/push-eax
    19883     51/push-ecx
    19884     # var s/ecx: (handle array byte)
    19885     68/push 0/imm32
    19886     68/push 0/imm32
    19887     89/<- %ecx 4/r32/esp
    19888     # s = slice-to-string(name)
    19889     (slice-to-string Heap *(ebp+0xc) %ecx)
    19890     # allocate to out
    19891     (new-var *(ebp+8) *ecx *(ecx+4) *(ebp+0x10))
    19892     # var out-addr/ecx: (addr var) = lookup(*out)
    19893     8b/-> *(ebp+0x10) 1/r32/ecx
    19894     (lookup *ecx *(ecx+4))  # => eax
    19895     89/<- %ecx 0/r32/eax
    19896     # out-addr->block-depth = *Curr-block-depth
    19897     8b/-> *Curr-block-depth 0/r32/eax
    19898     89/<- *(ecx+0x10) 0/r32/eax  # Var-block-depth
    19899     # out-addr->type/eax = new type
    19900     8d/copy-address *(ecx+8) 0/r32/eax  # Var-type
    19901     (allocate *(ebp+8) *Type-tree-size %eax)
    19902     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
    19903     # nothing else to do; default type is 'literal'
    19904     c7 0/subop/copy *eax 1/imm32/true  # Type-tree-is-atom
    19905 $new-literal:end:
    19906     # . reclaim locals
    19907     81 0/subop/add %esp 8/imm32
    19908     # . restore registers
    19909     59/pop-to-ecx
    19910     58/pop-to-eax
    19911     # . epilogue
    19912     89/<- %esp 5/r32/ebp
    19913     5d/pop-to-ebp
    19914     c3/return
    19915
    19916 new-literal-string:  # ad: (addr allocation-descriptor), name: (addr slice), out: (addr handle var)
    19917     # . prologue
    19918     55/push-ebp
    19919     89/<- %ebp 4/r32/esp
    19920     # . save registers
    19921     50/push-eax
    19922     51/push-ecx
    19923     # var s/ecx: (handle array byte)
    19924     68/push 0/imm32
    19925     68/push 0/imm32
    19926     89/<- %ecx 4/r32/esp
    19927     # s = slice-to-string(name)
    19928     (slice-to-string Heap *(ebp+0xc) %ecx)
    19929     # allocate to out
    19930     (new-var *(ebp+8) *ecx *(ecx+4) *(ebp+0x10))
    19931     # var out-addr/ecx: (addr var) = lookup(*out)
    19932     8b/-> *(ebp+0x10) 1/r32/ecx
    19933     (lookup *ecx *(ecx+4))  # => eax
    19934     89/<- %ecx 0/r32/eax
    19935     # out-addr->block-depth = *Curr-block-depth
    19936     8b/-> *Curr-block-depth 0/r32/eax
    19937     89/<- *(ecx+0x10) 0/r32/eax  # Var-block-depth
    19938     # out-addr->type/eax = new type
    19939     8d/copy-address *(ecx+8) 0/r32/eax  # Var-type
    19940     (allocate *(ebp+8) *Type-tree-size %eax)
    19941     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
    19942     # out-addr->type->value = literal-string
    19943     c7 0/subop/copy *(eax+4) 0x10/imm32/type-id-string-literal  # Type-tree-value
    19944     # out-addr->type->is-atom? = true
    19945     c7 0/subop/copy *eax 1/imm32/true  # Type-tree-is-atom
    19946 $new-literal-string:end:
    19947     # . reclaim locals
    19948     81 0/subop/add %esp 8/imm32
    19949     # . restore registers
    19950     59/pop-to-ecx
    19951     58/pop-to-eax
    19952     # . epilogue
    19953     89/<- %esp 5/r32/ebp
    19954     5d/pop-to-ebp
    19955     c3/return
    19956
    19957 new-var-from-slice:  # ad: (addr allocation-descriptor), name: (addr slice), out: (addr handle var)
    19958     # . prologue
    19959     55/push-ebp
    19960     89/<- %ebp 4/r32/esp
    19961     # . save registers
    19962     51/push-ecx
    19963     # var tmp/ecx: (handle array byte)
    19964     68/push 0/imm32
    19965     68/push 0/imm32
    19966     89/<- %ecx 4/r32/esp
    19967     # tmp = slice-to-string(name)
    19968     (slice-to-string Heap *(ebp+0xc) %ecx)
    19969     # out = new-var(tmp)
    19970     (new-var *(ebp+8) *ecx *(ecx+4) *(ebp+0x10))
    19971 $new-var-from-slice:end:
    19972     # . reclaim locals
    19973     81 0/subop/add %esp 8/imm32
    19974     # . restore registers
    19975     59/pop-to-ecx
    19976     # . epilogue
    19977     89/<- %esp 5/r32/ebp
    19978     5d/pop-to-ebp
    19979     c3/return
    19980
    19981 new-var-def:  # ad: (addr allocation-descriptor), var: (handle var), out: (addr handle stmt)
    19982     # . prologue
    19983     55/push-ebp
    19984     89/<- %ebp 4/r32/esp
    19985     # . save registers
    19986     50/push-eax
    19987     51/push-ecx
    19988     #
    19989     (allocate *(ebp+8) *Stmt-size *(ebp+0x14))
    19990     # var out-addr/eax: (addr stmt) = lookup(*out)
    19991     8b/-> *(ebp+0x14) 0/r32/eax
    19992     (lookup *eax *(eax+4))  # => eax
    19993     # out-addr->tag = stmt
    19994     c7 0/subop/copy *eax 2/imm32/tag/var-on-stack  # Stmt-tag
    19995     # result->var = var
    19996     8b/-> *(ebp+0xc) 1/r32/ecx
    19997     89/<- *(eax+4) 1/r32/ecx  # Vardef-var
    19998     8b/-> *(ebp+0x10) 1/r32/ecx
    19999     89/<- *(eax+8) 1/r32/ecx  # Vardef-var
    20000 $new-var-def:end:
    20001     # . restore registers
    20002     59/pop-to-ecx
    20003     58/pop-to-eax
    20004     # . epilogue
    20005     89/<- %esp 5/r32/ebp
    20006     5d/pop-to-ebp
    20007     c3/return
    20008
    20009 new-reg-var-def:  # ad: (addr allocation-descriptor), var: (handle var), out: (addr handle stmt)
    20010     # . prologue
    20011     55/push-ebp
    20012     89/<- %ebp 4/r32/esp
    20013     # . save registers
    20014     50/push-eax
    20015     # eax = out
    20016     8b/-> *(ebp+0x14) 0/r32/eax
    20017     #
    20018     (allocate *(ebp+8) *Stmt-size %eax)
    20019     # var out-addr/eax: (addr stmt) = lookup(*out)
    20020     (lookup *eax *(eax+4))  # => eax
    20021     # set tag
    20022     c7 0/subop/copy *eax 3/imm32/tag/var-in-register  # Stmt-tag
    20023     # set output
    20024     8d/copy-address *(eax+0x14) 0/r32/eax  # Regvardef-outputs
    20025     (append-stmt-var Heap  *(ebp+0xc) *(ebp+0x10)  0 0  0  %eax)
    20026 $new-reg-var-def:end:
    20027     # . restore registers
    20028     58/pop-to-eax
    20029     # . epilogue
    20030     89/<- %esp 5/r32/ebp
    20031     5d/pop-to-ebp
    20032     c3/return
    20033
    20034 append-list:  # ad: (addr allocation-descriptor), value: (handle _type), list: (handle list _type), out: (addr handle list _type)
    20035     # . prologue
    20036     55/push-ebp
    20037     89/<- %ebp 4/r32/esp
    20038     # . save registers
    20039     50/push-eax
    20040     51/push-ecx
    20041     57/push-edi
    20042     # edi = out
    20043     8b/-> *(ebp+0x1c) 7/r32/edi
    20044     # *out = new list
    20045     (allocate *(ebp+8) *List-size %edi)
    20046     # var out-addr/edi: (addr list _type) = lookup(*out)
    20047     (lookup *edi *(edi+4))  # => eax
    20048     89/<- %edi 0/r32/eax
    20049     # out-addr->value = value
    20050     8b/-> *(ebp+0xc) 0/r32/eax
    20051     89/<- *edi 0/r32/eax  # List-value
    20052     8b/-> *(ebp+0x10) 0/r32/eax
    20053     89/<- *(edi+4) 0/r32/eax  # List-value
    20054     # if (list == null) return
    20055     81 7/subop/compare *(ebp+0x14) 0/imm32
    20056     74/jump-if-= $append-list:end/disp8
    20057     # otherwise append
    20058 $append-list:non-empty-list:
    20059     # var curr/eax: (addr list _type) = lookup(list)
    20060     (lookup *(ebp+0x14) *(ebp+0x18))  # => eax
    20061     # while (curr->next != null) curr = curr->next
    20062     {
    20063       81 7/subop/compare *(eax+8) 0/imm32  # List-next
    20064       74/jump-if-= break/disp8
    20065       # curr = lookup(curr->next)
    20066       (lookup *(eax+8) *(eax+0xc))  # List-next, List-next => eax
    20067       #
    20068       eb/jump loop/disp8
    20069     }
    20070     # edi = out
    20071     8b/-> *(ebp+0x1c) 7/r32/edi
    20072     # curr->next = out
    20073     8b/-> *edi 1/r32/ecx
    20074     89/<- *(eax+8) 1/r32/ecx  # List-next
    20075     8b/-> *(edi+4) 1/r32/ecx
    20076     89/<- *(eax+0xc) 1/r32/ecx  # List-next
    20077     # out = list
    20078     8b/-> *(ebp+0x14) 1/r32/ecx
    20079     89/<- *edi 1/r32/ecx
    20080     8b/-> *(ebp+0x18) 1/r32/ecx
    20081     89/<- *(edi+4) 1/r32/ecx
    20082 $append-list:end:
    20083     # . restore registers
    20084     5f/pop-to-edi
    20085     59/pop-to-ecx
    20086     58/pop-to-eax
    20087     # . epilogue
    20088     89/<- %esp 5/r32/ebp
    20089     5d/pop-to-ebp
    20090     c3/return
    20091
    20092 append-stmt-var:  # ad: (addr allocation-descriptor), v: (handle var), vars: (handle stmt-var), is-deref?: boolean, out: (addr handle stmt-var)
    20093     # . prologue
    20094     55/push-ebp
    20095     89/<- %ebp 4/r32/esp
    20096     # . save registers
    20097     50/push-eax
    20098     51/push-ecx
    20099     57/push-edi
    20100     # edi = out
    20101     8b/-> *(ebp+0x20) 7/r32/edi
    20102     # out = new stmt-var
    20103     (allocate *(ebp+8) *Stmt-var-size %edi)
    20104     # var out-addr/ecx: (addr stmt-var) = lookup(*out)
    20105     (lookup *edi *(edi+4))  # => eax
    20106     89/<- %ecx 0/r32/eax
    20107     # out-addr->value = v
    20108     8b/-> *(ebp+0xc) 0/r32/eax
    20109     89/<- *ecx 0/r32/eax  # Stmt-var-value
    20110     8b/-> *(ebp+0x10) 0/r32/eax
    20111     89/<- *(ecx+4) 0/r32/eax  # Stmt-var-value
    20112     # out-addr->is-deref? = is-deref?
    20113     8b/-> *(ebp+0x1c) 0/r32/eax
    20114     89/<- *(ecx+0x10) 0/r32/eax  # Stmt-var-is-deref
    20115     # if (vars == null) return result
    20116     81 7/subop/compare *(ebp+0x14) 0/imm32/null
    20117     74/jump-if-= $append-stmt-var:end/disp8
    20118     # otherwise append
    20119     # var curr/eax: (addr stmt-var) = lookup(vars)
    20120     (lookup *(ebp+0x14) *(ebp+0x18))  # => eax
    20121     # while (curr->next != null) curr = curr->next
    20122     {
    20123       81 7/subop/compare *(eax+8) 0/imm32  # Stmt-var-next
    20124       74/jump-if-= break/disp8
    20125       # curr = lookup(curr->next)
    20126       (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next, Stmt-var-next => eax
    20127       #
    20128       eb/jump loop/disp8
    20129     }
    20130     # curr->next = out
    20131     8b/-> *edi 1/r32/ecx
    20132     89/<- *(eax+8) 1/r32/ecx  # Stmt-var-next
    20133     8b/-> *(edi+4) 1/r32/ecx
    20134     89/<- *(eax+0xc) 1/r32/ecx  # Stmt-var-next
    20135     # out = vars
    20136     8b/-> *(ebp+0x14) 1/r32/ecx
    20137     89/<- *edi 1/r32/ecx
    20138     8b/-> *(ebp+0x18) 1/r32/ecx
    20139     89/<- *(edi+4) 1/r32/ecx
    20140 $append-stmt-var:end:
    20141     # . restore registers
    20142     5f/pop-to-edi
    20143     59/pop-to-ecx
    20144     58/pop-to-eax
    20145     # . epilogue
    20146     89/<- %esp 5/r32/ebp
    20147     5d/pop-to-ebp
    20148     c3/return
    20149
    20150 append-to-block:  # ad: (addr allocation-descriptor), block: (addr block), x: (handle stmt)
    20151     # . prologue
    20152     55/push-ebp
    20153     89/<- %ebp 4/r32/esp
    20154     # . save registers
    20155     50/push-eax
    20156     56/push-esi
    20157     # esi = block
    20158     8b/-> *(ebp+0xc) 6/r32/esi
    20159     # block->stmts = append(x, block->stmts)
    20160     8d/copy-address *(esi+4) 0/r32/eax  # Block-stmts
    20161     (append-list *(ebp+8)  *(ebp+0x10) *(ebp+0x14)  *(esi+4) *(esi+8)  %eax)  # ad, x, x, Block-stmts, Block-stmts
    20162 $append-to-block:end:
    20163     # . restore registers
    20164     5e/pop-to-esi
    20165     58/pop-to-eax
    20166     # . epilogue
    20167     89/<- %esp 5/r32/ebp
    20168     5d/pop-to-ebp
    20169     c3/return
    20170
    20171 ## Parsing types
    20172 # We need to create metadata on user-defined types, and we need to use this
    20173 # metadata as we parse instructions.
    20174 # However, we also want to allow types to be used before their definitions.
    20175 # This means we can't ever assume any type data structures exist.
    20176
    20177 lookup-or-create-constant:  # container: (addr stmt-var), field-name: (addr slice), out: (addr handle var)
    20178     # . prologue
    20179     55/push-ebp
    20180     89/<- %ebp 4/r32/esp
    20181     # . save registers
    20182     50/push-eax
    20183     56/push-esi
    20184     # var container-type/esi: type-id
    20185     (container-type *(ebp+8))  # => eax
    20186     89/<- %esi 0/r32/eax
    20187     # var tmp/eax: (handle typeinfo) = find-or-create-typeinfo(container-type)
    20188     68/push 0/imm32
    20189     68/push 0/imm32
    20190     89/<- %eax 4/r32/esp
    20191     (find-or-create-typeinfo %esi %eax)
    20192     # var tmp-addr/eax: (addr typeinfo) = lookup(tmp)
    20193     (lookup *eax *(eax+4))  # => eax
    20194     # result = find-or-create-typeinfo-output-var(typeinfo, field-name)
    20195 #?     (write-buffered Stderr "constant: ")
    20196 #?     (write-slice-buffered Stderr *(ebp+0xc))
    20197 #?     (write-buffered Stderr Newline)
    20198 #?     (flush Stderr)
    20199     (find-or-create-typeinfo-output-var %eax *(ebp+0xc) *(ebp+0x10))
    20200 #?     8b/-> *(ebp+0x10) 0/r32/eax
    20201 #?     (write-buffered Stderr "@")
    20202 #?     (lookup *eax *(eax+4))
    20203 #?     (write-int32-hex-buffered Stderr %eax)
    20204 #?     (lookup *eax *(eax+4))
    20205 #?     (write-buffered Stderr %eax)
    20206 #?     (write-buffered Stderr Newline)
    20207 #?     (flush Stderr)
    20208 #?     (write-buffered Stderr "offset: ")
    20209 #?     8b/-> *(eax+0x14) 0/r32/eax
    20210 #?     (write-int32-hex-buffered Stderr %eax)
    20211 #?     (write-buffered Stderr Newline)
    20212 #?     (flush Stderr)
    20213 $lookup-or-create-constant:end:
    20214     # . reclaim locals
    20215     81 0/subop/add %esp 8/imm32
    20216     # . restore registers
    20217     5e/pop-to-esi
    20218     58/pop-to-eax
    20219     # . epilogue
    20220     89/<- %esp 5/r32/ebp
    20221     5d/pop-to-ebp
    20222     c3/return
    20223
    20224 # if addr var:
    20225 #   container->var->type->right->left->value
    20226 # otherwise
    20227 #   container->var->type->value
    20228 container-type:  # container: (addr stmt-var) -> result/eax: type-id
    20229     # . prologue
    20230     55/push-ebp
    20231     89/<- %ebp 4/r32/esp
    20232     #
    20233     8b/-> *(ebp+8) 0/r32/eax
    20234     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    20235     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    20236     {
    20237       81 7/subop/compare *(eax+8) 0/imm32  # Type-tree-right
    20238       74/jump-if-= break/disp8
    20239       (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
    20240       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    20241     }
    20242     8b/-> *(eax+4) 0/r32/eax  # Type-tree-value
    20243 $container-type:end:
    20244     # . epilogue
    20245     89/<- %esp 5/r32/ebp
    20246     5d/pop-to-ebp
    20247     c3/return
    20248
    20249 container?:  # t: type-id -> result/eax: boolean
    20250     # . prologue
    20251     55/push-ebp
    20252     89/<- %ebp 4/r32/esp
    20253     #
    20254     8b/-> *(ebp+8) 0/r32/eax
    20255     c1/shift 4/subop/left %eax 2/imm8
    20256     3b/compare 0/r32/eax *Primitive-type-ids
    20257     0f 9d/set-if->= %al
    20258     25/and-eax-with 0xff/imm32
    20259 $container?:end:
    20260     # . epilogue
    20261     89/<- %esp 5/r32/ebp
    20262     5d/pop-to-ebp
    20263     c3/return
    20264
    20265 find-or-create-typeinfo:  # t: type-id, out: (addr handle typeinfo)
    20266     # . prologue
    20267     55/push-ebp
    20268     89/<- %ebp 4/r32/esp
    20269     # . save registers
    20270     50/push-eax
    20271     51/push-ecx
    20272     52/push-edx
    20273     57/push-edi
    20274     # edi = out
    20275     8b/-> *(ebp+0xc) 7/r32/edi
    20276     # var fields/ecx: (handle table (handle array byte) (handle typeinfo-entry))
    20277     68/push 0/imm32
    20278     68/push 0/imm32
    20279     89/<- %ecx 4/r32/esp
    20280     # find-typeinfo(t, out)
    20281     (find-typeinfo *(ebp+8) %edi)
    20282     {
    20283       # if (*out != 0) break
    20284       81 7/subop/compare *edi 0/imm32
    20285       0f 85/jump-if-!= break/disp32
    20286 $find-or-create-typeinfo:create:
    20287       # *out = allocate
    20288       (allocate Heap *Typeinfo-size %edi)
    20289       # var tmp/eax: (addr typeinfo) = lookup(*out)
    20290       (lookup *edi *(edi+4))  # => eax
    20291 #?     (write-buffered Stderr "created typeinfo at ")
    20292 #?     (write-int32-hex-buffered Stderr %eax)
    20293 #?     (write-buffered Stderr " for type-id ")
    20294 #?     (write-int32-hex-buffered Stderr *(ebp+8))
    20295 #?     (write-buffered Stderr Newline)
    20296 #?     (flush Stderr)
    20297       # tmp->id = t
    20298       8b/-> *(ebp+8) 2/r32/edx
    20299       89/<- *eax 2/r32/edx  # Typeinfo-id
    20300       # tmp->fields = new table
    20301       # . fields = new table
    20302       (new-stream Heap 0x40 *Typeinfo-fields-row-size %ecx)
    20303       # . tmp->fields = fields
    20304       8b/-> *ecx 2/r32/edx
    20305       89/<- *(eax+4) 2/r32/edx  # Typeinfo-fields
    20306       8b/-> *(ecx+4) 2/r32/edx
    20307       89/<- *(eax+8) 2/r32/edx  # Typeinfo-fields
    20308       # tmp->next = Program->types
    20309       8b/-> *_Program-types 1/r32/ecx
    20310       89/<- *(eax+0x10) 1/r32/ecx  # Typeinfo-next
    20311       8b/-> *_Program-types->payload 1/r32/ecx
    20312       89/<- *(eax+0x14) 1/r32/ecx  # Typeinfo-next
    20313       # Program->types = out
    20314       8b/-> *edi 1/r32/ecx
    20315       89/<- *_Program-types 1/r32/ecx
    20316       8b/-> *(edi+4) 1/r32/ecx
    20317       89/<- *_Program-types->payload 1/r32/ecx
    20318     }
    20319 $find-or-create-typeinfo:end:
    20320     # . reclaim locals
    20321     81 0/subop/add %esp 8/imm32
    20322     # . restore registers
    20323     5f/pop-to-edi
    20324     5a/pop-to-edx
    20325     59/pop-to-ecx
    20326     58/pop-to-eax
    20327     # . epilogue
    20328     89/<- %esp 5/r32/ebp
    20329     5d/pop-to-ebp
    20330     c3/return
    20331
    20332 find-typeinfo:  # t: type-id, out: (addr handle typeinfo)
    20333     # . prologue
    20334     55/push-ebp
    20335     89/<- %ebp 4/r32/esp
    20336     # . save registers
    20337     50/push-eax
    20338     51/push-ecx
    20339     52/push-edx
    20340     57/push-edi
    20341     # ecx = t
    20342     8b/-> *(ebp+8) 1/r32/ecx
    20343     # edi = out
    20344     8b/-> *(ebp+0xc) 7/r32/edi
    20345     # *out = Program->types
    20346     8b/-> *_Program-types 0/r32/eax
    20347     89/<- *edi 0/r32/eax
    20348     8b/-> *_Program-types->payload 0/r32/eax
    20349     89/<- *(edi+4) 0/r32/eax
    20350     {
    20351 $find-typeinfo:loop:
    20352       # if (*out == 0) break
    20353       81 7/subop/compare *edi 0/imm32
    20354       74/jump-if-= break/disp8
    20355 $find-typeinfo:check:
    20356       # var tmp/eax: (addr typeinfo) = lookup(*out)
    20357       (lookup *edi *(edi+4))  # => eax
    20358       # if (tmp->id == t) break
    20359       39/compare *eax 1/r32/ecx  # Typeinfo-id
    20360       74/jump-if-= break/disp8
    20361 $find-typeinfo:continue:
    20362       # *out = tmp->next
    20363       8b/-> *(eax+0x10) 2/r32/edx  # Typeinfo-next
    20364       89/<- *edi 2/r32/edx
    20365       8b/-> *(eax+0x14) 2/r32/edx  # Typeinfo-next
    20366       89/<- *(edi+4) 2/r32/edx
    20367       #
    20368       eb/jump loop/disp8
    20369     }
    20370 $find-typeinfo:end:
    20371     # . restore registers
    20372     5f/pop-to-edi
    20373     5a/pop-to-edx
    20374     59/pop-to-ecx
    20375     58/pop-to-eax
    20376     # . epilogue
    20377     89/<- %esp 5/r32/ebp
    20378     5d/pop-to-ebp
    20379     c3/return
    20380
    20381 find-or-create-typeinfo-output-var:  # T: (addr typeinfo), f: (addr slice), out: (addr handle var)
    20382     # . prologue
    20383     55/push-ebp
    20384     89/<- %ebp 4/r32/esp
    20385     # . save registers
    20386     50/push-eax
    20387     52/push-edx
    20388     57/push-edi
    20389     # var dest/edi: (handle typeinfo-entry)
    20390     68/push 0/imm32
    20391     68/push 0/imm32
    20392     89/<- %edi 4/r32/esp
    20393     # find-or-create-typeinfo-fields(T, f, dest)
    20394     (find-or-create-typeinfo-fields *(ebp+8) *(ebp+0xc) %edi)
    20395     # var dest-addr/edi: (addr typeinfo-entry) = lookup(dest)
    20396     (lookup *edi *(edi+4))  # => eax
    20397     89/<- %edi 0/r32/eax
    20398     # if dest-addr->output-var doesn't exist, create it
    20399     {
    20400       81 7/subop/compare *(edi+0xc) 0/imm32  # Typeinfo-entry-output-var
    20401       0f 85/jump-if-!= break/disp32
    20402       # dest-addr->output-var = new var(dummy name, type, -1 offset)
    20403       # . var name/eax: (handle array byte) = "field"
    20404       68/push 0/imm32
    20405       68/push 0/imm32
    20406       89/<- %eax 4/r32/esp
    20407       (slice-to-string Heap *(ebp+0xc) %eax)
    20408       # . new var
    20409       8d/copy-address *(edi+0xc) 2/r32/edx
    20410       (new-var Heap  *eax *(eax+4)  %edx)
    20411       # . reclaim name
    20412       81 0/subop/add %esp 8/imm32
    20413       # var result/edx: (addr var) = lookup(dest-addr->output-var)
    20414       (lookup *(edi+0xc) *(edi+0x10))  # => eax
    20415       89/<- %edx 0/r32/eax
    20416       # result->type = new constant type
    20417       8d/copy-address *(edx+8) 0/r32/eax  # Var-type
    20418       (allocate Heap *Type-tree-size %eax)
    20419       (lookup *(edx+8) *(edx+0xc))  # => eax
    20420       c7 0/subop/copy *eax 1/imm32/true  # Type-tree-is-atom
    20421       c7 0/subop/copy *(eax+4) 6/imm32/constant  # Type-tree-value
    20422       c7 0/subop/copy *(eax+8) 0/imm32  # Type-tree-left
    20423       c7 0/subop/copy *(eax+0xc) 0/imm32  # Type-tree-right
    20424       c7 0/subop/copy *(eax+0x10) 0/imm32  # Type-tree-right
    20425       # result->offset isn't filled out yet
    20426       c7 0/subop/copy *(edx+0x14) -1/imm32/uninitialized  # Var-offset
    20427     }
    20428     # out = dest-addr->output-var
    20429     8b/-> *(ebp+0x10) 2/r32/edx
    20430     8b/-> *(edi+0xc) 0/r32/eax  # Typeinfo-entry-output-var
    20431     89/<- *edx 0/r32/eax
    20432     8b/-> *(edi+0x10) 0/r32/eax  # Typeinfo-entry-output-var
    20433     89/<- *(edx+4) 0/r32/eax
    20434 $find-or-create-typeinfo-output-var:end:
    20435     # . reclaim locals
    20436     81 0/subop/add %esp 8/imm32
    20437     # . restore registers
    20438     5f/pop-to-edi
    20439     5a/pop-to-edx
    20440     58/pop-to-eax
    20441     # . epilogue
    20442     89/<- %esp 5/r32/ebp
    20443     5d/pop-to-ebp
    20444     c3/return
    20445
    20446 find-or-create-typeinfo-fields:  # T: (addr typeinfo), f: (addr slice), out: (addr handle typeinfo-entry)
    20447     # . prologue
    20448     55/push-ebp
    20449     89/<- %ebp 4/r32/esp
    20450     # . save registers
    20451     50/push-eax
    20452     56/push-esi
    20453     57/push-edi
    20454     # eax = lookup(T->fields)
    20455     8b/-> *(ebp+8) 0/r32/eax
    20456     (lookup *(eax+4) *(eax+8))  # Typeinfo-fields Typeinfo-fields => eax
    20457     # edi = out
    20458     8b/-> *(ebp+0x10) 7/r32/edi
    20459     # var src/esi: (addr handle typeinfo-entry) = get-or-insert-slice(T->fields, f)
    20460     (get-or-insert-slice %eax *(ebp+0xc) *Typeinfo-fields-row-size Heap)  # => eax
    20461     89/<- %esi 0/r32/eax
    20462     # if src doesn't exist, allocate it
    20463     {
    20464       81 7/subop/compare *esi 0/imm32
    20465       75/jump-if-!= break/disp8
    20466       (allocate Heap *Typeinfo-entry-size %esi)
    20467 #?       (write-buffered Stderr "handle at ")
    20468 #?       (write-int32-hex-buffered Stderr %esi)
    20469 #?       (write-buffered Stderr ": ")
    20470 #?       (write-int32-hex-buffered Stderr *esi)
    20471 #?       (write-buffered Stderr " ")
    20472 #?       (write-int32-hex-buffered Stderr *(esi+4))
    20473 #?       (write-buffered Stderr Newline)
    20474 #?       (flush Stderr)
    20475 #?       (lookup *esi *(esi+4))
    20476 #?       (write-buffered Stderr "created typeinfo fields at ")
    20477 #?       (write-int32-hex-buffered Stderr %esi)
    20478 #?       (write-buffered Stderr " for ")
    20479 #?       (write-int32-hex-buffered Stderr *(ebp+8))
    20480 #?       (write-buffered Stderr Newline)
    20481 #?       (flush Stderr)
    20482     }
    20483     # *out = src
    20484     # . *edi = *src
    20485     8b/-> *esi 0/r32/eax
    20486     89/<- *edi 0/r32/eax
    20487     8b/-> *(esi+4) 0/r32/eax
    20488     89/<- *(edi+4) 0/r32/eax
    20489 $find-or-create-typeinfo-fields:end:
    20490     # . restore registers
    20491     5f/pop-to-edi
    20492     5e/pop-to-esi
    20493     58/pop-to-eax
    20494     # . epilogue
    20495     89/<- %esp 5/r32/ebp
    20496     5d/pop-to-ebp
    20497     c3/return
    20498
    20499 populate-mu-type:  # in: (addr stream byte), t: (addr typeinfo), err: (addr buffered-file), ed: (addr exit-descriptor)
    20500     # pseudocode:
    20501     #   var line: (stream byte 512)
    20502     #   curr-index = 0
    20503     #   while true
    20504     #     clear-stream(line)
    20505     #     read-line-buffered(in, line)
    20506     #     if line->write == 0
    20507     #       abort
    20508     #     word-slice = next-mu-token(line)
    20509     #     if slice-empty?(word-slice)               # end of line
    20510     #       continue
    20511     #     if slice-equal?(word-slice, "}")
    20512     #       break
    20513     #     var v: (handle var) = parse-var-with-type(word-slice, line)
    20514     #     var r: (handle typeinfo-fields) = find-or-create-typeinfo-fields(t, word-slice/v->name)
    20515     #     TODO: ensure that r->first is null
    20516     #     r->index = curr-index
    20517     #     curr-index++
    20518     #     r->input-var = v
    20519     #     if r->output-var == 0
    20520     #       r->output-var = new literal
    20521     #     TODO: ensure nothing else in line
    20522     # t->total-size-in-bytes = -2 (not yet initialized)
    20523     #
    20524     # . prologue
    20525     55/push-ebp
    20526     89/<- %ebp 4/r32/esp
    20527     # var curr-index: int at *(ebp-4)
    20528     68/push 0/imm32
    20529     # . save registers
    20530     50/push-eax
    20531     51/push-ecx
    20532     52/push-edx
    20533     53/push-ebx
    20534     56/push-esi
    20535     57/push-edi
    20536     # edi = t
    20537     8b/-> *(ebp+0xc) 7/r32/edi
    20538     # var line/ecx: (stream byte 512)
    20539     81 5/subop/subtract %esp 0x200/imm32
    20540     68/push 0x200/imm32/size
    20541     68/push 0/imm32/read
    20542     68/push 0/imm32/write
    20543     89/<- %ecx 4/r32/esp
    20544     # var word-slice/edx: slice
    20545     68/push 0/imm32/end
    20546     68/push 0/imm32/start
    20547     89/<- %edx 4/r32/esp
    20548     # var v/esi: (handle var)
    20549     68/push 0/imm32
    20550     68/push 0/imm32
    20551     89/<- %esi 4/r32/esp
    20552     # var r/ebx: (handle typeinfo-entry)
    20553     68/push 0/imm32
    20554     68/push 0/imm32
    20555     89/<- %ebx 4/r32/esp
    20556     {
    20557 $populate-mu-type:line-loop:
    20558       (clear-stream %ecx)
    20559       (read-line-buffered *(ebp+8) %ecx)
    20560       # if (line->write == 0) abort
    20561       81 7/subop/compare *ecx 0/imm32
    20562       0f 84/jump-if-= $populate-mu-type:error1/disp32
    20563 +--  6 lines: #?       # dump line ------------------------------------------------------------------------------------------------------------------------------------------------------
    20569       (next-mu-token %ecx %edx)
    20570       # if slice-empty?(word-slice) continue
    20571       (slice-empty? %edx)  # => eax
    20572       3d/compare-eax-and 0/imm32
    20573       0f 85/jump-if-!= loop/disp32
    20574       # if slice-equal?(word-slice, "}") break
    20575       (slice-equal? %edx "}")
    20576       3d/compare-eax-and 0/imm32
    20577       0f 85/jump-if-!= break/disp32
    20578 $populate-mu-type:parse-element:
    20579       # v = parse-var-with-type(word-slice, first-line)
    20580       # must do this first to strip the trailing ':' from word-slice before
    20581       # using it in find-or-create-typeinfo-fields below
    20582       # TODO: clean up that mutation in parse-var-with-type
    20583       (type-name *edi)  # Typeinfo-id => eax
    20584       (parse-var-with-type %edx %ecx %esi %eax *(ebp+0x10) *(ebp+0x14))
    20585       # if v is an addr, abort
    20586       (lookup *esi *(esi+4))  # => eax
    20587       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    20588       (mu-addr-type? %eax)  # => eax
    20589       3d/compare-eax-and 0/imm32/false
    20590       0f 85/jump-if-!= $populate-mu-type:error2/disp32
    20591       # if v is an array, abort  (we could support it, but initialization gets complex)
    20592       (lookup *esi *(esi+4))  # => eax
    20593       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    20594       (mu-array-type? %eax)  # => eax
    20595       3d/compare-eax-and 0/imm32/false
    20596       0f 85/jump-if-!= $populate-mu-type:error3/disp32
    20597       # if v is a byte, abort
    20598       (lookup *esi *(esi+4))  # => eax
    20599       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    20600       (simple-mu-type? %eax 8)  # byte => eax
    20601       3d/compare-eax-and 0/imm32/false
    20602       0f 85/jump-if-!= $populate-mu-type:error4/disp32
    20603       # if v is a slice, abort
    20604       (lookup *esi *(esi+4))  # => eax
    20605       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    20606       (simple-mu-type? %eax 0xc)  # slice => eax
    20607       3d/compare-eax-and 0/imm32/false
    20608       0f 85/jump-if-!= $populate-mu-type:error5/disp32
    20609       # if v is a stream, abort  (we could support it, but initialization gets even more complex)
    20610       (lookup *esi *(esi+4))  # => eax
    20611       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    20612       (mu-stream-type? %eax)  # => eax
    20613       3d/compare-eax-and 0/imm32/false
    20614       0f 85/jump-if-!= $populate-mu-type:error6/disp32
    20615       # var tmp/ecx
    20616       51/push-ecx
    20617 $populate-mu-type:create-typeinfo-fields:
    20618       # var r/ebx: (handle typeinfo-entry)
    20619       (find-or-create-typeinfo-fields %edi %edx %ebx)
    20620       # r->index = curr-index
    20621       (lookup *ebx *(ebx+4))  # => eax
    20622       8b/-> *(ebp-4) 1/r32/ecx
    20623 #?       (write-buffered Stderr "saving index ")
    20624 #?       (write-int32-hex-buffered Stderr %ecx)
    20625 #?       (write-buffered Stderr " at ")
    20626 #?       (write-int32-hex-buffered Stderr %edi)
    20627 #?       (write-buffered Stderr Newline)
    20628 #?       (flush Stderr)
    20629       89/<- *(eax+8) 1/r32/ecx  # Typeinfo-entry-index
    20630       # ++curr-index
    20631       ff 0/subop/increment *(ebp-4)
    20632 $populate-mu-type:set-input-type:
    20633       # r->input-var = v
    20634       8b/-> *esi 1/r32/ecx
    20635       89/<- *eax 1/r32/ecx  # Typeinfo-entry-input-var
    20636       8b/-> *(esi+4) 1/r32/ecx
    20637       89/<- *(eax+4) 1/r32/ecx  # Typeinfo-entry-input-var
    20638       # restore line
    20639       59/pop-to-ecx
    20640       {
    20641 $populate-mu-type:create-output-type:
    20642         # if (r->output-var == 0) create a new var with some placeholder data
    20643         81 7/subop/compare *(eax+0xc) 0/imm32  # Typeinfo-entry-output-var
    20644         75/jump-if-!= break/disp8
    20645         8d/copy-address *(eax+0xc) 0/r32/eax  # Typeinfo-entry-output-var
    20646         (new-literal Heap %edx %eax)
    20647       }
    20648       e9/jump loop/disp32
    20649     }
    20650 $populate-mu-type:invalidate-total-size-in-bytes:
    20651     # Offsets and total size may not be accurate here since we may not yet
    20652     # have encountered the element types.
    20653     # We'll recompute them separately after parsing the entire program.
    20654     c7 0/subop/copy *(edi+0xc) -2/imm32/uninitialized  # Typeinfo-total-size-in-bytes
    20655 $populate-mu-type:end:
    20656     # . reclaim locals
    20657     81 0/subop/add %esp 0x224/imm32
    20658     # . restore registers
    20659     5f/pop-to-edi
    20660     5e/pop-to-esi
    20661     5b/pop-to-ebx
    20662     5a/pop-to-edx
    20663     59/pop-to-ecx
    20664     58/pop-to-eax
    20665     # reclaim curr-index
    20666     81 0/subop/add %esp 4/imm32
    20667     # . epilogue
    20668     89/<- %esp 5/r32/ebp
    20669     5d/pop-to-ebp
    20670     c3/return
    20671
    20672 $populate-mu-type:error1:
    20673     # error("incomplete type definition '" t->name "'\n")
    20674     (write-buffered *(ebp+0x10) "incomplete type definition '")
    20675     (type-name *edi)  # Typeinfo-id => eax
    20676     (write-buffered *(ebp+0x10) %eax)
    20677     (write-buffered *(ebp+0x10) "\n")
    20678     (flush *(ebp+0x10))
    20679     (stop *(ebp+0x14) 1)
    20680     # never gets here
    20681
    20682 $populate-mu-type:error2:
    20683     (write-buffered *(ebp+0x10) "type ")
    20684     (type-name *edi)  # Typeinfo-id => eax
    20685     (write-buffered *(ebp+0x10) %eax)
    20686     (write-buffered *(ebp+0x10) ": 'addr' elements not allowed\n")
    20687     (flush *(ebp+0x10))
    20688     (stop *(ebp+0x14) 1)
    20689     # never gets here
    20690
    20691 $populate-mu-type:error3:
    20692     (write-buffered *(ebp+0x10) "type ")
    20693     (type-name *edi)  # Typeinfo-id => eax
    20694     (write-buffered *(ebp+0x10) %eax)
    20695     (write-buffered *(ebp+0x10) ": 'array' elements not allowed for now\n")
    20696     (flush *(ebp+0x10))
    20697     (stop *(ebp+0x14) 1)
    20698     # never gets here
    20699
    20700 $populate-mu-type:error4:
    20701     (write-buffered *(ebp+0x10) "type ")
    20702     (type-name *edi)  # Typeinfo-id => eax
    20703     (write-buffered *(ebp+0x10) %eax)
    20704     (write-buffered *(ebp+0x10) ": 'byte' elements not allowed\n")
    20705     (flush *(ebp+0x10))
    20706     (stop *(ebp+0x14) 1)
    20707     # never gets here
    20708
    20709 $populate-mu-type:error5:
    20710     (write-buffered *(ebp+0x10) "type ")
    20711     (type-name *edi)  # Typeinfo-id => eax
    20712     (write-buffered *(ebp+0x10) %eax)
    20713     (write-buffered *(ebp+0x10) ": 'slice' elements not allowed\n")
    20714     (flush *(ebp+0x10))
    20715     (stop *(ebp+0x14) 1)
    20716     # never gets here
    20717
    20718 $populate-mu-type:error6:
    20719     (write-buffered *(ebp+0x10) "type ")
    20720     (type-name *edi)  # Typeinfo-id => eax
    20721     (write-buffered *(ebp+0x10) %eax)
    20722     (write-buffered *(ebp+0x10) ": 'stream' elements not allowed for now\n")
    20723     (flush *(ebp+0x10))
    20724     (stop *(ebp+0x14) 1)
    20725     # never gets here
    20726
    20727 type-name:  # index: int -> result/eax: (addr array byte)
    20728     # . prologue
    20729     55/push-ebp
    20730     89/<- %ebp 4/r32/esp
    20731     #
    20732     (index Type-id *(ebp+8))
    20733 $type-name:end:
    20734     # . epilogue
    20735     89/<- %esp 5/r32/ebp
    20736     5d/pop-to-ebp
    20737     c3/return
    20738
    20739 index:  # arr: (addr stream (handle array byte)), index: int -> result/eax: (addr array byte)
    20740     # . prologue
    20741     55/push-ebp
    20742     89/<- %ebp 4/r32/esp
    20743     # . save registers
    20744     56/push-esi
    20745     # TODO: bounds-check index
    20746     # esi = arr
    20747     8b/-> *(ebp+8) 6/r32/esi
    20748     # eax = index
    20749     8b/-> *(ebp+0xc) 0/r32/eax
    20750     # eax = *(arr + 12 + index)
    20751     8b/-> *(esi+eax<<2+0xc) 0/r32/eax
    20752 $index:end:
    20753     # . restore registers
    20754     5e/pop-to-esi
    20755     # . epilogue
    20756     89/<- %esp 5/r32/ebp
    20757     5d/pop-to-ebp
    20758     c3/return
    20759
    20760 #######################################################
    20761 # Compute type sizes
    20762 #######################################################
    20763
    20764 # Compute the sizes of all user-defined types.
    20765 # We'll need the sizes of their elements, which may be other user-defined
    20766 # types, which we will compute as needed.
    20767
    20768 # Initially, all user-defined types have their sizes set to -2 (invalid)
    20769 populate-mu-type-sizes:  # err: (addr buffered-file), ed: (addr exit-descriptor)
    20770     # . prologue
    20771     55/push-ebp
    20772     89/<- %ebp 4/r32/esp
    20773 $populate-mu-type-sizes:total-sizes:
    20774     # var curr/eax: (addr typeinfo) = lookup(Program->types)
    20775     (lookup *_Program-types *_Program-types->payload)  # => eax
    20776     {
    20777       # if (curr == null) break
    20778       3d/compare-eax-and 0/imm32/null
    20779       74/jump-if-= break/disp8
    20780       (populate-mu-type-sizes-in-type %eax *(ebp+8) *(ebp+0xc))
    20781       # curr = lookup(curr->next)
    20782       (lookup *(eax+0x10) *(eax+0x14))  # Typeinfo-next Typeinfo-next => eax
    20783       eb/jump loop/disp8
    20784     }
    20785 $populate-mu-type-sizes:offsets:
    20786     # curr = *Program->types
    20787     (lookup *_Program-types *_Program-types->payload)  # => eax
    20788     {
    20789       # if (curr == null) break
    20790       3d/compare-eax-and 0/imm32/null
    20791       74/jump-if-= break/disp8
    20792       (populate-mu-type-offsets %eax *(ebp+8) *(ebp+0xc))
    20793       # curr = curr->next
    20794       (lookup *(eax+0x10) *(eax+0x14))  # Typeinfo-next Typeinfo-next => eax
    20795       eb/jump loop/disp8
    20796     }
    20797 $populate-mu-type-sizes:end:
    20798     # . epilogue
    20799     89/<- %esp 5/r32/ebp
    20800     5d/pop-to-ebp
    20801     c3/return
    20802
    20803 # compute sizes of all fields, recursing as necessary
    20804 # sum up all their sizes to arrive at total size
    20805 # fields may be out of order, but that doesn't affect the answer
    20806 populate-mu-type-sizes-in-type:  # T: (addr typeinfo), err: (addr buffered-file), ed: (addr exit-descriptor)
    20807     # . prologue
    20808     55/push-ebp
    20809     89/<- %ebp 4/r32/esp
    20810     # . save registers
    20811     50/push-eax
    20812     51/push-ecx
    20813     52/push-edx
    20814     56/push-esi
    20815     57/push-edi
    20816     # esi = T
    20817     8b/-> *(ebp+8) 6/r32/esi
    20818     # if T is already computed, return
    20819     81 7/subop/compare *(esi+0xc) 0/imm32  # Typeinfo-total-size-in-bytes
    20820     0f 8d/jump-if->= $populate-mu-type-sizes-in-type:end/disp32
    20821     # if T is being computed, abort
    20822     81 7/subop/compare *(esi+0xc) -1/imm32/being-computed  # Typeinfo-total-size-in-bytes
    20823     0f 84/jump-if-= $populate-mu-type-sizes-in-type:abort/disp32
    20824     # tag T (-2 to -1) to avoid infinite recursion
    20825     c7 0/subop/copy *(esi+0xc) -1/imm32/being-computed  # Typeinfo-total-size-in-bytes
    20826     # var total-size/edi: int = 0
    20827     bf/copy-to-edi 0/imm32
    20828     # - for every field, if it's a user-defined type, compute its size
    20829     # var table/ecx: (addr table (handle array byte) (handle typeinfo-entry)) = lookup(T->fields)
    20830     (lookup *(esi+4) *(esi+8))  # Typeinfo-fields Typeinfo-fields => eax
    20831     89/<- %ecx 0/r32/eax
    20832     # var table-size/edx: int = table->write
    20833     8b/-> *ecx 2/r32/edx  # stream-write
    20834     # var curr/ecx: (addr table_row) = table->data
    20835     8d/copy-address *(ecx+0xc) 1/r32/ecx
    20836     # var max/edx: (addr table_row) = table->data + table->write
    20837     8d/copy-address *(ecx+edx) 2/r32/edx
    20838     {
    20839 $populate-mu-type-sizes-in-type:loop:
    20840       # if (curr >= max) break
    20841       39/compare %ecx 2/r32/edx
    20842       73/jump-if-addr>= break/disp8
    20843       # var t/eax: (addr typeinfo-entry) = lookup(curr->value)
    20844       (lookup *(ecx+8) *(ecx+0xc))  # => eax
    20845       # if (t->input-var == 0) silently ignore it; we'll emit a nice error message while type-checking
    20846       81 7/subop/compare *eax 0/imm32  # Typeinfo-entry-input-var
    20847       74/jump-if-= $populate-mu-type-sizes-in-type:end/disp8
    20848       # compute size of t->input-var
    20849       (lookup *eax *(eax+4))  # Typeinfo-entry-input-var Typeinfo-entry-input-var => eax
    20850       (compute-size-of-var %eax *(ebp+0xc) *(ebp+0x10))  # => eax
    20851       # result += eax
    20852       01/add-to %edi 0/r32/eax
    20853       # curr += row-size
    20854       81 0/subop/add %ecx 0x10/imm32  # Typeinfo-fields-row-size
    20855       #
    20856       eb/jump loop/disp8
    20857     }
    20858     # - save result
    20859     89/<- *(esi+0xc) 7/r32/edi  # Typeinfo-total-size-in-bytes
    20860 $populate-mu-type-sizes-in-type:end:
    20861     # . restore registers
    20862     5f/pop-to-edi
    20863     5e/pop-to-esi
    20864     5a/pop-to-edx
    20865     59/pop-to-ecx
    20866     58/pop-to-eax
    20867     # . epilogue
    20868     89/<- %esp 5/r32/ebp
    20869     5d/pop-to-ebp
    20870     c3/return
    20871
    20872 $populate-mu-type-sizes-in-type:abort:
    20873     (write-buffered *(ebp+0xc) "cycle in type definitions\n")
    20874     (flush *(ebp+0xc))
    20875     (stop *(ebp+0x10) 1)
    20876     # never gets here
    20877
    20878 # Analogous to size-of, except we need to compute what size-of can just read
    20879 # off the right data structures.
    20880 compute-size-of-var:  # in: (addr var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
    20881     # . prologue
    20882     55/push-ebp
    20883     89/<- %ebp 4/r32/esp
    20884     # . push registers
    20885     51/push-ecx
    20886     # var t/ecx: (addr type-tree) = lookup(v->type)
    20887     8b/-> *(ebp+8) 1/r32/ecx
    20888     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
    20889     89/<- %ecx 0/r32/eax
    20890     # if (t->is-atom == false) t = lookup(t->left)
    20891     {
    20892       81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
    20893       75/jump-if-!= break/disp8
    20894       (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
    20895       89/<- %ecx 0/r32/eax
    20896     }
    20897     # TODO: ensure t is an atom
    20898     (compute-size-of-type-id *(ecx+4) *(ebp+0xc) *(ebp+0x10))  # Type-tree-value => eax
    20899 $compute-size-of-var:end:
    20900     # . restore registers
    20901     59/pop-to-ecx
    20902     # . epilogue
    20903     89/<- %esp 5/r32/ebp
    20904     5d/pop-to-ebp
    20905     c3/return
    20906
    20907 compute-size-of-type-id:  # t: type-id, err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
    20908     # . prologue
    20909     55/push-ebp
    20910     89/<- %ebp 4/r32/esp
    20911     # . save registers
    20912     51/push-ecx
    20913     # var out/ecx: (handle typeinfo)
    20914     68/push 0/imm32
    20915     68/push 0/imm32
    20916     89/<- %ecx 4/r32/esp
    20917     # eax = t
    20918     8b/-> *(ebp+8) 0/r32/eax
    20919     # if t is a literal, return 0
    20920     3d/compare-eax-and 0/imm32/literal
    20921     0f 84/jump-if-= $compute-size-of-type-id:end/disp32  # eax changes type from type-id to int
    20922     # if t is a byte, return 4 (because we don't really support non-multiples of 4)
    20923     3d/compare-eax-and 8/imm32/byte
    20924     {
    20925       75/jump-if-!= break/disp8
    20926       b8/copy-to-eax 4/imm32
    20927       eb/jump $compute-size-of-type-id:end/disp8
    20928     }
    20929     # if t is a handle, return 8
    20930     3d/compare-eax-and 4/imm32/handle
    20931     {
    20932       75/jump-if-!= break/disp8
    20933       b8/copy-to-eax 8/imm32
    20934       eb/jump $compute-size-of-type-id:end/disp8  # eax changes type from type-id to int
    20935     }
    20936     # if t is a slice, return 8
    20937     3d/compare-eax-and 0xc/imm32/slice
    20938     {
    20939       75/jump-if-!= break/disp8
    20940       b8/copy-to-eax 8/imm32
    20941       eb/jump $compute-size-of-type-id:end/disp8  # eax changes type from type-id to int
    20942     }
    20943     # if t is a user-defined type, compute its size
    20944     # TODO: support non-atom type
    20945     (find-typeinfo %eax %ecx)
    20946     {
    20947       81 7/subop/compare *ecx 0/imm32
    20948       74/jump-if-= break/disp8
    20949 $compute-size-of-type-id:user-defined:
    20950       (lookup *ecx *(ecx+4))  # => eax
    20951       (populate-mu-type-sizes-in-type %eax *(ebp+0xc) *(ebp+0x10))
    20952       8b/-> *(eax+0xc) 0/r32/eax  # Typeinfo-total-size-in-bytes
    20953       eb/jump $compute-size-of-type-id:end/disp8
    20954     }
    20955     # otherwise return the word size
    20956     b8/copy-to-eax 4/imm32
    20957 $compute-size-of-type-id:end:
    20958     # . reclaim locals
    20959     81 0/subop/add %esp 8/imm32
    20960     # . restore registers
    20961     59/pop-to-ecx
    20962     # . epilogue
    20963     89/<- %esp 5/r32/ebp
    20964     5d/pop-to-ebp
    20965     c3/return
    20966
    20967 # at this point we have total sizes for all user-defined types
    20968 # compute offsets for each element
    20969 # complication: fields may be out of order
    20970 populate-mu-type-offsets:  # in: (addr typeinfo), err: (addr buffered-file), ed: (addr exit-descriptor)
    20971     # . prologue
    20972     55/push-ebp
    20973     89/<- %ebp 4/r32/esp
    20974     # . save registers
    20975     50/push-eax
    20976     51/push-ecx
    20977     52/push-edx
    20978     53/push-ebx
    20979     56/push-esi
    20980     57/push-edi
    20981 #?     (dump-typeinfos "aaa\n")
    20982     # var curr-offset/edi: int = 0
    20983     bf/copy-to-edi 0/imm32
    20984     # var table/ecx: (addr table string_key (handle typeinfo-entry)) = lookup(in->fields)
    20985     8b/-> *(ebp+8) 1/r32/ecx
    20986     (lookup *(ecx+4) *(ecx+8))  # Typeinfo-fields Typeinfo-fields => eax
    20987     89/<- %ecx 0/r32/eax
    20988     # var num-elems/edx: int = table->write / Typeinfo-fields-row-size
    20989     8b/-> *ecx 2/r32/edx  # stream-write
    20990     c1 5/subop/shift-right-logical  %edx 4/imm8
    20991     # var i/ebx: int = 0
    20992     bb/copy-to-ebx 0/imm32
    20993     {
    20994 $populate-mu-type-offsets:loop:
    20995       39/compare %ebx 2/r32/edx
    20996       0f 8d/jump-if->= break/disp32
    20997 #?       (write-buffered Stderr "looking up index ")
    20998 #?       (write-int32-hex-buffered Stderr %ebx)
    20999 #?       (write-buffered Stderr " in ")
    21000 #?       (write-int32-hex-buffered Stderr *(ebp+8))
    21001 #?       (write-buffered Stderr Newline)
    21002 #?       (flush Stderr)
    21003       # var v/esi: (addr typeinfo-entry)
    21004       (locate-typeinfo-entry-with-index %ecx %ebx *(ebp+0xc) *(ebp+0x10))  # => eax
    21005       89/<- %esi 0/r32/eax
    21006       # if v is null, silently move on; we'll emit a nice error message while type-checking
    21007       81 7/subop/compare %esi 0/imm32  # Typeinfo-entry-input-var
    21008       74/jump-if-= $populate-mu-type-offsets:end/disp8
    21009       # if (v->input-var == 0) silently ignore v; we'll emit a nice error message while type-checking
    21010       81 7/subop/compare *esi 0/imm32  # Typeinfo-entry-input-var
    21011       74/jump-if-= $populate-mu-type-offsets:end/disp8
    21012       # v->output-var->offset = curr-offset
    21013       # . eax: (addr var)
    21014       (lookup *(esi+0xc) *(esi+0x10))  # Typeinfo-entry-output-var Typeinfo-entry-output-var => eax
    21015       89/<- *(eax+0x14) 7/r32/edi  # Var-offset
    21016       # curr-offset += size-of(v->input-var)
    21017       (lookup *esi *(esi+4))  # Typeinfo-entry-input-var Typeinfo-entry-input-var => eax
    21018       (size-of %eax)  # => eax
    21019       01/add-to %edi 0/r32/eax
    21020       # ++i
    21021       43/increment-ebx
    21022       e9/jump loop/disp32
    21023     }
    21024 $populate-mu-type-offsets:end:
    21025     # . restore registers
    21026     5f/pop-to-edi
    21027     5e/pop-to-esi
    21028     5b/pop-to-ebx
    21029     5a/pop-to-edx
    21030     59/pop-to-ecx
    21031     58/pop-to-eax
    21032     # . epilogue
    21033     89/<- %esp 5/r32/ebp
    21034     5d/pop-to-ebp
    21035     c3/return
    21036
    21037 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)
    21038     # . prologue
    21039     55/push-ebp
    21040     89/<- %ebp 4/r32/esp
    21041     # . save registers
    21042     51/push-ecx
    21043     52/push-edx
    21044     53/push-ebx
    21045     56/push-esi
    21046     57/push-edi
    21047     # esi = table
    21048     8b/-> *(ebp+8) 6/r32/esi
    21049     # var curr/ecx: (addr row (handle array byte) (handle typeinfo-entry)) = table->data
    21050     8d/copy-address *(esi+0xc) 1/r32/ecx
    21051     # var max/edx: (addr byte) = &table->data[table->write]
    21052     8b/-> *esi 2/r32/edx
    21053     8d/copy-address *(ecx+edx) 2/r32/edx
    21054     {
    21055 $locate-typeinfo-entry-with-index:loop:
    21056       39/compare %ecx 2/r32/edx
    21057       73/jump-if-addr>= break/disp8
    21058       # var v/eax: (addr typeinfo-entry)
    21059       (lookup *(ecx+8) *(ecx+0xc))  # => eax
    21060       # if (v->index == idx) return v
    21061       8b/-> *(eax+8) 3/r32/ebx  # Typeinfo-entry-index
    21062 #?       (write-buffered Stderr "comparing ")
    21063 #?       (write-int32-hex-buffered Stderr %ebx)
    21064 #?       (write-buffered Stderr " and ")
    21065 #?       (write-int32-hex-buffered Stderr *(ebp+0xc))
    21066 #?       (write-buffered Stderr Newline)
    21067 #?       (flush Stderr)
    21068       39/compare *(ebp+0xc) 3/r32/ebx
    21069       74/jump-if-= $locate-typeinfo-entry-with-index:end/disp8
    21070       # curr += Typeinfo-entry-size
    21071       81 0/subop/add %ecx 0x10/imm32  # Typeinfo-entry-size
    21072       #
    21073       eb/jump loop/disp8
    21074     }
    21075     # return 0
    21076     b8/copy-to-eax 0/imm32
    21077 $locate-typeinfo-entry-with-index:end:
    21078 #?     (write-buffered Stderr "returning ")
    21079 #?     (write-int32-hex-buffered Stderr %eax)
    21080 #?     (write-buffered Stderr Newline)
    21081 #?     (flush Stderr)
    21082     # . restore registers
    21083     5f/pop-to-edi
    21084     5e/pop-to-esi
    21085     5b/pop-to-ebx
    21086     5a/pop-to-edx
    21087     59/pop-to-ecx
    21088     # . epilogue
    21089     89/<- %esp 5/r32/ebp
    21090     5d/pop-to-ebp
    21091     c3/return
    21092
    21093 dump-typeinfos:  # hdr: (addr array byte)
    21094     # . prologue
    21095     55/push-ebp
    21096     89/<- %ebp 4/r32/esp
    21097     # . save registers
    21098     50/push-eax
    21099     #
    21100     (write-buffered Stderr *(ebp+8))
    21101     (flush Stderr)
    21102     # var curr/eax: (addr typeinfo) = lookup(Program->types)
    21103     (lookup *_Program-types *_Program-types->payload)  # => eax
    21104     {
    21105       # if (curr == null) break
    21106       3d/compare-eax-and 0/imm32
    21107       74/jump-if-= break/disp8
    21108       (write-buffered Stderr "---\n")
    21109       (flush Stderr)
    21110       (dump-typeinfo %eax)
    21111       # curr = lookup(curr->next)
    21112       (lookup *(eax+0x10) *(eax+0x14))  # Typeinfo-next Typeinfo-next => eax
    21113       eb/jump loop/disp8
    21114     }
    21115 $dump-typeinfos:end:
    21116     # . restore registers
    21117     58/pop-to-eax
    21118     # . epilogue
    21119     89/<- %esp 5/r32/ebp
    21120     5d/pop-to-ebp
    21121     c3/return
    21122
    21123 dump-typeinfo:  # in: (addr typeinfo)
    21124     # . prologue
    21125     55/push-ebp
    21126     89/<- %ebp 4/r32/esp
    21127     # . save registers
    21128     50/push-eax
    21129     51/push-ecx
    21130     52/push-edx
    21131     53/push-ebx
    21132     56/push-esi
    21133     57/push-edi
    21134     # esi = in
    21135     8b/-> *(ebp+8) 6/r32/esi
    21136     # var table/ecx: (addr table (handle array byte) (handle typeinfo-entry)) = lookup(T->fields)
    21137     (lookup *(esi+4) *(esi+8))  # Typeinfo-fields Typeinfo-fields => eax
    21138     89/<- %ecx 0/r32/eax
    21139     (write-buffered Stderr "id:")
    21140     (write-int32-hex-buffered Stderr *esi)
    21141     (write-buffered Stderr "\n")
    21142     (write-buffered Stderr "fields @ ")
    21143     (write-int32-hex-buffered Stderr %ecx)
    21144     (write-buffered Stderr Newline)
    21145     (flush Stderr)
    21146     (write-buffered Stderr "  write: ")
    21147     (write-int32-hex-buffered Stderr *ecx)
    21148     (write-buffered Stderr Newline)
    21149     (flush Stderr)
    21150     (write-buffered Stderr "  read: ")
    21151     (write-int32-hex-buffered Stderr *(ecx+4))
    21152     (write-buffered Stderr Newline)
    21153     (flush Stderr)
    21154     (write-buffered Stderr "  size: ")
    21155     (write-int32-hex-buffered Stderr *(ecx+8))
    21156     (write-buffered Stderr Newline)
    21157     (flush Stderr)
    21158     # var table-size/edx: int = table->write
    21159     8b/-> *ecx 2/r32/edx  # stream-write
    21160     # var curr/ecx: (addr table_row) = table->data
    21161     8d/copy-address *(ecx+0xc) 1/r32/ecx
    21162     # var max/edx: (addr table_row) = table->data + table->write
    21163     8d/copy-address *(ecx+edx) 2/r32/edx
    21164     {
    21165 $dump-typeinfo:loop:
    21166       # if (curr >= max) break
    21167       39/compare %ecx 2/r32/edx
    21168       0f 83/jump-if-addr>= break/disp32
    21169       (write-buffered Stderr "  row:\n")
    21170       (write-buffered Stderr "    key: ")
    21171       (write-int32-hex-buffered Stderr *ecx)
    21172       (write-buffered Stderr ",")
    21173       (write-int32-hex-buffered Stderr *(ecx+4))
    21174       (write-buffered Stderr " = '")
    21175       (lookup *ecx *(ecx+4))
    21176       (write-buffered Stderr %eax)
    21177       (write-buffered Stderr "' @ ")
    21178       (write-int32-hex-buffered Stderr %eax)
    21179       (write-buffered Stderr Newline)
    21180       (flush Stderr)
    21181       (write-buffered Stderr "    value: ")
    21182       (write-int32-hex-buffered Stderr *(ecx+8))
    21183       (write-buffered Stderr ",")
    21184       (write-int32-hex-buffered Stderr *(ecx+0xc))
    21185       (write-buffered Stderr " = typeinfo-entry@")
    21186       (lookup *(ecx+8) *(ecx+0xc))
    21187       (write-int32-hex-buffered Stderr %eax)
    21188       (write-buffered Stderr Newline)
    21189       (flush Stderr)
    21190       (write-buffered Stderr "        input var@")
    21191       (dump-var 5 %eax)
    21192       (lookup *(ecx+8) *(ecx+0xc))
    21193       (write-buffered Stderr "        index: ")
    21194       (write-int32-hex-buffered Stderr *(eax+8))
    21195       (write-buffered Stderr Newline)
    21196       (flush Stderr)
    21197       (write-buffered Stderr "        output var@")
    21198       8d/copy-address *(eax+0xc) 0/r32/eax  # Typeinfo-entry-output-var
    21199       (dump-var 5 %eax)
    21200       (flush Stderr)
    21201       # curr += row-size
    21202       81 0/subop/add %ecx 0x10/imm32  # Typeinfo-fields-row-size
    21203       #
    21204       e9/jump loop/disp32
    21205     }
    21206 $dump-typeinfo:end:
    21207     # . restore registers
    21208     5f/pop-to-edi
    21209     5e/pop-to-esi
    21210     5b/pop-to-ebx
    21211     5a/pop-to-edx
    21212     59/pop-to-ecx
    21213     58/pop-to-eax
    21214     # . epilogue
    21215     89/<- %esp 5/r32/ebp
    21216     5d/pop-to-ebp
    21217     c3/return
    21218
    21219 dump-var:  # indent: int, v: (addr handle var)
    21220     # . prologue
    21221     55/push-ebp
    21222     89/<- %ebp 4/r32/esp
    21223     # . save registers
    21224     50/push-eax
    21225     53/push-ebx
    21226     # eax = v
    21227     8b/-> *(ebp+0xc) 0/r32/eax
    21228     #
    21229     (write-int32-hex-buffered Stderr *eax)
    21230     (write-buffered Stderr ",")
    21231     (write-int32-hex-buffered Stderr *(eax+4))
    21232     (write-buffered Stderr "->")
    21233     (lookup *eax *(eax+4))
    21234     (write-int32-hex-buffered Stderr %eax)
    21235     (write-buffered Stderr Newline)
    21236     (flush Stderr)
    21237     {
    21238       3d/compare-eax-and 0/imm32
    21239       0f 84/jump-if-= break/disp32
    21240       (emit-indent Stderr *(ebp+8))
    21241       (write-buffered Stderr "name: ")
    21242       89/<- %ebx 0/r32/eax
    21243       (write-int32-hex-buffered Stderr *ebx)  # Var-name
    21244       (write-buffered Stderr ",")
    21245       (write-int32-hex-buffered Stderr *(ebx+4))  # Var-name
    21246       (write-buffered Stderr "->")
    21247       (lookup *ebx *(ebx+4))  # Var-name
    21248       (write-int32-hex-buffered Stderr %eax)
    21249       {
    21250         3d/compare-eax-and 0/imm32
    21251         74/jump-if-= break/disp8
    21252         (write-buffered Stderr Space)
    21253         (write-buffered Stderr %eax)
    21254       }
    21255       (write-buffered Stderr Newline)
    21256       (flush Stderr)
    21257       (emit-indent Stderr *(ebp+8))
    21258       (write-buffered Stderr "block depth: ")
    21259       (write-int32-hex-buffered Stderr *(ebx+0x10))  # Var-block-depth
    21260       (write-buffered Stderr Newline)
    21261       (flush Stderr)
    21262       (emit-indent Stderr *(ebp+8))
    21263       (write-buffered Stderr "stack offset: ")
    21264       (write-int32-hex-buffered Stderr *(ebx+0x14))  # Var-offset
    21265       (write-buffered Stderr Newline)
    21266       (flush Stderr)
    21267       (emit-indent Stderr *(ebp+8))
    21268       (write-buffered Stderr "reg: ")
    21269       (write-int32-hex-buffered Stderr *(ebx+0x18))  # Var-register
    21270       (write-buffered Stderr ",")
    21271       (write-int32-hex-buffered Stderr *(ebx+0x1c))  # Var-register
    21272       (write-buffered Stderr "->")
    21273       (flush Stderr)
    21274       (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register
    21275       (write-int32-hex-buffered Stderr %eax)
    21276       {
    21277         3d/compare-eax-and 0/imm32
    21278         74/jump-if-= break/disp8
    21279         (write-buffered Stderr Space)
    21280         (write-buffered Stderr %eax)
    21281       }
    21282       (write-buffered Stderr Newline)
    21283       (flush Stderr)
    21284     }
    21285 $dump-var:end:
    21286     # . restore registers
    21287     5b/pop-to-ebx
    21288     58/pop-to-eax
    21289     # . epilogue
    21290     89/<- %esp 5/r32/ebp
    21291     5d/pop-to-ebp
    21292     c3/return
    21293
    21294 #######################################################
    21295 # Type-checking
    21296 #######################################################
    21297
    21298 check-mu-types:  # err: (addr buffered-file), ed: (addr exit-descriptor)
    21299     # . prologue
    21300     55/push-ebp
    21301     89/<- %ebp 4/r32/esp
    21302     # . save registers
    21303     50/push-eax
    21304     # var curr/eax: (addr function) = lookup(Program->functions)
    21305     (lookup *_Program-functions *_Program-functions->payload)  # => eax
    21306     {
    21307 $check-mu-types:loop:
    21308       # if (curr == null) break
    21309       3d/compare-eax-and 0/imm32
    21310       0f 84/jump-if-= break/disp32
    21311 +--  8 lines: #?       # dump curr->name ------------------------------------------------------------------------------------------------------------------------------------------------
    21319       (check-mu-function %eax *(ebp+8) *(ebp+0xc))
    21320       # curr = lookup(curr->next)
    21321       (lookup *(eax+0x20) *(eax+0x24))  # Function-next Function-next => eax
    21322       e9/jump loop/disp32
    21323     }
    21324 $check-mu-types:end:
    21325     # . restore registers
    21326     58/pop-to-eax
    21327     # . epilogue
    21328     89/<- %esp 5/r32/ebp
    21329     5d/pop-to-ebp
    21330     c3/return
    21331
    21332 check-mu-function:  # fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    21333     # . prologue
    21334     55/push-ebp
    21335     89/<- %ebp 4/r32/esp
    21336     # . save registers
    21337     50/push-eax
    21338     56/push-esi
    21339     # esi = f
    21340     8b/-> *(ebp+8) 6/r32/esi
    21341     # outputs
    21342     (lookup *(esi+0x10) *(esi+0x14))  # Function-outputs Function-outputs => eax
    21343     (check-all-unique-registers %eax %esi *(ebp+0xc) *(ebp+0x10))
    21344     # body
    21345     (lookup *(esi+0x18) *(esi+0x1c))  # Function-body Function-body => eax
    21346     (check-mu-block %eax *(ebp+8) *(ebp+0xc) *(ebp+0x10))
    21347     # if function has no outputs, we're done
    21348     81 7/subop/compare *(esi+0x10) 0/imm32
    21349     74/jump-if-= $check-mu-function:end/disp8
    21350     # some final checks on body
    21351     (check-final-stmt-is-return %eax %esi *(ebp+0xc) *(ebp+0x10))
    21352     (check-no-breaks %eax %esi *(ebp+0xc) *(ebp+0x10))
    21353 $check-mu-function:end:
    21354     # . restore registers
    21355     5e/pop-to-esi
    21356     58/pop-to-eax
    21357     # . epilogue
    21358     89/<- %esp 5/r32/ebp
    21359     5d/pop-to-ebp
    21360     c3/return
    21361
    21362 check-mu-block:  # block: (addr block), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    21363     # . prologue
    21364     55/push-ebp
    21365     89/<- %ebp 4/r32/esp
    21366     # . save registers
    21367     50/push-eax
    21368     # eax = block
    21369     8b/-> *(ebp+8) 0/r32/eax
    21370     # var stmts/eax: (addr list stmt) = lookup(block->statements)
    21371     (lookup *(eax+4) *(eax+8))  # Block-stmts Block-stmts => eax
    21372     #
    21373     {
    21374 $check-mu-block:check-empty:
    21375       3d/compare-eax-and 0/imm32
    21376       0f 84/jump-if-= break/disp32
    21377       # emit block->statements
    21378       (check-mu-stmt-list %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21379     }
    21380 $check-mu-block:end:
    21381     # . restore registers
    21382     58/pop-to-eax
    21383     # . epilogue
    21384     89/<- %esp 5/r32/ebp
    21385     5d/pop-to-ebp
    21386     c3/return
    21387
    21388 check-mu-stmt-list:  # stmts: (addr list stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    21389     # . prologue
    21390     55/push-ebp
    21391     89/<- %ebp 4/r32/esp
    21392     # . save registers
    21393     50/push-eax
    21394     56/push-esi
    21395     # esi = stmts
    21396     8b/-> *(ebp+8) 6/r32/esi
    21397     {
    21398 $check-mu-stmt-list:loop:
    21399       81 7/subop/compare %esi 0/imm32
    21400       0f 84/jump-if-= break/disp32
    21401       # var curr-stmt/eax: (addr stmt) = lookup(stmts->value)
    21402       (lookup *esi *(esi+4))  # List-value List-value => eax
    21403       {
    21404 $check-mu-stmt-list:check-for-block:
    21405         81 7/subop/compare *eax 0/imm32/block  # Stmt-tag
    21406         75/jump-if-!= break/disp8
    21407 $check-mu-stmt-list:block:
    21408         (check-mu-block %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21409         eb/jump $check-mu-stmt-list:continue/disp8
    21410       }
    21411       {
    21412 $check-mu-stmt-list:check-for-stmt1:
    21413         81 7/subop/compare *eax 1/imm32/stmt1  # Stmt-tag
    21414         0f 85/jump-if-!= break/disp32
    21415 $check-mu-stmt-list:stmt1:
    21416         (check-mu-stmt %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21417         eb/jump $check-mu-stmt-list:continue/disp8
    21418       }
    21419       {
    21420 $check-mu-stmt-list:check-for-reg-var-def:
    21421         81 7/subop/compare *eax 3/imm32/reg-var-def  # Stmt-tag
    21422         0f 85/jump-if-!= break/disp32
    21423 $check-mu-stmt-list:reg-var-def:
    21424         (check-mu-stmt %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21425         eb/jump $check-mu-stmt-list:continue/disp8
    21426       }
    21427 $check-mu-stmt-list:continue:
    21428       # TODO: raise an error on unrecognized Stmt-tag
    21429       (lookup *(esi+8) *(esi+0xc))  # List-next List-next => eax
    21430       89/<- %esi 0/r32/eax
    21431       e9/jump loop/disp32
    21432     }
    21433 $check-mu-stmt-list:end:
    21434     # . restore registers
    21435     5e/pop-to-esi
    21436     58/pop-to-eax
    21437     # . epilogue
    21438     89/<- %esp 5/r32/ebp
    21439     5d/pop-to-ebp
    21440     c3/return
    21441
    21442 check-mu-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    21443     # . prologue
    21444     55/push-ebp
    21445     89/<- %ebp 4/r32/esp
    21446     # . save registers
    21447     50/push-eax
    21448     # - if stmt's operation matches a primitive, check against it
    21449     (has-primitive-name? *(ebp+8))  # => eax
    21450     3d/compare-eax-and 0/imm32/false
    21451     {
    21452       74/jump-if-= break/disp8
    21453       (check-mu-primitive *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21454       e9/jump $check-mu-stmt:end/disp32
    21455     }
    21456     # - otherwise find a function to check against
    21457     # var f/eax: (addr function) = lookup(*Program->functions)
    21458     (lookup *_Program-functions *_Program-functions->payload)  # => eax
    21459     (find-matching-function %eax *(ebp+8))  # => eax
    21460     3d/compare-eax-and 0/imm32
    21461     {
    21462       74/jump-if-= break/disp8
    21463       (check-mu-call *(ebp+8) %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21464       eb/jump $check-mu-stmt:end/disp8
    21465     }
    21466     # var f/eax: (addr function) = lookup(*Program->signatures)
    21467     (lookup *_Program-signatures *_Program-signatures->payload)  # => eax
    21468     (find-matching-function %eax *(ebp+8))  # => eax
    21469     3d/compare-eax-and 0/imm32
    21470     {
    21471       74/jump-if-= break/disp8
    21472       (check-mu-call *(ebp+8) %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21473       eb/jump $check-mu-stmt:end/disp8
    21474     }
    21475     # - otherwise abort
    21476     e9/jump $check-mu-stmt:unknown-call/disp32
    21477 $check-mu-stmt:end:
    21478     # . restore registers
    21479     58/pop-to-eax
    21480     # . epilogue
    21481     89/<- %esp 5/r32/ebp
    21482     5d/pop-to-ebp
    21483     c3/return
    21484
    21485 $check-mu-stmt:unknown-call:
    21486     (write-buffered *(ebp+0x10) "unknown function '")
    21487     8b/-> *(ebp+8) 0/r32/eax
    21488     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
    21489     (write-buffered *(ebp+0x10) %eax)
    21490     (write-buffered *(ebp+0x10) "'\n")
    21491     (flush *(ebp+0x10))
    21492     (stop *(ebp+0x14) 1)
    21493     # never gets here
    21494
    21495 has-primitive-name?:  # stmt: (addr stmt) -> result/eax: boolean
    21496     # . prologue
    21497     55/push-ebp
    21498     89/<- %ebp 4/r32/esp
    21499     # . save registers
    21500     51/push-ecx
    21501     56/push-esi
    21502     # var name/esi: (addr array byte) = lookup(stmt->operation)
    21503     8b/-> *(ebp+8) 6/r32/esi
    21504     (lookup *(esi+4) *(esi+8))  # Stmt1-operation Stmt1-operation => eax
    21505     89/<- %esi 0/r32/eax
    21506     # if (name == "return") return true
    21507     (string-equal? %esi "return")  # => eax
    21508     3d/compare-eax-and 0/imm32/false
    21509     0f 85/jump-if-!= $has-primitive-name?:end/disp32
    21510     # if (name == "get") return true
    21511     (string-equal? %esi "get")  # => eax
    21512     3d/compare-eax-and 0/imm32/false
    21513     0f 85/jump-if-!= $has-primitive-name?:end/disp32
    21514     # if (name == "index") return true
    21515     (string-equal? %esi "index")  # => eax
    21516     3d/compare-eax-and 0/imm32/false
    21517     0f 85/jump-if-!= $has-primitive-name?:end/disp32
    21518     # if (name == "length") return true
    21519     (string-equal? %esi "length")  # => eax
    21520     3d/compare-eax-and 0/imm32/false
    21521     0f 85/jump-if-!= $has-primitive-name?:end/disp32
    21522     # if (name == "compute-offset") return true
    21523     (string-equal? %esi "compute-offset")  # => eax
    21524     3d/compare-eax-and 0/imm32/false
    21525     0f 85/jump-if-!= $has-primitive-name?:end/disp32
    21526     # if (name == "copy-object") return true
    21527     (string-equal? %esi "copy-object")  # => eax
    21528     3d/compare-eax-and 0/imm32/false
    21529     0f 85/jump-if-!= $has-primitive-name?:end/disp32
    21530     # if (name == "clear-object") return true
    21531     (string-equal? %esi "clear-object")  # => eax
    21532     3d/compare-eax-and 0/imm32/false
    21533     0f 85/jump-if-!= $has-primitive-name?:end/disp32
    21534     # if (name == "allocate") return true
    21535     (string-equal? %esi "allocate")  # => eax
    21536     3d/compare-eax-and 0/imm32/false
    21537     0f 85/jump-if-!= $has-primitive-name?:end/disp32
    21538     # if (name == "populate") return true
    21539     (string-equal? %esi "populate")  # => eax
    21540     3d/compare-eax-and 0/imm32/false
    21541     0f 85/jump-if-!= $has-primitive-name?:end/disp32
    21542     # if (name == "populate-stream") return true
    21543     (string-equal? %esi "populate-stream")  # => eax
    21544     3d/compare-eax-and 0/imm32/false
    21545     0f 85/jump-if-!= $has-primitive-name?:end/disp32
    21546     # if (name == "read-from-stream") return true
    21547     (string-equal? %esi "read-from-stream")  # => eax
    21548     3d/compare-eax-and 0/imm32/false
    21549     0f 85/jump-if-!= $has-primitive-name?:end/disp32
    21550     # if (name == "write-to-stream") return true
    21551     (string-equal? %esi "write-to-stream")  # => eax
    21552     3d/compare-eax-and 0/imm32/false
    21553     0f 85/jump-if-!= $has-primitive-name?:end/disp32
    21554     # var curr/ecx: (addr primitive) = Primitives
    21555     b9/copy-to-ecx Primitives/imm32
    21556     {
    21557 $has-primitive-name?:loop:
    21558       # if (curr == null) break
    21559       81 7/subop/compare %ecx 0/imm32
    21560       74/jump-if-= break/disp8
    21561       # if (primitive->name == name) return true
    21562       (lookup *ecx *(ecx+4))  # Primitive-name Primitive-name => eax
    21563 #?       (write-buffered Stderr %eax)
    21564 #?       (write-buffered Stderr Newline)
    21565 #?       (flush Stderr)
    21566       (string-equal? %esi %eax)  # => eax
    21567       3d/compare-eax-and 0/imm32/false
    21568       75/jump-if-!= $has-primitive-name?:end/disp8
    21569 $has-primitive-name?:next-primitive:
    21570       # curr = curr->next
    21571       (lookup *(ecx+0x3c) *(ecx+0x40))  # Primitive-next Primitive-next => eax
    21572       89/<- %ecx 0/r32/eax
    21573       #
    21574       e9/jump loop/disp32
    21575     }
    21576     # return null
    21577     b8/copy-to-eax 0/imm32
    21578 $has-primitive-name?:end:
    21579     # . restore registers
    21580     5e/pop-to-esi
    21581     59/pop-to-ecx
    21582     # . epilogue
    21583     89/<- %esp 5/r32/ebp
    21584     5d/pop-to-ebp
    21585     c3/return
    21586
    21587 check-mu-primitive:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    21588     # . prologue
    21589     55/push-ebp
    21590     89/<- %ebp 4/r32/esp
    21591     # . save registers
    21592     50/push-eax
    21593     51/push-ecx
    21594     # var op/ecx: (addr array byte) = lookup(stmt->operation)
    21595     8b/-> *(ebp+8) 0/r32/eax
    21596     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
    21597     89/<- %ecx 0/r32/eax
    21598     # if (op == "copy") check-mu-copy-stmt
    21599     {
    21600       (string-equal? %ecx "copy")  # => eax
    21601       3d/compare-eax-and 0/imm32/false
    21602       74/jump-if-= break/disp8
    21603       (check-mu-copy-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21604       e9/jump $check-mu-primitive:end/disp32
    21605     }
    21606     # if (op == "copy-to") check-mu-copy-to-stmt
    21607     {
    21608       (string-equal? %ecx "copy-to")  # => eax
    21609       3d/compare-eax-and 0/imm32/false
    21610       74/jump-if-= break/disp8
    21611       (check-mu-copy-to-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21612       e9/jump $check-mu-primitive:end/disp32
    21613     }
    21614     # if (op == "copy-byte") check-mu-copy-byte-stmt
    21615     {
    21616       (string-equal? %ecx "copy-byte")  # => eax
    21617       3d/compare-eax-and 0/imm32/false
    21618       74/jump-if-= break/disp8
    21619       (check-mu-copy-byte-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21620       e9/jump $check-mu-primitive:end/disp32
    21621     }
    21622     # if (op == "copy-byte-to") check-mu-copy-byte-to-stmt
    21623     {
    21624       (string-equal? %ecx "copy-byte-to")  # => eax
    21625       3d/compare-eax-and 0/imm32/false
    21626       74/jump-if-= break/disp8
    21627       (check-mu-copy-byte-to-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21628       e9/jump $check-mu-primitive:end/disp32
    21629     }
    21630     # if (op == "compare") check-mu-compare-stmt
    21631     {
    21632       (string-equal? %ecx "compare")  # => eax
    21633       3d/compare-eax-and 0/imm32/false
    21634       74/jump-if-= break/disp8
    21635       (check-mu-compare-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21636       e9/jump $check-mu-primitive:end/disp32
    21637     }
    21638     # if (op == "address") check-mu-address-stmt
    21639     {
    21640       (string-equal? %ecx "address")  # => eax
    21641       3d/compare-eax-and 0/imm32/false
    21642       74/jump-if-= break/disp8
    21643       (check-mu-address-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21644       e9/jump $check-mu-primitive:end/disp32
    21645     }
    21646     # if (op == "return") check-mu-return-stmt
    21647     {
    21648       (string-equal? %ecx "return")  # => eax
    21649       3d/compare-eax-and 0/imm32/false
    21650       74/jump-if-= break/disp8
    21651       (check-mu-return-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21652       e9/jump $check-mu-primitive:end/disp32
    21653     }
    21654     # if (op == "get") check-mu-get-stmt
    21655     {
    21656       (string-equal? %ecx "get")  # => eax
    21657       3d/compare-eax-and 0/imm32/false
    21658       74/jump-if-= break/disp8
    21659       (check-mu-get-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21660       e9/jump $check-mu-primitive:end/disp32
    21661     }
    21662     # if (op == "index") check-mu-index-stmt
    21663     {
    21664       (string-equal? %ecx "index")  # => eax
    21665       3d/compare-eax-and 0/imm32/false
    21666       74/jump-if-= break/disp8
    21667       (check-mu-index-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21668       e9/jump $check-mu-primitive:end/disp32
    21669     }
    21670     # if (op == "length") check-mu-length-stmt
    21671     {
    21672       (string-equal? %ecx "length")  # => eax
    21673       3d/compare-eax-and 0/imm32/false
    21674       74/jump-if-= break/disp8
    21675       (check-mu-length-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21676       e9/jump $check-mu-primitive:end/disp32
    21677     }
    21678     # if (op == "compute-offset") check-mu-compute-offset-stmt
    21679     {
    21680       (string-equal? %ecx "compute-offset")  # => eax
    21681       3d/compare-eax-and 0/imm32/false
    21682       74/jump-if-= break/disp8
    21683       (check-mu-compute-offset-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21684       e9/jump $check-mu-primitive:end/disp32
    21685     }
    21686     # if (op == "copy-object") check-mu-copy-object-stmt
    21687     {
    21688       (string-equal? %ecx "copy-object")  # => eax
    21689       3d/compare-eax-and 0/imm32/false
    21690       74/jump-if-= break/disp8
    21691       (check-mu-copy-object-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21692       e9/jump $check-mu-primitive:end/disp32
    21693     }
    21694     # if (op == "clear-object") check-mu-clear-object-stmt
    21695     {
    21696       (string-equal? %ecx "clear-object")  # => eax
    21697       3d/compare-eax-and 0/imm32/false
    21698       74/jump-if-= break/disp8
    21699       (check-mu-clear-object-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21700       e9/jump $check-mu-primitive:end/disp32
    21701     }
    21702     # if (op == "allocate") check-mu-allocate-stmt
    21703     {
    21704       (string-equal? %ecx "allocate")  # => eax
    21705       3d/compare-eax-and 0/imm32/false
    21706       74/jump-if-= break/disp8
    21707       (check-mu-allocate-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21708       e9/jump $check-mu-primitive:end/disp32
    21709     }
    21710     # if (op == "populate") check-mu-populate-stmt
    21711     {
    21712       (string-equal? %ecx "populate")  # => eax
    21713       3d/compare-eax-and 0/imm32/false
    21714       74/jump-if-= break/disp8
    21715       (check-mu-populate-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21716       e9/jump $check-mu-primitive:end/disp32
    21717     }
    21718     # if (op == "populate-stream") check-mu-populate-stream-stmt
    21719     {
    21720       (string-equal? %ecx "populate-stream")  # => eax
    21721       3d/compare-eax-and 0/imm32/false
    21722       74/jump-if-= break/disp8
    21723       (check-mu-populate-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21724       e9/jump $check-mu-primitive:end/disp32
    21725     }
    21726     # if (op == "read-from-stream") check-mu-read-from-stream-stmt
    21727     {
    21728       (string-equal? %ecx "read-from-stream")  # => eax
    21729       3d/compare-eax-and 0/imm32/false
    21730       74/jump-if-= break/disp8
    21731       (check-mu-read-from-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21732       e9/jump $check-mu-primitive:end/disp32
    21733     }
    21734     # if (op == "write-to-stream") check-mu-write-to-stream-stmt
    21735     {
    21736       (string-equal? %ecx "write-to-stream")  # => eax
    21737       3d/compare-eax-and 0/imm32/false
    21738       74/jump-if-= break/disp8
    21739       (check-mu-write-to-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21740       e9/jump $check-mu-primitive:end/disp32
    21741     }
    21742     # if (op == "convert") check-mu-convert-stmt
    21743     {
    21744       (string-equal? %ecx "convert")  # => eax
    21745       3d/compare-eax-and 0/imm32/false
    21746       74/jump-if-= break/disp8
    21747       (check-mu-convert-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21748       e9/jump $check-mu-primitive:end/disp32
    21749     }
    21750     # otherwise check-numberlike-stmt
    21751     (check-mu-numberlike-primitive *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21752 $check-mu-primitive:end:
    21753     # . restore registers
    21754     59/pop-to-ecx
    21755     58/pop-to-eax
    21756     # . epilogue
    21757     89/<- %esp 5/r32/ebp
    21758     5d/pop-to-ebp
    21759     c3/return
    21760
    21761 # by default, Mu primitives should only operate on 'number-like' types
    21762 check-mu-numberlike-primitive:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    21763     # . prologue
    21764     55/push-ebp
    21765     89/<- %ebp 4/r32/esp
    21766     # . save registers
    21767     50/push-eax
    21768     51/push-ecx
    21769     56/push-esi
    21770     # esi = stmt
    21771     8b/-> *(ebp+8) 6/r32/esi
    21772     # var gas/ecx: int = 2
    21773     b9/copy-to-ecx 2/imm32
    21774     # - check at most 1 output
    21775     # var output/eax: (addr stmt-var) = stmt->outputs
    21776     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    21777     {
    21778       3d/compare-eax-and 0/imm32
    21779       74/jump-if-= break/disp8
    21780 $check-mu-numberlike-primitive:output:
    21781       (check-mu-numberlike-output %eax *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21782       (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    21783       3d/compare-eax-and 0/imm32
    21784       0f 85/jump-if-!= $check-mu-numberlike-primitive:error-too-many-outputs/disp32
    21785       # check output is in a register
    21786       # --gas
    21787       49/decrement-ecx
    21788     }
    21789     # - check first inout
    21790     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    21791     {
    21792       3d/compare-eax-and 0/imm32
    21793       0f 84/jump-if-= $check-mu-numberlike-primitive:end/disp32
    21794 $check-mu-numberlike-primitive:first-inout:
    21795       (check-mu-numberlike-arg %eax *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21796       # --gas
    21797       49/decrement-ecx
    21798     }
    21799     # - check second inout
    21800     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    21801     {
    21802       3d/compare-eax-and 0/imm32
    21803       74/jump-if-= $check-mu-numberlike-primitive:end/disp8
    21804 $check-mu-numberlike-primitive:second-inout:
    21805       # is a second inout allowed?
    21806       81 7/subop/compare %ecx 0/imm32
    21807       0f 84/jump-if-= $check-mu-numberlike-primitive:error-too-many-inouts/disp32
    21808 $check-mu-numberlike-primitive:second-inout-permitted:
    21809       (check-mu-numberlike-arg %eax *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21810     }
    21811 $check-mu-numberlike-primitive:third-inout:
    21812     # if there's a third arg, raise an error
    21813     81 7/subop/compare *(eax+8) 0/imm32  # Stmt-var-next
    21814     0f 85/jump-if-!= $check-mu-numberlike-primitive:error-too-many-inouts/disp32
    21815 $check-mu-numberlike-primitive:end:
    21816     # . restore registers
    21817     5e/pop-to-esi
    21818     59/pop-to-ecx
    21819     58/pop-to-eax
    21820     # . epilogue
    21821     89/<- %esp 5/r32/ebp
    21822     5d/pop-to-ebp
    21823     c3/return
    21824
    21825 $check-mu-numberlike-primitive:error-too-many-inouts:
    21826     (write-buffered *(ebp+0x10) "fn ")
    21827     8b/-> *(ebp+0xc) 0/r32/eax
    21828     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    21829     (write-buffered *(ebp+0x10) %eax)
    21830     (write-buffered *(ebp+0x10) ": stmt ")
    21831     (lookup *(esi+4) *(esi+8))  # Stmt1-operation Stmt1-operation => eax
    21832     (write-buffered *(ebp+0x10) %eax)
    21833     (write-buffered *(ebp+0x10) ": too many inouts; most primitives support at most two arguments, across inouts and outputs\n")
    21834     (flush *(ebp+0x10))
    21835     (stop *(ebp+0x14) 1)
    21836     # never gets here
    21837
    21838 $check-mu-numberlike-primitive:error-too-many-outputs:
    21839     (write-buffered *(ebp+0x10) "fn ")
    21840     8b/-> *(ebp+0xc) 0/r32/eax
    21841     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    21842     (write-buffered *(ebp+0x10) %eax)
    21843     (write-buffered *(ebp+0x10) ": stmt ")
    21844     (lookup *(esi+4) *(esi+8))  # Stmt1-operation Stmt1-operation => eax
    21845     (write-buffered *(ebp+0x10) %eax)
    21846     (write-buffered *(ebp+0x10) ": too many outputs; most primitives support at most one output\n")
    21847     (flush *(ebp+0x10))
    21848     (stop *(ebp+0x14) 1)
    21849     # never gets here
    21850
    21851 check-mu-numberlike-arg:  # v: (addr stmt-var), stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    21852     # . prologue
    21853     55/push-ebp
    21854     89/<- %ebp 4/r32/esp
    21855     # . save registers
    21856     50/push-eax
    21857     56/push-esi
    21858     # var t/esi: (addr type-tree) = lookup(v->value->type)
    21859     8b/-> *(ebp+8) 0/r32/eax
    21860     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    21861     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    21862     89/<- %esi 0/r32/eax
    21863 $check-mu-numberlike-arg:check-literal:
    21864     # if t is an int, return
    21865     (simple-mu-type? %esi 0)  # literal => eax
    21866     3d/compare-eax-and 0/imm32/false
    21867     0f 85/jump-if-!= $check-mu-numberlike-arg:end/disp32
    21868 $check-mu-numberlike-arg:check-addr:
    21869     # if t is an addr and v is dereferenced, return whether t->payload is an addr
    21870     {
    21871       (mu-addr-type? %esi)  # => eax
    21872       3d/compare-eax-and 0/imm32/false
    21873       74/jump-if-= break/disp8
    21874       8b/-> *(ebp+8) 0/r32/eax
    21875       8b/-> *(eax+0x10) 0/r32/eax  # Stmt-var-is-deref
    21876       3d/compare-eax-and 0/imm32/false
    21877       {
    21878         74/jump-if-= break/disp8
    21879         (lookup *(esi+0xc) *(esi+0x10))  # Type-tree-right Type-tree-right => eax
    21880         # if t->right is null, t = t->left
    21881         81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
    21882         {
    21883           75/jump-if-!= break/disp8
    21884           (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    21885         }
    21886         (mu-addr-type? %eax)  # => eax
    21887         3d/compare-eax-and 0/imm32/false
    21888         74/jump-if-= $check-mu-numberlike-arg:end/disp8
    21889       }
    21890     }
    21891 $check-mu-numberlike-arg:output-checks:
    21892     (check-mu-numberlike-output *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14) *(ebp+0x18))
    21893 $check-mu-numberlike-arg:end:
    21894     # . restore registers
    21895     5e/pop-to-esi
    21896     58/pop-to-eax
    21897     # . epilogue
    21898     89/<- %esp 5/r32/ebp
    21899     5d/pop-to-ebp
    21900     c3/return
    21901
    21902 check-mu-numberlike-output:  # v: (addr stmt-var), stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    21903     # . prologue
    21904     55/push-ebp
    21905     89/<- %ebp 4/r32/esp
    21906     # . save registers
    21907     50/push-eax
    21908     #
    21909     (mu-numberlike-output-var? *(ebp+8))  # => eax
    21910     3d/compare-eax-and 0/imm32/false
    21911     0f 84/jump-if-= $check-mu-numberlike-output:fail/disp32
    21912 $check-mu-numberlike-output:end:
    21913     # . restore registers
    21914     58/pop-to-eax
    21915     # . epilogue
    21916     89/<- %esp 5/r32/ebp
    21917     5d/pop-to-ebp
    21918     c3/return
    21919
    21920 $check-mu-numberlike-output:fail:
    21921     # otherwise raise an error
    21922     (write-buffered *(ebp+0x14) "fn ")
    21923     8b/-> *(ebp+0x10) 0/r32/eax
    21924     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    21925     (write-buffered *(ebp+0x14) %eax)
    21926     (write-buffered *(ebp+0x14) ": stmt ")
    21927     8b/-> *(ebp+0xc) 0/r32/eax
    21928     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
    21929     (write-buffered *(ebp+0x14) %eax)
    21930     (write-buffered *(ebp+0x14) ": '")
    21931     8b/-> *(ebp+8) 0/r32/eax
    21932     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    21933     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    21934     (write-buffered *(ebp+0x14) %eax)
    21935     (write-buffered *(ebp+0x14) "' must be a non-addr non-offset scalar\n")
    21936     (flush *(ebp+0x14))
    21937     (stop *(ebp+0x18) 1)
    21938     # never gets here
    21939
    21940 mu-numberlike-output-var?:  # v: (addr stmt-var) -> result/eax: boolean
    21941     # . prologue
    21942     55/push-ebp
    21943     89/<- %ebp 4/r32/esp
    21944     #
    21945     8b/-> *(ebp+8) 0/r32/eax
    21946     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    21947     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    21948     (mu-numberlike-output? %eax)  # => eax
    21949 $mu-numberlike-output-var?:end:
    21950     # . epilogue
    21951     89/<- %esp 5/r32/ebp
    21952     5d/pop-to-ebp
    21953     c3/return
    21954
    21955 mu-numberlike-output?:  # v: (addr type-tree) -> result/eax: boolean
    21956     # . prologue
    21957     55/push-ebp
    21958     89/<- %ebp 4/r32/esp
    21959     # . save registers
    21960     56/push-esi
    21961     # var t/esi: (addr type-tree) = lookup(v->value->type)
    21962     8b/-> *(ebp+8) 6/r32/esi
    21963 $mu-numberlike-output?:check-int:
    21964     # if t is an int, return
    21965     (simple-mu-type? %esi 1)  # int => eax
    21966     3d/compare-eax-and 0/imm32/false
    21967     0f 85/jump-if-!= $mu-numberlike-output?:return-true/disp32
    21968 $mu-numberlike-output?:check-float:
    21969     # if t is a float, return
    21970     (simple-mu-type? %esi 0xf)  # float => eax
    21971     3d/compare-eax-and 0/imm32/false
    21972     75/jump-if-!= $mu-numberlike-output?:return-true/disp8
    21973 $mu-numberlike-output?:check-boolean:
    21974     # if t is a boolean, return
    21975     (simple-mu-type? %esi 5)  # boolean => eax
    21976     3d/compare-eax-and 0/imm32/false
    21977     75/jump-if-!= $mu-numberlike-output?:return-true/disp8
    21978 $mu-numberlike-output?:check-byte:
    21979     # if t is a byte, return
    21980     (simple-mu-type? %esi 8)  # byte => eax
    21981     3d/compare-eax-and 0/imm32/false
    21982     75/jump-if-!= $mu-numberlike-output?:return-true/disp8
    21983 $mu-numberlike-output?:check-code-point:
    21984     # if t is a code-point, return
    21985     (simple-mu-type? %esi 0xd)  # code-point => eax
    21986     3d/compare-eax-and 0/imm32/false
    21987     75/jump-if-!= $mu-numberlike-output?:return-true/disp8
    21988 $mu-numberlike-output?:check-grapheme:
    21989     # if t is a grapheme, return
    21990     (simple-mu-type? %esi 0xe)  # grapheme => eax
    21991     3d/compare-eax-and 0/imm32/false
    21992     75/jump-if-!= $mu-numberlike-output?:return-true/disp8
    21993 $mu-numberlike-output?:return-false:
    21994     b8/copy-to-eax 0/imm32/false
    21995     eb/jump $mu-numberlike-output?:end/disp8
    21996 $mu-numberlike-output?:return-true:
    21997     b8/copy-to-eax 1/imm32/true
    21998 $mu-numberlike-output?:end:
    21999     # . restore registers
    22000     5e/pop-to-esi
    22001     # . epilogue
    22002     89/<- %esp 5/r32/ebp
    22003     5d/pop-to-ebp
    22004     c3/return
    22005
    22006 check-mu-copy-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    22007     # . prologue
    22008     55/push-ebp
    22009     89/<- %ebp 4/r32/esp
    22010     # . save registers
    22011     50/push-eax
    22012     51/push-ecx
    22013     52/push-edx
    22014     56/push-esi
    22015     57/push-edi
    22016     # var type-parameters/edx: (addr table (handle array byte) (addr type-tree) 8)
    22017     81 5/subop/subtract %esp 0x60/imm32
    22018     68/push 0x60/imm32/size
    22019     68/push 0/imm32/read
    22020     68/push 0/imm32/write
    22021     89/<- %edx 4/r32/esp
    22022 $check-mu-copy-stmt:get-output:
    22023     # esi = stmt
    22024     8b/-> *(ebp+8) 6/r32/esi
    22025     # var output/edi: (addr stmt-var) = stmt->outputs
    22026     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    22027     89/<- %edi 0/r32/eax
    22028     # zero outputs
    22029     3d/compare-eax-and 0/imm32
    22030     0f 84/jump-if-= $check-mu-copy-stmt:error-no-output/disp32
    22031     # > 1 output
    22032     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
    22033     3d/compare-eax-and 0/imm32
    22034     0f 85/jump-if-!= $check-mu-copy-stmt:error-too-many-outputs/disp32
    22035 $check-mu-copy-stmt:get-inout:
    22036     # var inout/esi: (addr stmt-var) = stmt->inouts
    22037     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    22038     89/<- %esi 0/r32/eax
    22039     # zero inouts
    22040     3d/compare-eax-and 0/imm32
    22041     0f 84/jump-if-= $check-mu-copy-stmt:error-no-inout/disp32
    22042     # > 1 inout
    22043     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
    22044     3d/compare-eax-and 0/imm32
    22045     0f 85/jump-if-!= $check-mu-copy-stmt:error-too-many-inouts/disp32
    22046 $check-mu-copy-stmt:types:
    22047     # if inout is not a scalar, abort
    22048     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    22049     (size-of %eax)  # => eax
    22050     3d/compare-eax-and 4/imm32
    22051     0f 8f/jump-if-> $check-mu-copy-stmt:error-inout-too-large/disp32
    22052     # var inout-type/ecx: (addr type-tree) = inout->value->type
    22053     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    22054     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    22055     89/<- %ecx 0/r32/eax
    22056     # if (inout->is-deref?) inout-type = inout-type->payload
    22057     8b/-> *(esi+0x10) 0/r32/eax  # Stmt-var-is-deref
    22058     3d/compare-eax-and 0/imm32/false
    22059     {
    22060       74/jump-if-= break/disp8
    22061       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
    22062       # if inout-type->right is null, t = inout-type->left
    22063       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
    22064       {
    22065         75/jump-if-!= break/disp8
    22066         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    22067       }
    22068       89/<- %ecx 0/r32/eax
    22069     }
    22070     # if output not in register, abort
    22071     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    22072     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    22073     3d/compare-eax-and 0/imm32
    22074     0f 84/jump-if-= $check-mu-copy-stmt:error-output-not-in-register/disp32
    22075     # var output-type/eax: (addr type-tree) = output->value->type
    22076     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    22077     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    22078     # if (inout-type == output-type) return
    22079     (type-match? %eax %ecx %edx)  # => eax
    22080     3d/compare-eax-and 0/imm32
    22081     0f 85/jump-if-!= $check-mu-copy-stmt:end/disp32
    22082     # if output is an addr and inout is 0, return
    22083     {
    22084       (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    22085       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    22086       (mu-addr-type? %eax)  # => eax
    22087       3d/compare-eax-and 0/imm32/false
    22088       74/jump-if-= break/disp8
    22089       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    22090       (lookup *eax *(eax+4))  # Var-name Var-name => eax
    22091       (string-equal? %eax "0")  # => eax
    22092       3d/compare-eax-and 0/imm32/false
    22093       74/jump-if-= break/disp8
    22094       e9/jump $check-mu-copy-stmt:end/disp32
    22095     }
    22096     # if output is an offset and inout is 0, return
    22097     {
    22098       (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    22099       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    22100       81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
    22101       75/jump-if-!= break/disp8
    22102       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    22103       (simple-mu-type? %eax 7)  # offset => eax
    22104       3d/compare-eax-and 0/imm32/false
    22105       74/jump-if-= break/disp8
    22106       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    22107       (lookup *eax *(eax+4))  # Var-name Var-name => eax
    22108       (string-equal? %eax "0")  # => eax
    22109       3d/compare-eax-and 0/imm32/false
    22110       74/jump-if-= break/disp8
    22111       e9/jump $check-mu-copy-stmt:end/disp32
    22112     }
    22113     # if output is a byte, abort if inout is not a literal. Otherwise return.
    22114     {
    22115       (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    22116       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    22117       (simple-mu-type? %eax 8)  # byte => eax
    22118       3d/compare-eax-and 0/imm32/false
    22119       74/jump-if-= break/disp8
    22120       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    22121       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    22122       (simple-mu-type? %eax 0)  # literal => eax
    22123       3d/compare-eax-and 0/imm32/false
    22124       0f 84/jump-if-= $check-mu-copy-stmt:error-non-literal-to-byte/disp32
    22125       eb/jump $check-mu-copy-stmt:end/disp8
    22126     }
    22127     # if output is not number-like, abort
    22128     (check-mu-numberlike-output %edi *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    22129 $check-mu-copy-stmt:end:
    22130     # . reclaim locals
    22131     81 0/subop/add %esp 0x6c/imm32
    22132     # . restore registers
    22133     5f/pop-to-edi
    22134     5e/pop-to-esi
    22135     5a/pop-to-edx
    22136     59/pop-to-ecx
    22137     58/pop-to-eax
    22138     # . epilogue
    22139     89/<- %esp 5/r32/ebp
    22140     5d/pop-to-ebp
    22141     c3/return
    22142
    22143 $check-mu-copy-stmt:error-no-inout:
    22144     (write-buffered *(ebp+0x10) "fn ")
    22145     8b/-> *(ebp+0xc) 0/r32/eax
    22146     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22147     (write-buffered *(ebp+0x10) %eax)
    22148     (write-buffered *(ebp+0x10) ": stmt 'copy' expects an inout\n")
    22149     (flush *(ebp+0x10))
    22150     (stop *(ebp+0x14) 1)
    22151     # never gets here
    22152
    22153 $check-mu-copy-stmt:error-too-many-inouts:
    22154     (write-buffered *(ebp+0x10) "fn ")
    22155     8b/-> *(ebp+0xc) 0/r32/eax
    22156     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22157     (write-buffered *(ebp+0x10) %eax)
    22158     (write-buffered *(ebp+0x10) ": stmt 'copy' must have just one inout\n")
    22159     (flush *(ebp+0x10))
    22160     (stop *(ebp+0x14) 1)
    22161     # never gets here
    22162
    22163 $check-mu-copy-stmt:error-no-output:
    22164     (write-buffered *(ebp+0x10) "fn ")
    22165     8b/-> *(ebp+0xc) 0/r32/eax
    22166     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22167     (write-buffered *(ebp+0x10) %eax)
    22168     (write-buffered *(ebp+0x10) ": stmt 'copy' expects an output\n")
    22169     (flush *(ebp+0x10))
    22170     (stop *(ebp+0x14) 1)
    22171     # never gets here
    22172
    22173 $check-mu-copy-stmt:error-output-not-in-register:
    22174     (write-buffered *(ebp+0x10) "fn ")
    22175     8b/-> *(ebp+0xc) 0/r32/eax
    22176     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22177     (write-buffered *(ebp+0x10) %eax)
    22178     (write-buffered *(ebp+0x10) ": stmt copy: output '")
    22179     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    22180     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    22181     (write-buffered *(ebp+0x10) %eax)
    22182     (write-buffered *(ebp+0x10) "' not in a register\n")
    22183     (flush *(ebp+0x10))
    22184     (stop *(ebp+0x14) 1)
    22185     # never gets here
    22186
    22187 $check-mu-copy-stmt:error-too-many-outputs:
    22188     (write-buffered *(ebp+0x10) "fn ")
    22189     8b/-> *(ebp+0xc) 0/r32/eax
    22190     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22191     (write-buffered *(ebp+0x10) %eax)
    22192     (write-buffered *(ebp+0x10) ": stmt 'copy' must have just one output\n")
    22193     (flush *(ebp+0x10))
    22194     (stop *(ebp+0x14) 1)
    22195     # never gets here
    22196
    22197 $check-mu-copy-stmt:error-inout-too-large:
    22198     (write-buffered *(ebp+0x10) "fn ")
    22199     8b/-> *(ebp+0xc) 0/r32/eax
    22200     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22201     (write-buffered *(ebp+0x10) %eax)
    22202     (write-buffered *(ebp+0x10) ": stmt copy: '")
    22203     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    22204     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    22205     (write-buffered *(ebp+0x10) %eax)
    22206     (write-buffered *(ebp+0x10) "' is too large to fit in a register\n")
    22207     (flush *(ebp+0x10))
    22208     (stop *(ebp+0x14) 1)
    22209     # never gets here
    22210
    22211 $check-mu-copy-stmt:error-non-literal-to-byte:
    22212     (write-buffered *(ebp+0x10) "fn ")
    22213     8b/-> *(ebp+0xc) 0/r32/eax
    22214     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22215     (write-buffered *(ebp+0x10) %eax)
    22216     (write-buffered *(ebp+0x10) ": stmt copy: cannot copy non-literal to '")
    22217     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    22218     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    22219     (write-buffered *(ebp+0x10) %eax)
    22220     (write-buffered *(ebp+0x10) "' of type byte; use copy-byte\n")
    22221     (flush *(ebp+0x10))
    22222     (stop *(ebp+0x14) 1)
    22223     # never gets here
    22224
    22225 check-mu-copy-to-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    22226     # . prologue
    22227     55/push-ebp
    22228     89/<- %ebp 4/r32/esp
    22229     # . save registers
    22230     50/push-eax
    22231     51/push-ecx
    22232     52/push-edx
    22233     53/push-ebx
    22234     56/push-esi
    22235     57/push-edi
    22236     # var type-parameters/edx: (addr table (handle array byte) (addr type-tree) 8)
    22237     81 5/subop/subtract %esp 0x60/imm32
    22238     68/push 0x60/imm32/size
    22239     68/push 0/imm32/read
    22240     68/push 0/imm32/write
    22241     89/<- %edx 4/r32/esp
    22242     # esi = stmt
    22243     8b/-> *(ebp+8) 6/r32/esi
    22244 $check-mu-copy-to-stmt:check-for-output:
    22245     # if stmt->outputs abort
    22246     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    22247     3d/compare-eax-and 0/imm32
    22248     0f 85/jump-if-!= $check-mu-copy-to-stmt:error-too-many-outputs/disp32
    22249 $check-mu-copy-to-stmt:get-dest:
    22250     # var dest/edi: (addr stmt-var) = stmt->inouts
    22251     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    22252     89/<- %edi 0/r32/eax
    22253     # zero inouts
    22254     3d/compare-eax-and 0/imm32
    22255     0f 84/jump-if-= $check-mu-copy-to-stmt:error-incorrect-inouts/disp32
    22256 $check-mu-copy-to-stmt:get-src:
    22257     # var src/esi: (addr stmt-var) = dest->next
    22258     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
    22259     89/<- %esi 0/r32/eax
    22260     # 1 inout
    22261     3d/compare-eax-and 0/imm32
    22262     0f 84/jump-if-= $check-mu-copy-to-stmt:error-incorrect-inouts/disp32
    22263     # > 2 inouts
    22264     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
    22265     3d/compare-eax-and 0/imm32
    22266     0f 85/jump-if-!= $check-mu-copy-to-stmt:error-incorrect-inouts/disp32
    22267 $check-mu-copy-to-stmt:types:
    22268     # if src is not a scalar, abort
    22269     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    22270     (size-of %eax)  # => eax
    22271     3d/compare-eax-and 4/imm32
    22272     0f 8f/jump-if-> $check-mu-copy-to-stmt:error-src-too-large/disp32
    22273     # var src-type/ecx: (addr type-tree) = src->value->type
    22274     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    22275     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    22276     89/<- %ecx 0/r32/eax
    22277     # if src not in register or literal, abort
    22278     # (we can't use stack-offset because it hasn't been computed yet)
    22279     {
    22280       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    22281       (lookup *(eax+0x8) *(eax+0xc))  # Var-type Var-type => eax
    22282       (simple-mu-type? %eax 0)  # => eax
    22283       3d/compare-eax-and 0/imm32
    22284       75/jump-if-!= break/disp8
    22285       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    22286       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    22287       3d/compare-eax-and 0/imm32
    22288       75/jump-if-!= break/disp8
    22289       e9/jump $check-mu-copy-to-stmt:error-src-not-literal-or-in-register/disp32
    22290     }
    22291     # var dest-type/ebx: (addr type-tree) = dest->value->type
    22292     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    22293     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    22294     89/<- %ebx 0/r32/eax
    22295     # if (dest->is-deref?) dest-type = dest-type->payload
    22296 $check-mu-copy-to-stmt:check-dest-deref:
    22297     8b/-> *(edi+0x10) 0/r32/eax  # Stmt-var-is-deref
    22298     3d/compare-eax-and 0/imm32/false
    22299     {
    22300       74/jump-if-= break/disp8
    22301       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
    22302 $check-mu-copy-to-stmt:dest-is-deref:
    22303       # if dest-type->right is null, dest-type = dest-type->left
    22304       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
    22305       {
    22306         75/jump-if-!= break/disp8
    22307 $check-mu-copy-to-stmt:dest-is-deref2:
    22308         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    22309       }
    22310       89/<- %ebx 0/r32/eax
    22311     }
    22312     # if dest is a byte and src is not a literal, abort
    22313     {
    22314 $check-mu-copy-to-stmt:final-check-byte:
    22315       (simple-mu-type? %ebx 8)  # byte => eax
    22316       3d/compare-eax-and 0/imm32/false
    22317       74/jump-if-= break/disp8
    22318       (simple-mu-type? %ecx 0)  # literal => eax
    22319       3d/compare-eax-and 0/imm32/false
    22320       0f 84/jump-if-= $check-mu-copy-to-stmt:error-non-literal-to-byte/disp32
    22321     }
    22322     # if (src-type == dest-type) return
    22323     (type-match? %ebx %ecx %edx)  # => eax
    22324     3d/compare-eax-and 0/imm32
    22325     0f 85/jump-if-!= $check-mu-copy-to-stmt:end/disp32
    22326     # if dest is an addr and src is 0, return
    22327     {
    22328 $check-mu-copy-to-stmt:final-check-addr:
    22329       (mu-addr-type? %ebx)  # => eax
    22330       3d/compare-eax-and 0/imm32/false
    22331       74/jump-if-= break/disp8
    22332       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    22333       (lookup *eax *(eax+4))  # Var-name Var-name => eax
    22334       (string-equal? %eax "0")  # => eax
    22335       3d/compare-eax-and 0/imm32/false
    22336       74/jump-if-= break/disp8
    22337       e9/jump $check-mu-copy-to-stmt:end/disp32
    22338     }
    22339     # if dest is an offset and src is 0, return
    22340     {
    22341 $check-mu-copy-to-stmt:final-check-offset:
    22342       81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
    22343       75/jump-if-!= break/disp8
    22344       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
    22345       (simple-mu-type? %eax 7)  # offset => eax
    22346       3d/compare-eax-and 0/imm32/false
    22347       74/jump-if-= break/disp8
    22348       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    22349       (lookup *eax *(eax+4))  # Var-name Var-name => eax
    22350       (string-equal? %eax "0")  # => eax
    22351       3d/compare-eax-and 0/imm32/false
    22352       74/jump-if-= break/disp8
    22353       e9/jump $check-mu-copy-to-stmt:end/disp32
    22354     }
    22355     # if dest is not number-like, abort
    22356     (check-mu-numberlike-arg %edi *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    22357 $check-mu-copy-to-stmt:end:
    22358     # . reclaim locals
    22359     81 0/subop/add %esp 0x6c/imm32
    22360     # . restore registers
    22361     5f/pop-to-edi
    22362     5e/pop-to-esi
    22363     5b/pop-to-ebx
    22364     5a/pop-to-edx
    22365     59/pop-to-ecx
    22366     58/pop-to-eax
    22367     # . epilogue
    22368     89/<- %esp 5/r32/ebp
    22369     5d/pop-to-ebp
    22370     c3/return
    22371
    22372 $check-mu-copy-to-stmt:error-incorrect-inouts:
    22373     (write-buffered *(ebp+0x10) "fn ")
    22374     8b/-> *(ebp+0xc) 0/r32/eax
    22375     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22376     (write-buffered *(ebp+0x10) %eax)
    22377     (write-buffered *(ebp+0x10) ": stmt 'copy-to' must have two inouts\n")
    22378     (flush *(ebp+0x10))
    22379     (stop *(ebp+0x14) 1)
    22380     # never gets here
    22381
    22382 $check-mu-copy-to-stmt:error-too-many-outputs:
    22383     (write-buffered *(ebp+0x10) "fn ")
    22384     8b/-> *(ebp+0xc) 0/r32/eax
    22385     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22386     (write-buffered *(ebp+0x10) %eax)
    22387     (write-buffered *(ebp+0x10) ": stmt 'copy-to' must not have any outputs\n")
    22388     (flush *(ebp+0x10))
    22389     (stop *(ebp+0x14) 1)
    22390     # never gets here
    22391
    22392 $check-mu-copy-to-stmt:error-src-not-literal-or-in-register:
    22393     (write-buffered *(ebp+0x10) "fn ")
    22394     8b/-> *(ebp+0xc) 0/r32/eax
    22395     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22396     (write-buffered *(ebp+0x10) %eax)
    22397     (write-buffered *(ebp+0x10) ": stmt copy-to: source (second inout) is in memory\n")
    22398     (flush *(ebp+0x10))
    22399     (stop *(ebp+0x14) 1)
    22400     # never gets here
    22401
    22402 $check-mu-copy-to-stmt:error-src-too-large:
    22403     (write-buffered *(ebp+0x10) "fn ")
    22404     8b/-> *(ebp+0xc) 0/r32/eax
    22405     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22406     (write-buffered *(ebp+0x10) %eax)
    22407     (write-buffered *(ebp+0x10) ": stmt copy-to: '")
    22408     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    22409     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    22410     (write-buffered *(ebp+0x10) %eax)
    22411     (write-buffered *(ebp+0x10) "' is too large to copy\n")
    22412     (flush *(ebp+0x10))
    22413     (stop *(ebp+0x14) 1)
    22414     # never gets here
    22415
    22416 $check-mu-copy-to-stmt:error-non-literal-to-byte:
    22417     (write-buffered *(ebp+0x10) "fn ")
    22418     8b/-> *(ebp+0xc) 0/r32/eax
    22419     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22420     (write-buffered *(ebp+0x10) %eax)
    22421     (write-buffered *(ebp+0x10) ": stmt copy-to: cannot copy non-literal to type byte; use copy-byte-to\n")
    22422     (flush *(ebp+0x10))
    22423     (stop *(ebp+0x14) 1)
    22424     # never gets here
    22425
    22426 check-mu-copy-byte-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    22427     # . prologue
    22428     55/push-ebp
    22429     89/<- %ebp 4/r32/esp
    22430     # . save registers
    22431     50/push-eax
    22432     51/push-ecx
    22433     52/push-edx
    22434     56/push-esi
    22435     57/push-edi
    22436     # var type-parameters/edx: (addr table (handle array byte) (addr type-tree) 8)
    22437     81 5/subop/subtract %esp 0x60/imm32
    22438     68/push 0x60/imm32/size
    22439     68/push 0/imm32/read
    22440     68/push 0/imm32/write
    22441     89/<- %edx 4/r32/esp
    22442 $check-mu-copy-byte-stmt:get-output:
    22443     # esi = stmt
    22444     8b/-> *(ebp+8) 6/r32/esi
    22445     # var output/edi: (addr stmt-var) = stmt->outputs
    22446     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    22447     89/<- %edi 0/r32/eax
    22448     # zero outputs
    22449     3d/compare-eax-and 0/imm32
    22450     0f 84/jump-if-= $check-mu-copy-byte-stmt:error-no-output/disp32
    22451     # > 1 output
    22452     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
    22453     3d/compare-eax-and 0/imm32
    22454     0f 85/jump-if-!= $check-mu-copy-byte-stmt:error-too-many-outputs/disp32
    22455 $check-mu-copy-byte-stmt:get-inout:
    22456     # var inout/esi: (addr stmt-var) = stmt->inouts
    22457     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    22458     89/<- %esi 0/r32/eax
    22459     # zero inouts
    22460     3d/compare-eax-and 0/imm32
    22461     0f 84/jump-if-= $check-mu-copy-byte-stmt:error-no-inout/disp32
    22462     # > 1 inout
    22463     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
    22464     3d/compare-eax-and 0/imm32
    22465     0f 85/jump-if-!= $check-mu-copy-byte-stmt:error-too-many-inouts/disp32
    22466 $check-mu-copy-byte-stmt:types:
    22467     # if inout is not a scalar, abort
    22468     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    22469     (size-of %eax)  # => eax
    22470     3d/compare-eax-and 4/imm32
    22471     0f 8f/jump-if-> $check-mu-copy-byte-stmt:error-inout-too-large/disp32
    22472     # var inout-type/ecx: (addr type-tree) = inout->value->type
    22473     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    22474     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    22475     89/<- %ecx 0/r32/eax
    22476 $check-mu-copy-byte-stmt:check-inout-deref:
    22477     # if (inout->is-deref?) inout-type = inout-type->payload
    22478     8b/-> *(esi+0x10) 0/r32/eax  # Stmt-var-is-deref
    22479     3d/compare-eax-and 0/imm32/false
    22480     {
    22481       74/jump-if-= break/disp8
    22482 $check-mu-copy-byte-stmt:inout-is-deref:
    22483       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
    22484       # if inout-type->right is null, t = inout-type->left
    22485       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
    22486       {
    22487         75/jump-if-!= break/disp8
    22488 $check-mu-copy-byte-stmt:inout-is-deref2:
    22489         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    22490       }
    22491       89/<- %ecx 0/r32/eax
    22492     }
    22493     # if output not in register, abort
    22494     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    22495     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    22496     3d/compare-eax-and 0/imm32
    22497     0f 84/jump-if-= $check-mu-copy-byte-stmt:error-output-not-in-register/disp32
    22498     # var output-type/eax: (addr type-tree) = output->value->type
    22499     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    22500     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    22501     # if output is not of type byte, abort
    22502     (simple-mu-type? %eax 8)  # byte => eax
    22503     3d/compare-eax-and 0/imm32
    22504     0f 84/jump-if-= $check-mu-copy-byte-stmt:error-invalid-output-type/disp32
    22505 $check-mu-copy-byte-stmt:end:
    22506     # . reclaim locals
    22507     81 0/subop/add %esp 0x6c/imm32
    22508     # . restore registers
    22509     5f/pop-to-edi
    22510     5e/pop-to-esi
    22511     5a/pop-to-edx
    22512     59/pop-to-ecx
    22513     58/pop-to-eax
    22514     # . epilogue
    22515     89/<- %esp 5/r32/ebp
    22516     5d/pop-to-ebp
    22517     c3/return
    22518
    22519 $check-mu-copy-byte-stmt:error-no-inout:
    22520     (write-buffered *(ebp+0x10) "fn ")
    22521     8b/-> *(ebp+0xc) 0/r32/eax
    22522     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22523     (write-buffered *(ebp+0x10) %eax)
    22524     (write-buffered *(ebp+0x10) ": stmt 'copy-byte' expects an inout\n")
    22525     (flush *(ebp+0x10))
    22526     (stop *(ebp+0x14) 1)
    22527     # never gets here
    22528
    22529 $check-mu-copy-byte-stmt:error-too-many-inouts:
    22530     (write-buffered *(ebp+0x10) "fn ")
    22531     8b/-> *(ebp+0xc) 0/r32/eax
    22532     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22533     (write-buffered *(ebp+0x10) %eax)
    22534     (write-buffered *(ebp+0x10) ": stmt 'copy-byte' must have just one inout\n")
    22535     (flush *(ebp+0x10))
    22536     (stop *(ebp+0x14) 1)
    22537     # never gets here
    22538
    22539 $check-mu-copy-byte-stmt:error-no-output:
    22540     (write-buffered *(ebp+0x10) "fn ")
    22541     8b/-> *(ebp+0xc) 0/r32/eax
    22542     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22543     (write-buffered *(ebp+0x10) %eax)
    22544     (write-buffered *(ebp+0x10) ": stmt 'copy-byte' expects an output\n")
    22545     (flush *(ebp+0x10))
    22546     (stop *(ebp+0x14) 1)
    22547     # never gets here
    22548
    22549 $check-mu-copy-byte-stmt:error-output-not-in-register:
    22550     (write-buffered *(ebp+0x10) "fn ")
    22551     8b/-> *(ebp+0xc) 0/r32/eax
    22552     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22553     (write-buffered *(ebp+0x10) %eax)
    22554     (write-buffered *(ebp+0x10) ": stmt copy-byte: output '")
    22555     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    22556     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    22557     (write-buffered *(ebp+0x10) %eax)
    22558     (write-buffered *(ebp+0x10) "' not in a register\n")
    22559     (flush *(ebp+0x10))
    22560     (stop *(ebp+0x14) 1)
    22561     # never gets here
    22562
    22563 $check-mu-copy-byte-stmt:error-too-many-outputs:
    22564     (write-buffered *(ebp+0x10) "fn ")
    22565     8b/-> *(ebp+0xc) 0/r32/eax
    22566     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22567     (write-buffered *(ebp+0x10) %eax)
    22568     (write-buffered *(ebp+0x10) ": stmt 'copy-byte' must have just one output\n")
    22569     (flush *(ebp+0x10))
    22570     (stop *(ebp+0x14) 1)
    22571     # never gets here
    22572
    22573 $check-mu-copy-byte-stmt:error-invalid-output-type:
    22574     (write-buffered *(ebp+0x10) "fn ")
    22575     8b/-> *(ebp+0xc) 0/r32/eax
    22576     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22577     (write-buffered *(ebp+0x10) %eax)
    22578     (write-buffered *(ebp+0x10) ": stmt 'copy-byte' must write to output of type byte\n")
    22579     (flush *(ebp+0x10))
    22580     (stop *(ebp+0x14) 1)
    22581     # never gets here
    22582
    22583 $check-mu-copy-byte-stmt:error-inout-too-large:
    22584     (write-buffered *(ebp+0x10) "fn ")
    22585     8b/-> *(ebp+0xc) 0/r32/eax
    22586     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22587     (write-buffered *(ebp+0x10) %eax)
    22588     (write-buffered *(ebp+0x10) ": stmt copy-byte: '")
    22589     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    22590     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    22591     (write-buffered *(ebp+0x10) %eax)
    22592     (write-buffered *(ebp+0x10) "' is too large to fit in a register\n")
    22593     (flush *(ebp+0x10))
    22594     (stop *(ebp+0x14) 1)
    22595     # never gets here
    22596
    22597 check-mu-copy-byte-to-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    22598     # . prologue
    22599     55/push-ebp
    22600     89/<- %ebp 4/r32/esp
    22601     # . save registers
    22602     50/push-eax
    22603     52/push-edx
    22604     53/push-ebx
    22605     56/push-esi
    22606     57/push-edi
    22607     # var type-parameters/edx: (addr table (handle array byte) (addr type-tree) 8)
    22608     81 5/subop/subtract %esp 0x60/imm32
    22609     68/push 0x60/imm32/size
    22610     68/push 0/imm32/read
    22611     68/push 0/imm32/write
    22612     89/<- %edx 4/r32/esp
    22613     # esi = stmt
    22614     8b/-> *(ebp+8) 6/r32/esi
    22615 $check-mu-copy-byte-to-stmt:check-for-output:
    22616     # if stmt->outputs abort
    22617     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    22618     3d/compare-eax-and 0/imm32
    22619     0f 85/jump-if-!= $check-mu-copy-byte-to-stmt:error-too-many-outputs/disp32
    22620 $check-mu-copy-byte-to-stmt:get-dest:
    22621     # var dest/edi: (addr stmt-var) = stmt->inouts
    22622     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    22623     89/<- %edi 0/r32/eax
    22624     # zero inouts
    22625     3d/compare-eax-and 0/imm32
    22626     0f 84/jump-if-= $check-mu-copy-byte-to-stmt:error-incorrect-inouts/disp32
    22627 $check-mu-copy-byte-to-stmt:get-src:
    22628     # var src/esi: (addr stmt-var) = dest->next
    22629     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
    22630     89/<- %esi 0/r32/eax
    22631     # 1 inout
    22632     3d/compare-eax-and 0/imm32
    22633     0f 84/jump-if-= $check-mu-copy-byte-to-stmt:error-incorrect-inouts/disp32
    22634     # > 2 inouts
    22635     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
    22636     3d/compare-eax-and 0/imm32
    22637     0f 85/jump-if-!= $check-mu-copy-byte-to-stmt:error-incorrect-inouts/disp32
    22638 $check-mu-copy-byte-to-stmt:types:
    22639     # if src is not a scalar, abort
    22640     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    22641     (size-of %eax)  # => eax
    22642     3d/compare-eax-and 4/imm32
    22643     0f 8f/jump-if-> $check-mu-copy-byte-to-stmt:error-src-too-large/disp32
    22644     # if src not in register, abort
    22645     {
    22646       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    22647       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    22648       3d/compare-eax-and 0/imm32
    22649       75/jump-if-!= break/disp8
    22650       e9/jump $check-mu-copy-byte-to-stmt:error-src-not-in-register/disp32
    22651     }
    22652     # var dest-type/ebx: (addr type-tree) = dest->value->type
    22653     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    22654     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    22655     89/<- %ebx 0/r32/eax
    22656     # if (dest->is-deref?) dest-type = dest-type->payload
    22657 $check-mu-copy-byte-to-stmt:check-dest-deref:
    22658     8b/-> *(edi+0x10) 0/r32/eax  # Stmt-var-is-deref
    22659     3d/compare-eax-and 0/imm32/false
    22660     {
    22661       74/jump-if-= break/disp8
    22662       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
    22663 $check-mu-copy-byte-to-stmt:dest-is-deref:
    22664       # if dest-type->right is null, dest-type = dest-type->left
    22665       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
    22666       {
    22667         75/jump-if-!= break/disp8
    22668 $check-mu-copy-byte-to-stmt:dest-is-deref2:
    22669         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    22670       }
    22671       89/<- %ebx 0/r32/eax
    22672     }
    22673     # if dest is not a byte, abort
    22674     (simple-mu-type? %ebx 8)  # byte => eax
    22675     3d/compare-eax-and 0/imm32/false
    22676     0f 84/jump-if-= $check-mu-copy-byte-to-stmt:error-invalid-dest-type/disp32
    22677 $check-mu-copy-byte-to-stmt:end:
    22678     # . reclaim locals
    22679     81 0/subop/add %esp 0x6c/imm32
    22680     # . restore registers
    22681     5f/pop-to-edi
    22682     5e/pop-to-esi
    22683     5b/pop-to-ebx
    22684     5a/pop-to-edx
    22685     58/pop-to-eax
    22686     # . epilogue
    22687     89/<- %esp 5/r32/ebp
    22688     5d/pop-to-ebp
    22689     c3/return
    22690
    22691 $check-mu-copy-byte-to-stmt:error-incorrect-inouts:
    22692     (write-buffered *(ebp+0x10) "fn ")
    22693     8b/-> *(ebp+0xc) 0/r32/eax
    22694     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22695     (write-buffered *(ebp+0x10) %eax)
    22696     (write-buffered *(ebp+0x10) ": stmt 'copy-byte-to' must have two inouts\n")
    22697     (flush *(ebp+0x10))
    22698     (stop *(ebp+0x14) 1)
    22699     # never gets here
    22700
    22701 $check-mu-copy-byte-to-stmt:error-too-many-outputs:
    22702     (write-buffered *(ebp+0x10) "fn ")
    22703     8b/-> *(ebp+0xc) 0/r32/eax
    22704     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22705     (write-buffered *(ebp+0x10) %eax)
    22706     (write-buffered *(ebp+0x10) ": stmt 'copy-byte-to' must not have any outputs\n")
    22707     (flush *(ebp+0x10))
    22708     (stop *(ebp+0x14) 1)
    22709     # never gets here
    22710
    22711 $check-mu-copy-byte-to-stmt:error-src-not-in-register:
    22712     (write-buffered *(ebp+0x10) "fn ")
    22713     8b/-> *(ebp+0xc) 0/r32/eax
    22714     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22715     (write-buffered *(ebp+0x10) %eax)
    22716     (write-buffered *(ebp+0x10) ": stmt copy-byte-to: source (second inout) must be in a register\n")
    22717     (flush *(ebp+0x10))
    22718     (stop *(ebp+0x14) 1)
    22719     # never gets here
    22720
    22721 $check-mu-copy-byte-to-stmt:error-invalid-dest-type:
    22722     (write-buffered *(ebp+0x10) "fn ")
    22723     8b/-> *(ebp+0xc) 0/r32/eax
    22724     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22725     (write-buffered *(ebp+0x10) %eax)
    22726     (write-buffered *(ebp+0x10) ": stmt copy-byte-to: '")
    22727     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    22728     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    22729     (write-buffered *(ebp+0x10) %eax)
    22730     (write-buffered *(ebp+0x10) "' must be a byte\n")
    22731     (flush *(ebp+0x10))
    22732     (stop *(ebp+0x14) 1)
    22733     # never gets here
    22734
    22735 $check-mu-copy-byte-to-stmt:error-src-too-large:
    22736     (write-buffered *(ebp+0x10) "fn ")
    22737     8b/-> *(ebp+0xc) 0/r32/eax
    22738     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22739     (write-buffered *(ebp+0x10) %eax)
    22740     (write-buffered *(ebp+0x10) ": stmt copy-byte-to: '")
    22741     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    22742     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    22743     (write-buffered *(ebp+0x10) %eax)
    22744     (write-buffered *(ebp+0x10) "' is too large to copy\n")
    22745     (flush *(ebp+0x10))
    22746     (stop *(ebp+0x14) 1)
    22747     # never gets here
    22748
    22749 check-mu-compare-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    22750     # . prologue
    22751     55/push-ebp
    22752     89/<- %ebp 4/r32/esp
    22753     # . save registers
    22754     50/push-eax
    22755     51/push-ecx
    22756     52/push-edx
    22757     53/push-ebx
    22758     56/push-esi
    22759     57/push-edi
    22760     # var type-parameters/edx: (addr table (handle array byte) (addr type-tree) 8)
    22761     81 5/subop/subtract %esp 0x60/imm32
    22762     68/push 0x60/imm32/size
    22763     68/push 0/imm32/read
    22764     68/push 0/imm32/write
    22765     89/<- %edx 4/r32/esp
    22766     # esi = stmt
    22767     8b/-> *(ebp+8) 6/r32/esi
    22768 $check-mu-compare-stmt:check-for-output:
    22769     # if stmt->outputs abort
    22770     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    22771     3d/compare-eax-and 0/imm32
    22772     0f 85/jump-if-!= $check-mu-compare-stmt:error-too-many-outputs/disp32
    22773 $check-mu-compare-stmt:get-left:
    22774     # var left/edi: (addr stmt-var) = stmt->inouts
    22775     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    22776     89/<- %edi 0/r32/eax
    22777     # zero inouts
    22778     3d/compare-eax-and 0/imm32
    22779     0f 84/jump-if-= $check-mu-compare-stmt:error-incorrect-inouts/disp32
    22780 $check-mu-compare-stmt:get-right:
    22781     # var right/esi: (addr stmt-var) = left->next
    22782     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
    22783     89/<- %esi 0/r32/eax
    22784     # 1 inout
    22785     3d/compare-eax-and 0/imm32
    22786     0f 84/jump-if-= $check-mu-compare-stmt:error-incorrect-inouts/disp32
    22787     # > 2 inouts
    22788     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
    22789     3d/compare-eax-and 0/imm32
    22790     0f 85/jump-if-!= $check-mu-compare-stmt:error-incorrect-inouts/disp32
    22791     # if both inouts are in memory, abort
    22792     {
    22793 $check-mu-compare-stmt:both-in-mem:
    22794       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    22795       (lookup *(eax+0x8) *(eax+0xc))  # Var-type Var-type => eax
    22796       (simple-mu-type? %eax 0)  # => eax
    22797       3d/compare-eax-and 0/imm32
    22798       0f 85/jump-if-!= break/disp32
    22799       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    22800       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    22801       3d/compare-eax-and 0/imm32
    22802       75/jump-if-!= break/disp8
    22803       (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    22804       (lookup *(eax+0x8) *(eax+0xc))  # Var-type Var-type => eax
    22805       (simple-mu-type? %eax 0)  # => eax
    22806       3d/compare-eax-and 0/imm32
    22807       75/jump-if-!= break/disp8
    22808       (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    22809       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    22810       3d/compare-eax-and 0/imm32
    22811       75/jump-if-!= break/disp8
    22812       e9/jump $check-mu-compare-stmt:error-both-in-memory/disp32
    22813     }
    22814 $check-mu-compare-stmt:types:
    22815     # var right-type/ecx: (addr type-tree) = right->value->type
    22816     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    22817     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    22818     89/<- %ecx 0/r32/eax
    22819     # if (right->is-deref?) right-type = right-type->payload
    22820     8b/-> *(esi+0x10) 0/r32/eax  # Stmt-var-is-deref
    22821     3d/compare-eax-and 0/imm32/false
    22822     {
    22823       74/jump-if-= break/disp8
    22824       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
    22825       # if right-type->right is null, right-type = right-type->left
    22826       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
    22827       {
    22828         75/jump-if-!= break/disp8
    22829         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    22830       }
    22831       89/<- %ecx 0/r32/eax
    22832     }
    22833     # if right-type is a literal string, abort
    22834     (simple-mu-type? %ecx 0x10)  # string-literal => eax
    22835     3d/compare-eax-and 0/imm32/false
    22836     0f 85/jump-if-!= $check-mu-compare-stmt:error-right-string-literal/disp32
    22837     # if right is not a scalar, abort
    22838     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    22839     (size-of %eax)  # => eax
    22840     3d/compare-eax-and 4/imm32
    22841     0f 8f/jump-if-> $check-mu-compare-stmt:error-right-too-large/disp32
    22842     # if left is not a scalar, abort
    22843     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    22844     (size-of %eax)  # => eax
    22845     3d/compare-eax-and 4/imm32
    22846     0f 8f/jump-if-> $check-mu-compare-stmt:error-left-too-large/disp32
    22847     # var left-type/ebx: (addr type-tree) = left->value->type
    22848     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    22849     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    22850     89/<- %ebx 0/r32/eax
    22851     # if (left->is-deref?) left-type = left-type->payload
    22852     8b/-> *(edi+0x10) 0/r32/eax  # Stmt-var-is-deref
    22853     3d/compare-eax-and 0/imm32/false
    22854     {
    22855       74/jump-if-= break/disp8
    22856       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
    22857       # if left-type->right is null, left-type = left-type->left
    22858       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
    22859       {
    22860         75/jump-if-!= break/disp8
    22861         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    22862       }
    22863       89/<- %ebx 0/r32/eax
    22864     }
    22865     # if (left-type == right-type) return
    22866     (type-match? %ebx %ecx %edx)  # => eax
    22867     3d/compare-eax-and 0/imm32
    22868     0f 85/jump-if-!= $check-mu-compare-stmt:end/disp32
    22869     # if left is an addr and right is 0, return
    22870     {
    22871       (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    22872       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    22873       (mu-addr-type? %eax)  # => eax
    22874       3d/compare-eax-and 0/imm32/false
    22875       74/jump-if-= break/disp8
    22876       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    22877       (lookup *eax *(eax+4))  # Var-name Var-name => eax
    22878       (string-equal? %eax "0")  # => eax
    22879       3d/compare-eax-and 0/imm32/false
    22880       74/jump-if-= break/disp8
    22881       eb/jump $check-mu-compare-stmt:end/disp8
    22882     }
    22883     # if left is not number-like, abort
    22884     (check-mu-numberlike-arg %edi *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    22885 $check-mu-compare-stmt:end:
    22886     # . reclaim locals
    22887     81 0/subop/add %esp 0x6c/imm32
    22888     # . restore registers
    22889     5f/pop-to-edi
    22890     5e/pop-to-esi
    22891     5b/pop-to-ebx
    22892     5a/pop-to-edx
    22893     59/pop-to-ecx
    22894     58/pop-to-eax
    22895     # . epilogue
    22896     89/<- %esp 5/r32/ebp
    22897     5d/pop-to-ebp
    22898     c3/return
    22899
    22900 $check-mu-compare-stmt:error-incorrect-inouts:
    22901     (write-buffered *(ebp+0x10) "fn ")
    22902     8b/-> *(ebp+0xc) 0/r32/eax
    22903     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22904     (write-buffered *(ebp+0x10) %eax)
    22905     (write-buffered *(ebp+0x10) ": stmt 'compare' must have two inouts\n")
    22906     (flush *(ebp+0x10))
    22907     (stop *(ebp+0x14) 1)
    22908     # never gets here
    22909
    22910 $check-mu-compare-stmt:error-too-many-outputs:
    22911     (write-buffered *(ebp+0x10) "fn ")
    22912     8b/-> *(ebp+0xc) 0/r32/eax
    22913     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22914     (write-buffered *(ebp+0x10) %eax)
    22915     (write-buffered *(ebp+0x10) ": stmt 'compare' must not have any outputs\n")
    22916     (flush *(ebp+0x10))
    22917     (stop *(ebp+0x14) 1)
    22918     # never gets here
    22919
    22920 $check-mu-compare-stmt:error-both-in-memory:
    22921     (write-buffered *(ebp+0x10) "fn ")
    22922     8b/-> *(ebp+0xc) 0/r32/eax
    22923     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22924     (write-buffered *(ebp+0x10) %eax)
    22925     (write-buffered *(ebp+0x10) ": stmt compare: both inouts are in memory\n")
    22926     (flush *(ebp+0x10))
    22927     (stop *(ebp+0x14) 1)
    22928     # never gets here
    22929
    22930 $check-mu-compare-stmt:error-left-too-large:
    22931     (write-buffered *(ebp+0x10) "fn ")
    22932     8b/-> *(ebp+0xc) 0/r32/eax
    22933     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22934     (write-buffered *(ebp+0x10) %eax)
    22935     (write-buffered *(ebp+0x10) ": stmt compare: '")
    22936     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    22937     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    22938     (write-buffered *(ebp+0x10) %eax)
    22939     (write-buffered *(ebp+0x10) "' is too large to compare\n")
    22940     (flush *(ebp+0x10))
    22941     (stop *(ebp+0x14) 1)
    22942     # never gets here
    22943
    22944 $check-mu-compare-stmt:error-right-too-large:
    22945     (write-buffered *(ebp+0x10) "fn ")
    22946     8b/-> *(ebp+0xc) 0/r32/eax
    22947     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22948     (write-buffered *(ebp+0x10) %eax)
    22949     (write-buffered *(ebp+0x10) ": stmt compare: '")
    22950     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    22951     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    22952     (write-buffered *(ebp+0x10) %eax)
    22953     (write-buffered *(ebp+0x10) "' is too large to compare\n")
    22954     (flush *(ebp+0x10))
    22955     (stop *(ebp+0x14) 1)
    22956     # never gets here
    22957
    22958 $check-mu-compare-stmt:error-right-string-literal:
    22959     (write-buffered *(ebp+0x10) "fn ")
    22960     8b/-> *(ebp+0xc) 0/r32/eax
    22961     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22962     (write-buffered *(ebp+0x10) %eax)
    22963     (write-buffered *(ebp+0x10) ": stmt compare: string literal ")
    22964     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    22965     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    22966     (write-buffered *(ebp+0x10) %eax)
    22967     (write-buffered *(ebp+0x10) " is not supported; use the string-equal? function\n")
    22968     (flush *(ebp+0x10))
    22969     (stop *(ebp+0x14) 1)
    22970     # never gets here
    22971
    22972 check-mu-address-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    22973     # . prologue
    22974     55/push-ebp
    22975     89/<- %ebp 4/r32/esp
    22976     # . save registers
    22977     50/push-eax
    22978     51/push-ecx
    22979     52/push-edx
    22980     56/push-esi
    22981     57/push-edi
    22982 $check-mu-address-stmt:get-output:
    22983     # esi = stmt
    22984     8b/-> *(ebp+8) 6/r32/esi
    22985     # var output/edi: (addr stmt-var) = stmt->outputs
    22986     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    22987     89/<- %edi 0/r32/eax
    22988     # zero outputs
    22989     3d/compare-eax-and 0/imm32
    22990     0f 84/jump-if-= $check-mu-address-stmt:error-no-output/disp32
    22991     # > 1 output
    22992     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
    22993     3d/compare-eax-and 0/imm32
    22994     0f 85/jump-if-!= $check-mu-address-stmt:error-too-many-outputs/disp32
    22995 $check-mu-address-stmt:get-inout:
    22996     # var inout/esi: (addr stmt-var) = stmt->inouts
    22997     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    22998     89/<- %esi 0/r32/eax
    22999     # zero inouts
    23000     3d/compare-eax-and 0/imm32
    23001     0f 84/jump-if-= $check-mu-address-stmt:error-no-inout/disp32
    23002     # > 1 inout
    23003     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
    23004     3d/compare-eax-and 0/imm32
    23005     0f 85/jump-if-!= $check-mu-address-stmt:error-too-many-inouts/disp32
    23006 $check-mu-address-stmt:types:
    23007     # if output not in register, abort
    23008     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    23009     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    23010     3d/compare-eax-and 0/imm32
    23011     0f 84/jump-if-= $check-mu-address-stmt:error-output-not-in-register/disp32
    23012     # var output-type/edx: (addr type-tree) = output->value->type
    23013     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    23014     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    23015     89/<- %edx 0/r32/eax
    23016     # if output-type not an addr, abort
    23017     (mu-addr-type? %edx)  # => eax
    23018     3d/compare-eax-and 0/imm32/false
    23019     0f 84/jump-if-= $check-mu-address-stmt:error-output-not-address/disp32
    23020     # output-type = output-type->right
    23021     (lookup *(edx+0xc) *(edx+0x10))  # Type-tree-right Type-tree-right => eax
    23022     # if output-type->right is null, output-type = output-type->left
    23023     81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
    23024     {
    23025       75/jump-if-!= break/disp8
    23026       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    23027     }
    23028     89/<- %edx 0/r32/eax
    23029     # var inout-type/ecx: (addr type-tree) = inout->value->type
    23030     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    23031     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    23032     89/<- %ecx 0/r32/eax
    23033     # if (inout->is-deref?) inout-type = inout-type->payload
    23034     8b/-> *(esi+0x10) 0/r32/eax  # Stmt-var-is-deref
    23035     3d/compare-eax-and 0/imm32/false
    23036     {
    23037       74/jump-if-= break/disp8
    23038       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
    23039       # if inout-type->right is null, t = inout-type->left
    23040       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
    23041       {
    23042         75/jump-if-!= break/disp8
    23043         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    23044       }
    23045       89/<- %ecx 0/r32/eax
    23046     }
    23047     # if (inout-type != output-type) abort
    23048     (type-equal-ignoring-capacity? %edx %ecx)  # => eax
    23049     3d/compare-eax-and 0/imm32
    23050     0f 84/jump-if-= $check-mu-address-stmt:error-type-mismatch/disp32
    23051 $check-mu-address-stmt:end:
    23052     # . restore registers
    23053     5f/pop-to-edi
    23054     5e/pop-to-esi
    23055     5a/pop-to-edx
    23056     59/pop-to-ecx
    23057     58/pop-to-eax
    23058     # . epilogue
    23059     89/<- %esp 5/r32/ebp
    23060     5d/pop-to-ebp
    23061     c3/return
    23062
    23063 $check-mu-address-stmt:error-no-inout:
    23064     (write-buffered *(ebp+0x10) "fn ")
    23065     8b/-> *(ebp+0xc) 0/r32/eax
    23066     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    23067     (write-buffered *(ebp+0x10) %eax)
    23068     (write-buffered *(ebp+0x10) ": stmt 'address' expects an inout\n")
    23069     (flush *(ebp+0x10))
    23070     (stop *(ebp+0x14) 1)
    23071     # never gets here
    23072
    23073 $check-mu-address-stmt:error-too-many-inouts:
    23074     (write-buffered *(ebp+0x10) "fn ")
    23075     8b/-> *(ebp+0xc) 0/r32/eax
    23076     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    23077     (write-buffered *(ebp+0x10) %eax)
    23078     (write-buffered *(ebp+0x10) ": stmt 'address' must have just one inout\n")
    23079     (flush *(ebp+0x10))
    23080     (stop *(ebp+0x14) 1)
    23081     # never gets here
    23082
    23083 $check-mu-address-stmt:error-no-output:
    23084     (write-buffered *(ebp+0x10) "fn ")
    23085     8b/-> *(ebp+0xc) 0/r32/eax
    23086     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    23087     (write-buffered *(ebp+0x10) %eax)
    23088     (write-buffered *(ebp+0x10) ": stmt 'address' expects an output\n")
    23089     (flush *(ebp+0x10))
    23090     (stop *(ebp+0x14) 1)
    23091     # never gets here
    23092
    23093 $check-mu-address-stmt:error-output-not-in-register:
    23094     (write-buffered *(ebp+0x10) "fn ")
    23095     8b/-> *(ebp+0xc) 0/r32/eax
    23096     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    23097     (write-buffered *(ebp+0x10) %eax)
    23098     (write-buffered *(ebp+0x10) ": stmt address: output '")
    23099     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    23100     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    23101     (write-buffered *(ebp+0x10) %eax)
    23102     (write-buffered *(ebp+0x10) "' not in a register\n")
    23103     (flush *(ebp+0x10))
    23104     (stop *(ebp+0x14) 1)
    23105     # never gets here
    23106
    23107 $check-mu-address-stmt:error-too-many-outputs:
    23108     (write-buffered *(ebp+0x10) "fn ")
    23109     8b/-> *(ebp+0xc) 0/r32/eax
    23110     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    23111     (write-buffered *(ebp+0x10) %eax)
    23112     (write-buffered *(ebp+0x10) ": stmt 'address' must have just one output\n")
    23113     (flush *(ebp+0x10))
    23114     (stop *(ebp+0x14) 1)
    23115     # never gets here
    23116
    23117 $check-mu-address-stmt:error-output-not-address:
    23118     (write-buffered *(ebp+0x10) "fn ")
    23119     8b/-> *(ebp+0xc) 0/r32/eax
    23120     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    23121     (write-buffered *(ebp+0x10) %eax)
    23122     (write-buffered *(ebp+0x10) ": stmt address: output '")
    23123     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    23124     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    23125     (write-buffered *(ebp+0x10) %eax)
    23126     (write-buffered *(ebp+0x10) "' is not an addr\n")
    23127     (flush *(ebp+0x10))
    23128     (stop *(ebp+0x14) 1)
    23129     # never gets here
    23130
    23131 $check-mu-address-stmt:error-type-mismatch:
    23132     (write-buffered *(ebp+0x10) "fn ")
    23133     8b/-> *(ebp+0xc) 0/r32/eax
    23134     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    23135     (write-buffered *(ebp+0x10) %eax)
    23136     (write-buffered *(ebp+0x10) ": stmt address: output '")
    23137     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    23138     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    23139     (write-buffered *(ebp+0x10) %eax)
    23140     (write-buffered *(ebp+0x10) "' cannot hold address of '")
    23141     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    23142     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    23143     (write-buffered *(ebp+0x10) %eax)
    23144     (write-buffered *(ebp+0x10) "'\n")
    23145     (flush *(ebp+0x10))
    23146     (stop *(ebp+0x14) 1)
    23147     # never gets here
    23148
    23149 type-equal-ignoring-capacity?:  # a: (addr type-tree), b: (addr type-tree) -> result/eax: boolean
    23150     # . prologue
    23151     55/push-ebp
    23152     89/<- %ebp 4/r32/esp
    23153     # . save registers
    23154     51/push-ecx
    23155     52/push-edx
    23156     53/push-ebx
    23157     # var curr-a/ecx: (addr type-tree) = a
    23158     8b/-> *(ebp+8) 1/r32/ecx
    23159     # var curr-b/ebx: (addr type-tree) = b
    23160     8b/-> *(ebp+0xc) 3/r32/ebx
    23161     # if (curr-a->is-atom?) fall back to regular equality
    23162     81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
    23163     0f 85/jump-if-!= $type-equal-ignoring-capacity?:base-case/disp32
    23164     # if (curr-a->left != curr-b->left) return false
    23165     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
    23166     89/<- %edx 0/r32/eax
    23167     (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
    23168     (type-equal? %edx %eax)  # => eax
    23169     3d/compare-eax-and 0/imm32/false
    23170     0f 84/jump-if-= $type-equal-ignoring-capacity?:end/disp32  # eax switches meaning
    23171     # if (curr-a->left == "array") curr-a = curr-a->element-type
    23172     {
    23173       (mu-array? %edx)  # => eax
    23174       3d/compare-eax-and 0/imm32/false
    23175       75/jump-if-!= break/disp8
    23176 $type-equal-ignoring-capacity?:array:
    23177       # curr-a = curr-a->right->left
    23178       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
    23179       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    23180       89/<- %ecx 0/r32/eax
    23181       # curr-b = curr-b->right->left
    23182       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
    23183       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    23184       89/<- %ebx 0/r32/eax
    23185       eb/jump $type-equal-ignoring-capacity?:base-case/disp8
    23186     }
    23187     # if (curr-a->left == "stream") curr-a = curr-a->element-type
    23188     {
    23189       (mu-stream? %edx)  # => eax
    23190       3d/compare-eax-and 0/imm32/false
    23191       75/jump-if-!= break/disp8
    23192 $type-equal-ignoring-capacity?:stream:
    23193       # curr-a = curr-a->right->left
    23194       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
    23195       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    23196       89/<- %ecx 0/r32/eax
    23197       # curr-b = curr-b->right->left
    23198       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
    23199       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    23200       89/<- %ebx 0/r32/eax
    23201       eb/jump $type-equal-ignoring-capacity?:base-case/disp8
    23202     }
    23203 $type-equal-ignoring-capacity?:base-case:
    23204     # return type-equal?(curr-a, curr-b)
    23205     (type-equal? %ecx %ebx)  # => eax
    23206 $type-equal-ignoring-capacity?:end:
    23207     # . restore registers
    23208     5b/pop-to-ebx
    23209     5a/pop-to-edx
    23210     59/pop-to-ecx
    23211     # . epilogue
    23212     89/<- %esp 5/r32/ebp
    23213     5d/pop-to-ebp
    23214     c3/return
    23215
    23216 check-mu-return-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    23217     # . prologue
    23218     55/push-ebp
    23219     89/<- %ebp 4/r32/esp
    23220     # . save registers
    23221     50/push-eax
    23222     51/push-ecx
    23223     52/push-edx
    23224     53/push-ebx
    23225     56/push-esi
    23226     57/push-edi
    23227     # var type-parameters/edx: (addr table (handle array byte) (addr type-tree) 8)
    23228     81 5/subop/subtract %esp 0x60/imm32
    23229     68/push 0x60/imm32/size
    23230     68/push 0/imm32/read
    23231     68/push 0/imm32/write
    23232     89/<- %edx 4/r32/esp
    23233     # var template/esi: (addr list var) = fn->outputs
    23234     8b/-> *(ebp+0xc) 0/r32/eax
    23235     (lookup *(eax+0x10) *(eax+0x14))  # Function-outputs Function-outputs => eax
    23236     89/<- %esi 0/r32/eax
    23237     # var curr-template/ebx: (addr list var) = fn->outputs
    23238     89/<- %ebx 0/r32/eax
    23239     # var curr/edi: (addr stmt-var) = stmt->inouts
    23240     8b/-> *(ebp+8) 0/r32/eax
    23241     (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    23242     89/<- %edi 0/r32/eax
    23243     {
    23244       # if template is null, break
    23245       81 7/subop/compare %ebx 0/imm32
    23246       0f 84/jump-if-= break/disp32
    23247       # if curr is null, abort
    23248       81 7/subop/compare %edi 0/imm32
    23249       0f 84/jump-if-= $check-mu-return-stmt:error-too-few-inouts/disp32
    23250       # var template-type/ecx: (addr type-tree) = template->value->type
    23251       (lookup *ebx *(ebx+4))  # List-value List-value => eax
    23252       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    23253       89/<- %ecx 0/r32/eax
    23254       # var curr-type/eax: (addr type-tree) = curr->value->type
    23255       (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    23256       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    23257       # if (curr->is-deref?) curr-type = payload of curr-type
    23258       81 7/subop/compare *(edi+0x10) 0/imm32/false  # Stmt-var-is-deref
    23259       {
    23260         74/jump-if-= break/disp8
    23261         (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
    23262         # if t->right is null, t = t->left
    23263         81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
    23264         75/jump-if-!= break/disp8
    23265         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    23266       }
    23267       # if curr-type is literal and template-type is float, abort
    23268       50/push-eax
    23269       {
    23270         (simple-mu-type? %eax 0)  # literal => eax
    23271         3d/compare-eax-and 0/imm32/false
    23272         74/jump-if-= break/disp8
    23273         (simple-mu-type? %ecx 0xf)  # float => eax
    23274         3d/compare-eax-and 0/imm32/false
    23275         0f 85/jump-if-!= $check-mu-return-stmt:error-literal-to-float/disp32
    23276       }
    23277       58/pop-to-eax
    23278       # if (curr-type != template-type) abort
    23279       (type-match? %ecx %eax %edx)  # => eax
    23280       3d/compare-eax-and 0/imm32/false
    23281       0f 84/jump-if-= $check-mu-return-stmt:error1/disp32
    23282       # if register-within-list-with-conflict?(curr, original template, curr-template, stmt) abort
    23283       (register-within-list-with-conflict? %edi %esi %ebx *(ebp+8))  # => eax
    23284       3d/compare-eax-and 0/imm32/false
    23285       0f 85/jump-if-!= $check-mu-return-stmt:error2/disp32
    23286       # template = template->next
    23287       (lookup *(ebx+8) *(ebx+0xc))  # List-next List-next => eax
    23288       89/<- %ebx 0/r32/eax
    23289       # curr = curr->next
    23290       (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
    23291       89/<- %edi 0/r32/eax
    23292       #
    23293       e9/jump loop/disp32
    23294     }
    23295     # if curr is not null, abort
    23296     81 7/subop/compare %edi 0/imm32
    23297     0f 85/jump-if-!= $check-mu-return-stmt:error-too-many-inouts/disp32
    23298 $check-mu-return-stmt:end:
    23299     # . reclaim locals
    23300     81 0/subop/add %esp 0x6c/imm32
    23301     # . restore registers
    23302     5f/pop-to-edi
    23303     5e/pop-to-esi
    23304     5b/pop-to-ebx
    23305     5a/pop-to-edx
    23306     59/pop-to-ecx
    23307     58/pop-to-eax
    23308     # . epilogue
    23309     89/<- %esp 5/r32/ebp
    23310     5d/pop-to-ebp
    23311     c3/return
    23312
    23313 $check-mu-return-stmt:error1:
    23314     (write-buffered *(ebp+0x10) "fn ")
    23315     8b/-> *(ebp+0xc) 0/r32/eax
    23316     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    23317     (write-buffered *(ebp+0x10) %eax)
    23318     (write-buffered *(ebp+0x10) ": return: '")
    23319     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    23320     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    23321     (write-buffered *(ebp+0x10) %eax)
    23322     (write-buffered *(ebp+0x10) "' has the wrong type\n")
    23323     (flush *(ebp+0x10))
    23324     (stop *(ebp+0x14) 1)
    23325     # never gets here
    23326
    23327 $check-mu-return-stmt:error2:
    23328     (write-buffered *(ebp+0x10) "fn ")
    23329     8b/-> *(ebp+0xc) 0/r32/eax
    23330     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    23331     (write-buffered *(ebp+0x10) %eax)
    23332     (write-buffered *(ebp+0x10) ": return: '")
    23333     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    23334     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    23335     (write-buffered *(ebp+0x10) %eax)
    23336     (write-buffered *(ebp+0x10) "' is no longer available\n")
    23337     (flush *(ebp+0x10))
    23338     (stop *(ebp+0x14) 1)
    23339     # never gets here
    23340
    23341 $check-mu-return-stmt:error-literal-to-float:
    23342     (write-buffered *(ebp+0x10) "fn ")
    23343     8b/-> *(ebp+0xc) 0/r32/eax
    23344     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    23345     (write-buffered *(ebp+0x10) %eax)
    23346     (write-buffered *(ebp+0x10) ": return: cannot copy literal '")
    23347     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    23348     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    23349     (write-buffered *(ebp+0x10) %eax)
    23350     (write-buffered *(ebp+0x10) "' to float\n")
    23351     (flush *(ebp+0x10))
    23352     (stop *(ebp+0x14) 1)
    23353     # never gets here
    23354
    23355 $check-mu-return-stmt:error-too-few-inouts:
    23356     (write-buffered *(ebp+0x10) "fn ")
    23357     8b/-> *(ebp+0xc) 0/r32/eax
    23358     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    23359     (write-buffered *(ebp+0x10) %eax)
    23360     (write-buffered *(ebp+0x10) ": return: too few inouts\n")
    23361     (flush *(ebp+0x10))
    23362     (stop *(ebp+0x14) 1)
    23363     # never gets here
    23364
    23365 $check-mu-return-stmt:error-too-many-inouts:
    23366     (write-buffered *(ebp+0x10) "fn ")
    23367     8b/-> *(ebp+0xc) 0/r32/eax
    23368     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    23369     (write-buffered *(ebp+0x10) %eax)
    23370     (write-buffered *(ebp+0x10) ": return: too many inouts\n")
    23371     (flush *(ebp+0x10))
    23372     (stop *(ebp+0x14) 1)
    23373     # never gets here
    23374
    23375 check-all-unique-registers:  # outputs: (addr list var), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    23376     # . prologue
    23377     55/push-ebp
    23378     89/<- %ebp 4/r32/esp
    23379     # . save registers
    23380     50/push-eax
    23381     51/push-ecx
    23382     56/push-esi
    23383     # var table/esi: (addr table (handle array byte) int 8)
    23384     81 5/subop/subtract %esp 0x60/imm32
    23385     68/push 0x60/imm32/size
    23386     68/push 0/imm32/read
    23387     68/push 0/imm32/write
    23388     89/<- %esi 4/r32/esp
    23389     # var curr/ecx: (addr list var) = outputs
    23390     8b/-> *(ebp+8) 1/r32/ecx
    23391     {
    23392       # if (curr == 0) break
    23393       81 7/subop/compare %ecx 0/imm32
    23394       0f 84/jump-if-= break/disp32
    23395       # var reg/eax: (addr array byte) = curr->value->register  # guaranteed to exist
    23396       (lookup *ecx *(ecx+4))  # List-value List-value => eax
    23397       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    23398       # if reg exists in table, abort
    23399       (maybe-get %esi %eax 0xc)  # => eax
    23400       3d/compare-eax-and 0/imm32
    23401       0f 85/jump-if-!= $check-all-unique-registers:abort/disp32
    23402       # insert reg in table
    23403       (lookup *ecx *(ecx+4))  # List-value List-value => eax
    23404       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    23405       (get-or-insert %esi %eax 0xc Heap)
    23406       # curr = curr->next
    23407       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
    23408       89/<- %ecx 0/r32/eax
    23409       e9/jump loop/disp32
    23410     }
    23411 $check-all-unique-registers:end:
    23412     # . reclaim locals
    23413     81 0/subop/add %esp 0x6c/imm32
    23414     # . restore registers
    23415     5e/pop-to-esi
    23416     59/pop-to-ecx
    23417     58/pop-to-eax
    23418     # . epilogue
    23419     89/<- %esp 5/r32/ebp
    23420     5d/pop-to-ebp
    23421     c3/return
    23422
    23423 $check-all-unique-registers:abort:
    23424     (write-buffered *(ebp+0x10) "fn ")
    23425     8b/-> *(ebp+0xc) 0/r32/eax
    23426     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    23427     (write-buffered *(ebp+0x10) %eax)
    23428     (write-buffered *(ebp+0x10) ": outputs must be in unique registers\n")
    23429     (flush *(ebp+0x10))
    23430     (stop *(ebp+0x14) 1)
    23431     # never gets here
    23432
    23433 # return false if s's register is not between start (inclusive) and end (exclusive)
    23434 # return false if the positionally corresponding register in stmt->inouts (where s comes from) is also s's register
    23435 # otherwise return true
    23436 register-within-list-with-conflict?:  # s: (addr stmt-var), start: (addr list var), end: (addr list var), stmt: (addr stmt) -> result/eax: boolean
    23437     # . prologue
    23438     55/push-ebp
    23439     89/<- %ebp 4/r32/esp
    23440     # . save registers
    23441     51/push-ecx
    23442     52/push-edx
    23443     53/push-ebx
    23444     56/push-esi
    23445     57/push-edi
    23446     # var target/ebx: (addr array byte) = s->value->register
    23447     8b/-> *(ebp+8) 0/r32/eax
    23448     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    23449     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    23450 #?     (write-buffered Stderr "AA: ")
    23451 #?     (write-buffered Stderr %eax)
    23452 #?     (write-buffered Stderr Newline)
    23453 #?     (flush Stderr)
    23454     # if (var->register == 0) return false
    23455     3d/compare-eax-and 0/imm32
    23456     0f 84/jump-if-= $register-within-list-with-conflict?:end/disp32  # eax turns into result
    23457     89/<- %ebx 0/r32/eax
    23458     # var curr/ecx: (addr list var) = start
    23459     8b/-> *(ebp+0xc) 1/r32/ecx
    23460     # edx = end
    23461     8b/-> *(ebp+0x10) 2/r32/edx
    23462     {
    23463       # if (curr == 0) break
    23464       81 7/subop/compare %edi 0/imm32
    23465       0f 84/jump-if-= break/disp32
    23466       # if (curr == end) break
    23467       39/compare %ecx 2/r32/edx
    23468       0f 84/jump-if-= break/disp32
    23469       # var curr-reg/eax: (addr array byte) = curr->value->register
    23470       (lookup *ecx *(ecx+4))  # List-value List-value => eax
    23471       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    23472       # if (curr-reg == 0) continue
    23473       3d/compare-eax-and 0/imm32
    23474       74/jump-if-= $register-within-list-with-conflict?:continue/disp8
    23475       # if (curr-reg == target) check for conflict
    23476       (string-equal? %eax %ebx)  # => eax
    23477       3d/compare-eax-and 0/imm32/false
    23478       {
    23479         74/jump-if-= break/disp8
    23480 #?         (write-buffered Stderr "conflict?\n")
    23481 #?         (flush Stderr)
    23482         # var return-inouts/eax: (addr stmt-var) = stmt->inouts
    23483         8b/-> *(ebp+0x14) 0/r32/eax
    23484         (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    23485         (register-conflict? %ebx %eax *(ebp+0xc))  # => eax
    23486         eb/jump $register-within-list-with-conflict?:end/disp8
    23487       }
    23488 $register-within-list-with-conflict?:continue:
    23489       # curr = curr->next
    23490       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
    23491       89/<- %ecx 0/r32/eax
    23492       e9/jump loop/disp32
    23493     }
    23494     # return false
    23495     b8/copy-to-eax 0/imm32/false
    23496 $register-within-list-with-conflict?:end:
    23497     # . restore registers
    23498     5f/pop-to-edi
    23499     5e/pop-to-esi
    23500     5b/pop-to-ebx
    23501     5a/pop-to-edx
    23502     59/pop-to-ecx
    23503     # . epilogue
    23504     89/<- %esp 5/r32/ebp
    23505     5d/pop-to-ebp
    23506     c3/return
    23507
    23508 # At the first occurrence of register 'reg' in fn-outputs,
    23509 # check if the corresponding element of return-inouts has a different register.
    23510 # This hacky helper is intended to be called in one specific place. Don't
    23511 # reuse it as is.
    23512 register-conflict?:  # reg: (addr array byte), return-inouts: (addr stmt-var), fn-outputs: (addr list var) => result/eax: boolean
    23513     # . prologue
    23514     55/push-ebp
    23515     89/<- %ebp 4/r32/esp
    23516     # . save registers
    23517     51/push-ecx
    23518     52/push-edx
    23519     53/push-ebx
    23520     56/push-esi
    23521     57/push-edi
    23522 #?     (write-buffered Stderr "BB: ")
    23523 #?     (write-buffered Stderr *(ebp+8))
    23524 #?     (write-buffered Stderr Newline)
    23525 #?     (flush Stderr)
    23526     # var curr-output/edi: (addr list var) = fn-outputs
    23527     8b/-> *(ebp+0x10) 7/r32/edi
    23528     # var curr-inout/esi: (addr stmt-var) = return-inouts
    23529     8b/-> *(ebp+0xc) 6/r32/esi
    23530     {
    23531       # if (curr-output == 0) abort
    23532       81 7/subop/compare %edi 0/imm32
    23533       0f 84/jump-if-= break/disp32
    23534       # if (curr-output->value->register != reg) continue
    23535       (lookup *edi *(edi+4))  # List-value List-value => eax
    23536       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    23537       (string-equal? %eax *(ebp+8))  # => eax
    23538       3d/compare-eax-and 0/imm32/false
    23539       0f 84/jump-if= $register-conflict?:continue/disp32
    23540 #?       (write-buffered Stderr "rescan\n")
    23541 #?       (flush Stderr)
    23542       # var curr-reg/eax: (addr array byte) = curr-inout->value->register
    23543       (lookup *esi *(esi+4))  # List-value List-value => eax
    23544       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    23545       # if (curr-reg == 0) return true
    23546       3d/compare-eax-and 0/imm32
    23547       {
    23548         75/jump-if-!= break/disp8
    23549 #?         (write-buffered Stderr "no register\n")
    23550 #?         (flush Stderr)
    23551         b8/copy-to-eax 1/imm32/true
    23552         e9/jump $register-conflict?:end/disp32
    23553       }
    23554       # return (curr-reg != reg)
    23555       (string-equal? %eax *(ebp+8))  # => eax
    23556       3d/compare-eax-and 0/imm32/false
    23557       0f 94/set-if-= %al
    23558 #?       (write-buffered Stderr "final: ")
    23559 #?       (write-int32-hex-buffered Stderr %eax)
    23560 #?       (write-buffered Stderr Newline)
    23561 #?       (flush Stderr)
    23562       eb/jump $register-conflict?:end/disp8
    23563 $register-conflict?:continue:
    23564       # curr-output = curr-output->next
    23565       (lookup *(edi+8) *(edi+0xc))  # List-next List-next => eax
    23566       89/<- %edi 0/r32/eax
    23567       # curr-inout = curr-inout->next
    23568       (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
    23569       89/<- %esi 0/r32/eax
    23570       e9/jump loop/disp32
    23571     }
    23572     # should never get here
    23573     (write-buffered Stderr "register-conflict? misused\n")
    23574     (flush Stderr)
    23575     e8/call syscall_exit/disp32
    23576 $register-conflict?:end:
    23577     # . restore registers
    23578     5f/pop-to-edi
    23579     5e/pop-to-esi
    23580     5b/pop-to-ebx
    23581     5a/pop-to-edx
    23582     59/pop-to-ecx
    23583     # . epilogue
    23584     89/<- %esp 5/r32/ebp
    23585     5d/pop-to-ebp
    23586     c3/return
    23587
    23588 check-final-stmt-is-return:  # block: (addr block), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    23589     # . prologue
    23590     55/push-ebp
    23591     89/<- %ebp 4/r32/esp
    23592     # . save registers
    23593     50/push-eax
    23594     51/push-ecx
    23595     # var curr/ecx: (addr list stmt) = block->stmts
    23596     8b/-> *(ebp+8) 0/r32/eax
    23597     (lookup *(eax+4) *(eax+8))  # Block-stmts Block-stmts => eax
    23598     3d/compare-eax-and 0/imm32
    23599     74/jump-if-= $check-final-stmt-is-return:error/disp8
    23600     89/<- %ecx 0/r32/eax
    23601     {
    23602       # if curr->next == 0, break
    23603       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
    23604       3d/compare-eax-and 0/imm32
    23605       74/jump-if-= break/disp8
    23606       # curr = curr->next
    23607       89/<- %ecx 0/r32/eax
    23608       e9/jump loop/disp32
    23609     }
    23610 $check-final-stmt-is-return:check-tag:
    23611     # if curr->value->tag != Stmt1, abort
    23612     (lookup *ecx *(ecx+4))  # List-value List-value => eax
    23613     81 7/subop/compare *eax 1/imm32/stmt1  # Stmt-tag
    23614     75/jump-if-!= $check-final-stmt-is-return:error/disp8
    23615 $check-final-stmt-is-return:check-operation:
    23616     # if curr->operation != "return", abort
    23617     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
    23618     (string-equal? %eax "return")
    23619     3d/compare-eax-and 0/imm32/false
    23620     74/jump-if-= $check-final-stmt-is-return:error/disp8
    23621 $check-final-stmt-is-return:end:
    23622     # . restore registers
    23623     59/pop-to-ecx
    23624     58/pop-to-eax
    23625     # . epilogue
    23626     89/<- %esp 5/r32/ebp
    23627     5d/pop-to-ebp
    23628     c3/return
    23629
    23630 $check-final-stmt-is-return:error:
    23631     (write-buffered *(ebp+0x10) "fn ")
    23632     8b/-> *(ebp+0xc) 0/r32/eax
    23633     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    23634     (write-buffered *(ebp+0x10) %eax)
    23635     (write-buffered *(ebp+0x10) ": final statement should be a 'return'\n")
    23636     (flush *(ebp+0x10))
    23637     (stop *(ebp+0x14) 1)
    23638     # never gets here
    23639
    23640 check-no-breaks:  # block: (addr block), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    23641     # . prologue
    23642     55/push-ebp
    23643     89/<- %ebp 4/r32/esp
    23644     # . save registers
    23645     50/push-eax
    23646     51/push-ecx
    23647     # var curr/ecx: (addr list stmt) = block->stmts
    23648     8b/-> *(ebp+8) 0/r32/eax
    23649     (lookup *(eax+4) *(eax+8))  # Block-stmts Block-stmts => eax
    23650     3d/compare-eax-and 0/imm32
    23651     0f 84/jump-if-= $check-no-breaks:end/disp32
    23652     89/<- %ecx 0/r32/eax
    23653     {
    23654       # if curr->next == 0, break
    23655       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
    23656       3d/compare-eax-and 0/imm32
    23657       74/jump-if-= break/disp8
    23658       # if curr->value->tag != Stmt1, continue
    23659       (lookup *ecx *(ecx+4))  # List-value List-value => eax
    23660       81 7/subop/compare *eax 1/imm32/stmt1  # Stmt-tag
    23661       75/jump-if-!= $check-no-breaks:continue/disp8
    23662       # if curr->value->operation starts with "break", abort
    23663       (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
    23664       (string-starts-with? %eax "break")  # => eax
    23665       3d/compare-eax-and 0/imm32/false
    23666       75/jump-if-!= $check-no-breaks:error/disp8
    23667 $check-no-breaks:continue:
    23668       # curr = curr->next
    23669       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
    23670       89/<- %ecx 0/r32/eax
    23671       e9/jump loop/disp32
    23672     }
    23673 $check-no-breaks:end:
    23674     # . restore registers
    23675     59/pop-to-ecx
    23676     58/pop-to-eax
    23677     # . epilogue
    23678     89/<- %esp 5/r32/ebp
    23679     5d/pop-to-ebp
    23680     c3/return
    23681
    23682 $check-no-breaks:error:
    23683     (write-buffered *(ebp+0x10) "fn ")
    23684     8b/-> *(ebp+0xc) 0/r32/eax
    23685     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    23686     (write-buffered *(ebp+0x10) %eax)
    23687     (write-buffered *(ebp+0x10) " has outputs, so you cannot 'break' out of the outermost block. Use 'return'.\n")
    23688     (flush *(ebp+0x10))
    23689     (stop *(ebp+0x14) 1)
    23690     # never gets here
    23691
    23692 check-mu-get-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    23693     # . prologue
    23694     55/push-ebp
    23695     89/<- %ebp 4/r32/esp
    23696     # . save registers
    23697     50/push-eax
    23698     51/push-ecx
    23699     52/push-edx
    23700     53/push-ebx
    23701     56/push-esi
    23702     57/push-edi
    23703     # esi = stmt
    23704     8b/-> *(ebp+8) 6/r32/esi
    23705     # - check for 0 inouts
    23706     # var base/ecx: (addr var) = stmt->inouts->value
    23707     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    23708     3d/compare-eax-and 0/imm32/false
    23709     0f 84/jump-if-= $check-mu-get-stmt:error-too-few-inouts/disp32
    23710     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    23711     89/<- %ecx 0/r32/eax
    23712 $check-mu-get-stmt:check-base:
    23713     # - check base type
    23714     # if it's an 'addr', check that it's in a register
    23715     # var base-type/ebx: (addr type-tree) = lookup(base->type)
    23716     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
    23717     89/<- %ebx 0/r32/eax
    23718     {
    23719       81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
    23720       0f 85/jump-if-!= break/disp32
    23721 $check-mu-get-stmt:base-is-compound:
    23722       # if (type->left != addr) break
    23723       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
    23724       (simple-mu-type? %eax 2)  # addr => eax
    23725       3d/compare-eax-and 0/imm32/false
    23726       74/jump-if-= break/disp8
    23727 $check-mu-get-stmt:base-is-addr:
    23728       # now check for register
    23729       81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
    23730       0f 84/jump-if-= $check-mu-get-stmt:error-base-type-addr-but-not-register/disp32
    23731 $check-mu-get-stmt:base-is-addr-in-register:
    23732       # type->left is now an addr; skip it
    23733       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
    23734       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
    23735       0f 85/jump-if-!= $check-mu-get-stmt:error-bad-base/disp32
    23736 $check-mu-get-stmt:base-is-addr-to-atom-in-register:
    23737       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    23738       89/<- %ebx 0/r32/eax
    23739     }
    23740 $check-mu-get-stmt:check-base-typeinfo:
    23741     # ensure type is a container
    23742     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
    23743     {
    23744       75/jump-if-!= break/disp8
    23745       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
    23746       89/<- %ebx 0/r32/eax
    23747     }
    23748     # var base-type-id/ebx: type-id = base-type->value
    23749     8b/-> *(ebx+4) 3/r32/ebx  # Type-tree-value
    23750     (container? %ebx)  # => eax
    23751     3d/compare-eax-and 0/imm32/false
    23752     0f 84/jump-if-= $check-mu-get-stmt:error-bad-base/disp32
    23753     # var base-typeinfo/edx: (addr typeinfo) = find-typeinfo(base-type-id)
    23754     # . var container/ecx: (handle typeinfo)
    23755     68/push 0/imm32
    23756     68/push 0/imm32
    23757     89/<- %ecx 4/r32/esp
    23758     # .
    23759     (find-typeinfo %ebx %ecx)
    23760     (lookup *ecx *(ecx+4))  # => eax
    23761     # . reclaim container
    23762     81 0/subop/add %esp 8/imm32
    23763     # .
    23764     89/<- %edx 0/r32/eax
    23765     # var offset/ecx: (addr stmt-var) = stmt->inouts->next
    23766     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    23767     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    23768     89/<- %ecx 0/r32/eax
    23769     # - check for 1 inout
    23770     3d/compare-eax-and 0/imm32/false
    23771     0f 84/jump-if-= $check-mu-get-stmt:error-too-few-inouts/disp32
    23772     # var offset/ecx: (addr var) = lookup(offset->value)
    23773     (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
    23774     89/<- %ecx 0/r32/eax
    23775     # - check for valid field
    23776     81 7/subop/compare *(ecx+0x14) -1/imm32/uninitialized  # Var-offset
    23777     0f 84/jump-if-= $check-mu-get-stmt:error-bad-field/disp32
    23778     # - check for too many inouts
    23779     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    23780     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    23781     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    23782     3d/compare-eax-and 0/imm32/false
    23783     0f 85/jump-if-!= $check-mu-get-stmt:error-too-many-inouts/disp32
    23784     # var output/edi: (addr var) = stmt->outputs->value
    23785     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    23786     # - check for 0 outputs
    23787     3d/compare-eax-and 0/imm32/false
    23788     0f 84/jump-if-= $check-mu-get-stmt:error-too-few-outputs/disp32
    23789     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    23790     89/<- %edi 0/r32/eax
    23791 $check-mu-get-stmt:check-output-type:
    23792     # - check output type
    23793     # must be in register
    23794     (lookup *(edi+0x18) *(edi+0x1c))  # Var-register Var-register => eax
    23795     3d/compare-eax-and 0/imm32
    23796     0f 84/jump-if-= $check-mu-get-stmt:error-output-not-in-register/disp32
    23797     # must have a non-atomic type
    23798     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
    23799     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
    23800     0f 85/jump-if-!= $check-mu-get-stmt:error-output-type-not-address/disp32
    23801     # type must start with (addr ...)
    23802     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    23803     (simple-mu-type? %eax 2)  # => eax
    23804     3d/compare-eax-and 0/imm32/false
    23805     0f 84/jump-if-= $check-mu-get-stmt:error-output-type-not-address/disp32
    23806 $check-mu-get-stmt:check-output-type-match:
    23807     # payload of addr type must match 'type' definition
    23808     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
    23809     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
    23810     # if (payload->right == null) payload = payload->left
    23811     81 7/subop/compare *(eax+0xc) 0/imm32/null  # Type-tree-right
    23812     {
    23813       75/jump-if-!= break/disp8
    23814       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    23815     }
    23816     89/<- %edi 0/r32/eax
    23817     # . var output-name/ecx: (addr array byte)
    23818     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    23819     89/<- %ecx 0/r32/eax
    23820     # . var base-typeinfo-entry/eax: (addr handle typeinfo-entry)
    23821     (lookup *(edx+4) *(edx+8))  # Typeinfo-fields Typeinfo-fields => eax
    23822     (get %eax %ecx 0x10)  # => eax
    23823     # .
    23824     (lookup *eax *(eax+4))  # => eax
    23825     (lookup *eax *(eax+4))  # Typeinfo-entry-input-var Typeinfo-entry-input-var => eax
    23826     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    23827     # .
    23828     (type-equal? %edi %eax)  # => eax
    23829     3d/compare-eax-and 0/imm32/false
    23830     0f 84/jump-if-= $check-mu-get-stmt:error-bad-output-type/disp32
    23831     # - check for too many outputs
    23832     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    23833     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    23834     3d/compare-eax-and 0/imm32/false
    23835     0f 85/jump-if-!= $check-mu-get-stmt:error-too-many-outputs/disp32
    23836 $check-mu-get-stmt:end:
    23837     # . restore registers
    23838     5f/pop-to-edi
    23839     5e/pop-to-esi
    23840     5b/pop-to-ebx
    23841     5a/pop-to-edx
    23842     59/pop-to-ecx
    23843     58/pop-to-eax
    23844     # . epilogue
    23845     89/<- %esp 5/r32/ebp
    23846     5d/pop-to-ebp
    23847     c3/return
    23848
    23849 $check-mu-get-stmt:error-too-few-inouts:
    23850     (write-buffered *(ebp+0x10) "fn ")
    23851     8b/-> *(ebp+0xc) 0/r32/eax
    23852     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    23853     (write-buffered *(ebp+0x10) %eax)
    23854     (write-buffered *(ebp+0x10) ": stmt get: too few inouts (2 required)\n")
    23855     (flush *(ebp+0x10))
    23856     (stop *(ebp+0x14) 1)
    23857     # never gets here
    23858
    23859 $check-mu-get-stmt:error-too-many-inouts:
    23860     (write-buffered *(ebp+0x10) "fn ")
    23861     8b/-> *(ebp+0xc) 0/r32/eax
    23862     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    23863     (write-buffered *(ebp+0x10) %eax)
    23864     (write-buffered *(ebp+0x10) ": stmt get: too many inouts (2 required)\n")
    23865     (flush *(ebp+0x10))
    23866     (stop *(ebp+0x14) 1)
    23867     # never gets here
    23868
    23869 $check-mu-get-stmt:error-too-few-outputs:
    23870     (write-buffered *(ebp+0x10) "fn ")
    23871     8b/-> *(ebp+0xc) 0/r32/eax
    23872     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    23873     (write-buffered *(ebp+0x10) %eax)
    23874     (write-buffered *(ebp+0x10) ": stmt get: must have an output\n")
    23875     (flush *(ebp+0x10))
    23876     (stop *(ebp+0x14) 1)
    23877     # never gets here
    23878
    23879 $check-mu-get-stmt:error-too-many-outputs:
    23880     (write-buffered *(ebp+0x10) "fn ")
    23881     8b/-> *(ebp+0xc) 0/r32/eax
    23882     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    23883     (write-buffered *(ebp+0x10) %eax)
    23884     (write-buffered *(ebp+0x10) ": stmt get: too many outputs (1 required)\n")
    23885     (flush *(ebp+0x10))
    23886     (stop *(ebp+0x14) 1)
    23887     # never gets here
    23888
    23889 $check-mu-get-stmt:error-bad-base:
    23890     # error("fn " fn ": stmt get: var '" base->name "' must have a 'type' definition\n")
    23891     (write-buffered *(ebp+0x10) "fn ")
    23892     8b/-> *(ebp+0xc) 0/r32/eax
    23893     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    23894     (write-buffered *(ebp+0x10) %eax)
    23895     (write-buffered *(ebp+0x10) ": stmt get: var '")
    23896     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    23897     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    23898     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    23899     (write-buffered *(ebp+0x10) %eax)
    23900     (write-buffered *(ebp+0x10) "' must have a 'type' definition\n")
    23901     (flush *(ebp+0x10))
    23902     (stop *(ebp+0x14) 1)
    23903     # never gets here
    23904
    23905 $check-mu-get-stmt:error-base-type-addr-but-not-register:
    23906     (write-buffered *(ebp+0x10) "fn ")
    23907     8b/-> *(ebp+0xc) 0/r32/eax
    23908     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    23909     (write-buffered *(ebp+0x10) %eax)
    23910     (write-buffered *(ebp+0x10) ": stmt get: var '")
    23911     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    23912     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    23913     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    23914     (write-buffered *(ebp+0x10) %eax)
    23915     (write-buffered *(ebp+0x10) "' is an 'addr' type, and so must live in a register\n")
    23916     (flush *(ebp+0x10))
    23917     (stop *(ebp+0x14) 1)
    23918     # never gets here
    23919
    23920 $check-mu-get-stmt:error-bad-field:
    23921     # error("fn " fn ": stmt get: type " type " has no member called '" curr->name "'\n")
    23922     (write-buffered *(ebp+0x10) "fn ")
    23923     8b/-> *(ebp+0xc) 0/r32/eax
    23924     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    23925     (write-buffered *(ebp+0x10) %eax)
    23926     (write-buffered *(ebp+0x10) ": stmt get: type '")
    23927     # . write(Type-id->data[tmp])
    23928     bf/copy-to-edi Type-id/imm32
    23929     8b/-> *(edi+ebx<<2+0xc) 6/r32/esi
    23930     {
    23931       81 7/subop/compare %esi 0/imm32
    23932       74/jump-if-= break/disp8
    23933       (write-buffered *(ebp+0x10) %esi)
    23934     }
    23935     # .
    23936     (write-buffered *(ebp+0x10) "' has no member called '")
    23937     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    23938     (write-buffered *(ebp+0x10) %eax)
    23939     (write-buffered *(ebp+0x10) "'\n")
    23940     (flush *(ebp+0x10))
    23941     (stop *(ebp+0x14) 1)
    23942     # never gets here
    23943
    23944 $check-mu-get-stmt:error-output-not-in-register:
    23945     (write-buffered *(ebp+0x10) "fn ")
    23946     8b/-> *(ebp+0xc) 0/r32/eax
    23947     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    23948     (write-buffered *(ebp+0x10) %eax)
    23949     (write-buffered *(ebp+0x10) ": stmt get: output '")
    23950     (lookup *edi *(edi+4))  # Var-name Var-name => eax
    23951     (write-buffered *(ebp+0x10) %eax)
    23952     (write-buffered *(ebp+0x10) "' is not in a register\n")
    23953     (flush *(ebp+0x10))
    23954     (stop *(ebp+0x14) 1)
    23955     # never gets here
    23956
    23957 $check-mu-get-stmt:error-output-type-not-address:
    23958     (write-buffered *(ebp+0x10) "fn ")
    23959     8b/-> *(ebp+0xc) 0/r32/eax
    23960     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    23961     (write-buffered *(ebp+0x10) %eax)
    23962     (write-buffered *(ebp+0x10) ": stmt get: output must be an addr\n")
    23963     (flush *(ebp+0x10))
    23964     (stop *(ebp+0x14) 1)
    23965     # never gets here
    23966
    23967 $check-mu-get-stmt:error-bad-output-type:
    23968     (write-buffered *(ebp+0x10) "fn ")
    23969     8b/-> *(ebp+0xc) 0/r32/eax
    23970     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    23971     (write-buffered *(ebp+0x10) %eax)
    23972     (write-buffered *(ebp+0x10) ": stmt get: wrong output type for member '")
    23973     (write-buffered *(ebp+0x10) %ecx)
    23974     (write-buffered *(ebp+0x10) "' of type '")
    23975     bf/copy-to-edi Type-id/imm32
    23976     8b/-> *(edi+ebx<<2+0xc) 6/r32/esi
    23977     {
    23978       81 7/subop/compare %esi 0/imm32
    23979       74/jump-if-= break/disp8
    23980       (write-buffered *(ebp+0x10) %esi)
    23981     }
    23982     (write-buffered *(ebp+0x10) "'\n")
    23983     (flush *(ebp+0x10))
    23984     (stop *(ebp+0x14) 1)
    23985     # never gets here
    23986
    23987 check-mu-index-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    23988     # . prologue
    23989     55/push-ebp
    23990     89/<- %ebp 4/r32/esp
    23991     # . save registers
    23992     50/push-eax
    23993     51/push-ecx
    23994     52/push-edx
    23995     53/push-ebx
    23996     56/push-esi
    23997     57/push-edi
    23998     # esi = stmt
    23999     8b/-> *(ebp+8) 6/r32/esi
    24000     # - check for 0 inouts
    24001     # var base/ecx: (addr var) = stmt->inouts->value
    24002     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    24003 $check-mu-index-stmt:check-no-inouts:
    24004     3d/compare-eax-and 0/imm32
    24005     0f 84/jump-if-= $check-mu-index-stmt:error-too-few-inouts/disp32
    24006     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    24007     89/<- %ecx 0/r32/eax
    24008     # - check base type is either (addr array ...) in register or (array ...) on stack
    24009     # var base-type/ebx: (addr type-tree) = lookup(base->type)
    24010     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
    24011     89/<- %ebx 0/r32/eax
    24012     # if base-type is an atom, abort with a precise error
    24013     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
    24014     {
    24015       74/jump-if-= break/disp8
    24016       (simple-mu-type? %ebx 3)  # array => eax
    24017       3d/compare-eax-and 0/imm32/false
    24018       0f 85/jump-if-!= $check-mu-index-stmt:error-base-array-atom-type/disp32
    24019       0f 84/jump-if-= $check-mu-index-stmt:error-base-non-array-type/disp32
    24020     }
    24021 $check-mu-index-stmt:base-is-compound:
    24022     # if type->left not addr or array, abort
    24023     {
    24024       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
    24025       (simple-mu-type? %eax 2)  # addr => eax
    24026       3d/compare-eax-and 0/imm32/false
    24027       75/jump-if-!= break/disp8
    24028       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
    24029       (simple-mu-type? %eax 3)  # array => eax
    24030       3d/compare-eax-and 0/imm32/false
    24031       75/jump-if-!= break/disp8
    24032       e9/jump $check-mu-index-stmt:error-base-non-array-type/disp32
    24033     }
    24034     # if (type->left == addr) ensure type->right->left == array and type->register exists
    24035     {
    24036       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
    24037       (simple-mu-type? %eax 2)  # addr => eax
    24038       3d/compare-eax-and 0/imm32/false
    24039       74/jump-if-= break/disp8
    24040 $check-mu-index-stmt:base-is-addr:
    24041       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
    24042       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    24043       (simple-mu-type? %eax 3)  # array => eax
    24044       3d/compare-eax-and 0/imm32/false
    24045       0f 84/jump-if-= $check-mu-index-stmt:error-base-non-array-type/disp32
    24046 $check-mu-index-stmt:check-base-addr-is-register:
    24047       81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
    24048       0f 84/jump-if-= $check-mu-index-stmt:error-base-address-array-type-on-stack/disp32
    24049     }
    24050     # if (type->left == array) ensure type->register doesn't exist
    24051     {
    24052       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
    24053       (simple-mu-type? %eax 3)  # array => eax
    24054       3d/compare-eax-and 0/imm32/false
    24055       74/jump-if-= break/disp8
    24056 $check-mu-index-stmt:base-is-array:
    24057       81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
    24058       0f 85/jump-if-!= $check-mu-index-stmt:error-base-array-type-in-register/disp32
    24059     }
    24060     # if (base-type->left == addr) base-type = base-type->right
    24061     {
    24062       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
    24063       (simple-mu-type? %eax 2)  # addr => eax
    24064       3d/compare-eax-and 0/imm32/false
    24065       74/jump-if-= break/disp8
    24066       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
    24067       89/<- %ebx 0/r32/eax
    24068     }
    24069     # - check for 1 inout
    24070     # var index/ecx: (addr stmt-var) = stmt->inouts->next->value
    24071     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    24072     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    24073 $check-mu-index-stmt:check-single-inout:
    24074     3d/compare-eax-and 0/imm32
    24075     0f 84/jump-if-= $check-mu-index-stmt:error-too-few-inouts/disp32
    24076     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    24077     89/<- %ecx 0/r32/eax
    24078     # - check index is either a literal or register
    24079     # var index-type/edx: (addr type-tree)
    24080     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
    24081     89/<- %edx 0/r32/eax
    24082     # if index type is an atom, it must be a literal or int
    24083     81 7/subop/compare *edx 0/imm32/false  # Type-tree-is-atom
    24084     {
    24085       74/jump-if-= break/disp8
    24086 $check-mu-index-stmt:index-type-is-atom:
    24087       (simple-mu-type? %edx 0)  # literal => eax
    24088       3d/compare-eax-and 0/imm32/false
    24089       75/jump-if-!= $check-mu-index-stmt:index-type-done/disp8
    24090       (simple-mu-type? %edx 1)  # int => eax
    24091       3d/compare-eax-and 0/imm32/false
    24092       75/jump-if-!= $check-mu-index-stmt:index-type-done/disp8
    24093       (simple-mu-type? %edx 7)  # offset => eax
    24094       3d/compare-eax-and 0/imm32/false
    24095       0f 85/jump-if-!= $check-mu-index-stmt:error-index-offset-atom-type/disp32
    24096       e9/jump $check-mu-index-stmt:error-invalid-index-type/disp32
    24097     }
    24098     # if index type is a non-atom: it must be an offset
    24099     {
    24100       75/jump-if-!= break/disp8
    24101 $check-mu-index-stmt:index-type-is-non-atom:
    24102       (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
    24103       (simple-mu-type? %eax 7)  # offset => eax
    24104       3d/compare-eax-and 0/imm32/false
    24105       0f 84/jump-if-= $check-mu-index-stmt:error-invalid-index-type/disp32
    24106     }
    24107 $check-mu-index-stmt:index-type-done:
    24108     # check index is either a literal or in a register
    24109     {
    24110       (simple-mu-type? %edx 0)  # literal => eax
    24111       3d/compare-eax-and 0/imm32/false
    24112       75/jump-if-!= break/disp8
    24113 $check-mu-index-stmt:check-index-in-register:
    24114       81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
    24115       0f 84/jump-if-= $check-mu-index-stmt:error-index-on-stack/disp32
    24116     }
    24117     # - if index is an 'int', check that element type of base has size 1, 2, 4 or 8 bytes.
    24118     {
    24119       (simple-mu-type? %edx 1)  # int => eax
    24120       3d/compare-eax-and 0/imm32/false
    24121       74/jump-if-= break/disp8
    24122 $check-mu-index-stmt:check-index-can-be-int:
    24123       (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    24124       (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    24125       (array-element-size %eax)  # => eax
    24126       3d/compare-eax-and 1/imm32
    24127       74/jump-if-= break/disp8
    24128       3d/compare-eax-and 2/imm32
    24129       74/jump-if-= break/disp8
    24130       3d/compare-eax-and 4/imm32
    24131       74/jump-if-= break/disp8
    24132       3d/compare-eax-and 8/imm32
    24133       74/jump-if-= break/disp8
    24134       e9/jump $check-mu-index-stmt:error-index-needs-offset/disp32
    24135     }
    24136     # - check for too many inouts
    24137     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    24138     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    24139     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    24140     3d/compare-eax-and 0/imm32/false
    24141     0f 85/jump-if-!= $check-mu-index-stmt:error-too-many-inouts/disp32
    24142     # - check for 0 outputs
    24143     # var output/edi: (addr var) = stmt->outputs->value
    24144     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    24145     3d/compare-eax-and 0/imm32/false
    24146     0f 84/jump-if-= $check-mu-index-stmt:error-too-few-outputs/disp32
    24147     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    24148     89/<- %edi 0/r32/eax
    24149     # - check output type
    24150     # must have a non-atomic type
    24151     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
    24152     89/<- %edx 0/r32/eax
    24153     81 7/subop/compare *edx 0/imm32/false  # Type-tree-is-atom
    24154     0f 85/jump-if-!= $check-mu-index-stmt:error-output-type-not-address/disp32
    24155     # type must start with (addr ...)
    24156     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
    24157     (simple-mu-type? %eax 2)  # addr => eax
    24158     3d/compare-eax-and 0/imm32/false
    24159     0f 84/jump-if-= $check-mu-index-stmt:error-output-type-not-address/disp32
    24160     # if tail(base-type) != tail(output-type) abort
    24161     (type-tail %ebx)  # => eax
    24162     89/<- %ebx 0/r32/eax
    24163     (type-tail %edx)  # => eax
    24164     (type-equal? %ebx %eax)  # => eax
    24165     3d/compare-eax-and 0/imm32/false
    24166     0f 84/jump-if-= $check-mu-index-stmt:error-bad-output-type/disp32
    24167     # - check for too many outputs
    24168     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    24169     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    24170     3d/compare-eax-and 0/imm32/false
    24171     0f 85/jump-if-!= $check-mu-index-stmt:error-too-many-outputs/disp32
    24172 $check-mu-index-stmt:end:
    24173     # . restore registers
    24174     5f/pop-to-edi
    24175     5e/pop-to-esi
    24176     5b/pop-to-ebx
    24177     5a/pop-to-edx
    24178     59/pop-to-ecx
    24179     58/pop-to-eax
    24180     # . epilogue
    24181     89/<- %esp 5/r32/ebp
    24182     5d/pop-to-ebp
    24183     c3/return
    24184
    24185 $check-mu-index-stmt:error-base-non-array-type:
    24186     (write-buffered *(ebp+0x10) "fn ")
    24187     8b/-> *(ebp+0xc) 0/r32/eax
    24188     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24189     (write-buffered *(ebp+0x10) %eax)
    24190     (write-buffered *(ebp+0x10) ": stmt index: var '")
    24191     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    24192     (write-buffered *(ebp+0x10) %eax)
    24193     (write-buffered *(ebp+0x10) "' is not an array\n")
    24194     (flush *(ebp+0x10))
    24195     (stop *(ebp+0x14) 1)
    24196     # never gets here
    24197
    24198 $check-mu-index-stmt:error-base-array-atom-type:
    24199     (write-buffered *(ebp+0x10) "fn ")
    24200     8b/-> *(ebp+0xc) 0/r32/eax
    24201     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24202     (write-buffered *(ebp+0x10) %eax)
    24203     (write-buffered *(ebp+0x10) ": stmt index: array '")
    24204     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    24205     (write-buffered *(ebp+0x10) %eax)
    24206     (write-buffered *(ebp+0x10) "' must specify the type of its elements\n")
    24207     (flush *(ebp+0x10))
    24208     (stop *(ebp+0x14) 1)
    24209     # never gets here
    24210
    24211 $check-mu-index-stmt:error-base-address-array-type-on-stack:
    24212     (write-buffered *(ebp+0x10) "fn ")
    24213     8b/-> *(ebp+0xc) 0/r32/eax
    24214     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24215     (write-buffered *(ebp+0x10) %eax)
    24216     (write-buffered *(ebp+0x10) ": stmt index: var '")
    24217     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    24218     (write-buffered *(ebp+0x10) %eax)
    24219     (write-buffered *(ebp+0x10) "' is an addr to an array, and so must live in a register\n")
    24220     (flush *(ebp+0x10))
    24221     (stop *(ebp+0x14) 1)
    24222     # never gets here
    24223
    24224 $check-mu-index-stmt:error-base-array-type-in-register:
    24225     (write-buffered *(ebp+0x10) "fn ")
    24226     8b/-> *(ebp+0xc) 0/r32/eax
    24227     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24228     (write-buffered *(ebp+0x10) %eax)
    24229     (write-buffered *(ebp+0x10) ": stmt index: var '")
    24230     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    24231     (write-buffered *(ebp+0x10) %eax)
    24232     (write-buffered *(ebp+0x10) "' is an array, and so must live on the stack\n")
    24233     (flush *(ebp+0x10))
    24234     (stop *(ebp+0x14) 1)
    24235     # never gets here
    24236
    24237 $check-mu-index-stmt:error-too-few-inouts:
    24238     (write-buffered *(ebp+0x10) "fn ")
    24239     8b/-> *(ebp+0xc) 0/r32/eax
    24240     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24241     (write-buffered *(ebp+0x10) %eax)
    24242     (write-buffered *(ebp+0x10) ": stmt index: too few inouts (2 required)\n")
    24243     (flush *(ebp+0x10))
    24244     (stop *(ebp+0x14) 1)
    24245     # never gets here
    24246
    24247 $check-mu-index-stmt:error-invalid-index-type:
    24248     (write-buffered *(ebp+0x10) "fn ")
    24249     8b/-> *(ebp+0xc) 0/r32/eax
    24250     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24251     (write-buffered *(ebp+0x10) %eax)
    24252     (write-buffered *(ebp+0x10) ": stmt index: second argument '")
    24253     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    24254     (write-buffered *(ebp+0x10) %eax)
    24255     (write-buffered *(ebp+0x10) "' must be an int or offset\n")
    24256     (flush *(ebp+0x10))
    24257     (stop *(ebp+0x14) 1)
    24258     # never gets here
    24259
    24260 $check-mu-index-stmt:error-index-offset-atom-type:
    24261     (write-buffered *(ebp+0x10) "fn ")
    24262     8b/-> *(ebp+0xc) 0/r32/eax
    24263     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24264     (write-buffered *(ebp+0x10) %eax)
    24265     (write-buffered *(ebp+0x10) ": stmt index: offset '")
    24266     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    24267     (write-buffered *(ebp+0x10) %eax)
    24268     (write-buffered *(ebp+0x10) "' must specify the type of array elements\n")
    24269     (flush *(ebp+0x10))
    24270     (stop *(ebp+0x14) 1)
    24271     # never gets here
    24272
    24273 $check-mu-index-stmt:error-index-on-stack:
    24274     (write-buffered *(ebp+0x10) "fn ")
    24275     8b/-> *(ebp+0xc) 0/r32/eax
    24276     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24277     (write-buffered *(ebp+0x10) %eax)
    24278     (write-buffered *(ebp+0x10) ": stmt index: second argument '")
    24279     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    24280     (write-buffered *(ebp+0x10) %eax)
    24281     (write-buffered *(ebp+0x10) "' must be in a register\n")
    24282     (flush *(ebp+0x10))
    24283     (stop *(ebp+0x14) 1)
    24284     # never gets here
    24285
    24286 $check-mu-index-stmt:error-index-needs-offset:
    24287     (write-buffered *(ebp+0x10) "fn ")
    24288     8b/-> *(ebp+0xc) 0/r32/eax
    24289     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24290     (write-buffered *(ebp+0x10) %eax)
    24291     (write-buffered *(ebp+0x10) ": stmt index: cannot take an int for array '")
    24292     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    24293     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    24294     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    24295     (write-buffered *(ebp+0x10) %eax)
    24296     (write-buffered *(ebp+0x10) "'; create an offset instead. See mu.md for details.\n")
    24297     (flush *(ebp+0x10))
    24298     (stop *(ebp+0x14) 1)
    24299     # never gets here
    24300
    24301 $check-mu-index-stmt:error-too-many-inouts:
    24302     (write-buffered *(ebp+0x10) "fn ")
    24303     8b/-> *(ebp+0xc) 0/r32/eax
    24304     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24305     (write-buffered *(ebp+0x10) %eax)
    24306     (write-buffered *(ebp+0x10) ": stmt index: too many inouts (2 required)\n")
    24307     (flush *(ebp+0x10))
    24308     (stop *(ebp+0x14) 1)
    24309     # never gets here
    24310
    24311 $check-mu-index-stmt:error-too-few-outputs:
    24312     (write-buffered *(ebp+0x10) "fn ")
    24313     8b/-> *(ebp+0xc) 0/r32/eax
    24314     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24315     (write-buffered *(ebp+0x10) %eax)
    24316     (write-buffered *(ebp+0x10) ": stmt index: must have an output\n")
    24317     (flush *(ebp+0x10))
    24318     (stop *(ebp+0x14) 1)
    24319     # never gets here
    24320
    24321 $check-mu-index-stmt:error-too-many-outputs:
    24322     (write-buffered *(ebp+0x10) "fn ")
    24323     8b/-> *(ebp+0xc) 0/r32/eax
    24324     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24325     (write-buffered *(ebp+0x10) %eax)
    24326     (write-buffered *(ebp+0x10) ": stmt index: too many outputs (1 required)\n")
    24327     (flush *(ebp+0x10))
    24328     (stop *(ebp+0x14) 1)
    24329     # never gets here
    24330
    24331 $check-mu-index-stmt:error-output-not-in-register:
    24332     (write-buffered *(ebp+0x10) "fn ")
    24333     8b/-> *(ebp+0xc) 0/r32/eax
    24334     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24335     (write-buffered *(ebp+0x10) %eax)
    24336     (write-buffered *(ebp+0x10) ": stmt index: output '")
    24337     (lookup *edi *(edi+4))  # Var-name Var-name => eax
    24338     (write-buffered *(ebp+0x10) %eax)
    24339     (write-buffered *(ebp+0x10) "' is not in a register\n")
    24340     (flush *(ebp+0x10))
    24341     (stop *(ebp+0x14) 1)
    24342     # never gets here
    24343
    24344 $check-mu-index-stmt:error-output-type-not-address:
    24345     (write-buffered *(ebp+0x10) "fn ")
    24346     8b/-> *(ebp+0xc) 0/r32/eax
    24347     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24348     (write-buffered *(ebp+0x10) %eax)
    24349     (write-buffered *(ebp+0x10) ": stmt index: output '")
    24350     (lookup *edi *(edi+4))  # Var-name Var-name => eax
    24351     (write-buffered *(ebp+0x10) %eax)
    24352     (write-buffered *(ebp+0x10) "' must be an addr\n")
    24353     (flush *(ebp+0x10))
    24354     (stop *(ebp+0x14) 1)
    24355     # never gets here
    24356
    24357 $check-mu-index-stmt:error-bad-output-type:
    24358     (write-buffered *(ebp+0x10) "fn ")
    24359     8b/-> *(ebp+0xc) 0/r32/eax
    24360     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24361     (write-buffered *(ebp+0x10) %eax)
    24362     (write-buffered *(ebp+0x10) ": stmt index: output '")
    24363     (lookup *edi *(edi+4))  # Var-name Var-name => eax
    24364     (write-buffered *(ebp+0x10) %eax)
    24365     (write-buffered *(ebp+0x10) "' does not have the right type\n")
    24366     (flush *(ebp+0x10))
    24367     (stop *(ebp+0x14) 1)
    24368     # never gets here
    24369
    24370 check-mu-length-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    24371     # . prologue
    24372     55/push-ebp
    24373     89/<- %ebp 4/r32/esp
    24374     # . save registers
    24375     50/push-eax
    24376     51/push-ecx
    24377     52/push-edx
    24378     53/push-ebx
    24379     56/push-esi
    24380     57/push-edi
    24381     # esi = stmt
    24382     8b/-> *(ebp+8) 6/r32/esi
    24383     # - check for 0 inouts
    24384     # var base/ecx: (addr var) = stmt->inouts->value
    24385     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    24386 $check-mu-length-stmt:check-no-inouts:
    24387     3d/compare-eax-and 0/imm32
    24388     0f 84/jump-if-= $check-mu-length-stmt:error-too-few-inouts/disp32
    24389     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    24390     89/<- %ecx 0/r32/eax
    24391     # - check base type is either (addr array ...) in register or (array ...) on stack
    24392     # var base-type/ebx: (addr type-tree) = lookup(base->type)
    24393     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
    24394     89/<- %ebx 0/r32/eax
    24395     # if base-type is an atom, abort with a precise error
    24396     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
    24397     {
    24398       74/jump-if-= break/disp8
    24399       (simple-mu-type? %ebx 3)  # array => eax
    24400       3d/compare-eax-and 0/imm32/false
    24401       0f 85/jump-if-!= $check-mu-length-stmt:error-base-array-atom-type/disp32
    24402       0f 84/jump-if-= $check-mu-length-stmt:error-base-non-array-type/disp32
    24403     }
    24404 $check-mu-length-stmt:base-is-compound:
    24405     # if type->left not addr or array, abort
    24406     {
    24407       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
    24408       (simple-mu-type? %eax 2)  # addr => eax
    24409       3d/compare-eax-and 0/imm32/false
    24410       75/jump-if-!= break/disp8
    24411       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
    24412       (simple-mu-type? %eax 3)  # array => eax
    24413       3d/compare-eax-and 0/imm32/false
    24414       75/jump-if-!= break/disp8
    24415       e9/jump $check-mu-length-stmt:error-base-non-array-type/disp32
    24416     }
    24417     # if (type->left == addr) ensure type->right->left == array and type->register exists
    24418     {
    24419       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
    24420       (simple-mu-type? %eax 2)  # addr => eax
    24421       3d/compare-eax-and 0/imm32/false
    24422       74/jump-if-= break/disp8
    24423 $check-mu-length-stmt:base-is-addr:
    24424       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
    24425       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    24426       (simple-mu-type? %eax 3)  # array => eax
    24427       3d/compare-eax-and 0/imm32/false
    24428       0f 84/jump-if-= $check-mu-length-stmt:error-base-non-array-type/disp32
    24429 $check-mu-length-stmt:check-base-addr-is-register:
    24430       81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
    24431       0f 84/jump-if-= $check-mu-length-stmt:error-base-address-array-type-on-stack/disp32
    24432     }
    24433     # if (type->left == array) ensure type->register doesn't exist
    24434     {
    24435       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
    24436       (simple-mu-type? %eax 3)  # array => eax
    24437       3d/compare-eax-and 0/imm32/false
    24438       74/jump-if-= break/disp8
    24439 $check-mu-length-stmt:base-is-array:
    24440       81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
    24441       0f 85/jump-if-!= $check-mu-length-stmt:error-base-array-type-in-register/disp32
    24442     }
    24443     # if (base-type->left == addr) base-type = base-type->right
    24444     {
    24445       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
    24446       (simple-mu-type? %eax 2)  # addr => eax
    24447       3d/compare-eax-and 0/imm32/false
    24448       74/jump-if-= break/disp8
    24449       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
    24450       89/<- %ebx 0/r32/eax
    24451     }
    24452     # - check for too many inouts
    24453     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    24454     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    24455     3d/compare-eax-and 0/imm32/false
    24456     0f 85/jump-if-!= $check-mu-length-stmt:error-too-many-inouts/disp32
    24457     # - check for 0 outputs
    24458     # var output/edi: (addr var) = stmt->outputs->value
    24459     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    24460     3d/compare-eax-and 0/imm32/false
    24461     0f 84/jump-if-= $check-mu-length-stmt:error-too-few-outputs/disp32
    24462     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    24463     89/<- %edi 0/r32/eax
    24464     # - check output type
    24465     # must have a non-atomic type
    24466     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
    24467     (simple-mu-type? %eax 1)  # int => eax
    24468     3d/compare-eax-and 0/imm32/false
    24469     0f 84/jump-if-= $check-mu-length-stmt:error-invalid-output-type/disp32
    24470     # - check for too many outputs
    24471     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    24472     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    24473     3d/compare-eax-and 0/imm32/false
    24474     0f 85/jump-if-!= $check-mu-length-stmt:error-too-many-outputs/disp32
    24475 $check-mu-length-stmt:end:
    24476     # . restore registers
    24477     5f/pop-to-edi
    24478     5e/pop-to-esi
    24479     5b/pop-to-ebx
    24480     5a/pop-to-edx
    24481     59/pop-to-ecx
    24482     58/pop-to-eax
    24483     # . epilogue
    24484     89/<- %esp 5/r32/ebp
    24485     5d/pop-to-ebp
    24486     c3/return
    24487
    24488 $check-mu-length-stmt:error-base-non-array-type:
    24489     (write-buffered *(ebp+0x10) "fn ")
    24490     8b/-> *(ebp+0xc) 0/r32/eax
    24491     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24492     (write-buffered *(ebp+0x10) %eax)
    24493     (write-buffered *(ebp+0x10) ": stmt length: var '")
    24494     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    24495     (write-buffered *(ebp+0x10) %eax)
    24496     (write-buffered *(ebp+0x10) "' is not an array\n")
    24497     (flush *(ebp+0x10))
    24498     (stop *(ebp+0x14) 1)
    24499     # never gets here
    24500
    24501 $check-mu-length-stmt:error-base-array-atom-type:
    24502     (write-buffered *(ebp+0x10) "fn ")
    24503     8b/-> *(ebp+0xc) 0/r32/eax
    24504     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24505     (write-buffered *(ebp+0x10) %eax)
    24506     (write-buffered *(ebp+0x10) ": stmt length: array '")
    24507     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    24508     (write-buffered *(ebp+0x10) %eax)
    24509     (write-buffered *(ebp+0x10) "' must specify the type of its elements\n")
    24510     (flush *(ebp+0x10))
    24511     (stop *(ebp+0x14) 1)
    24512     # never gets here
    24513
    24514 $check-mu-length-stmt:error-base-address-array-type-on-stack:
    24515     (write-buffered *(ebp+0x10) "fn ")
    24516     8b/-> *(ebp+0xc) 0/r32/eax
    24517     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24518     (write-buffered *(ebp+0x10) %eax)
    24519     (write-buffered *(ebp+0x10) ": stmt length: var '")
    24520     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    24521     (write-buffered *(ebp+0x10) %eax)
    24522     (write-buffered *(ebp+0x10) "' is an addr to an array, and so must live in a register\n")
    24523     (flush *(ebp+0x10))
    24524     (stop *(ebp+0x14) 1)
    24525     # never gets here
    24526
    24527 $check-mu-length-stmt:error-base-array-type-in-register:
    24528     (write-buffered *(ebp+0x10) "fn ")
    24529     8b/-> *(ebp+0xc) 0/r32/eax
    24530     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24531     (write-buffered *(ebp+0x10) %eax)
    24532     (write-buffered *(ebp+0x10) ": stmt length: var '")
    24533     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    24534     (write-buffered *(ebp+0x10) %eax)
    24535     (write-buffered *(ebp+0x10) "' is an array, and so must live on the stack\n")
    24536     (flush *(ebp+0x10))
    24537     (stop *(ebp+0x14) 1)
    24538     # never gets here
    24539
    24540 $check-mu-length-stmt:error-too-few-inouts:
    24541     (write-buffered *(ebp+0x10) "fn ")
    24542     8b/-> *(ebp+0xc) 0/r32/eax
    24543     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24544     (write-buffered *(ebp+0x10) %eax)
    24545     (write-buffered *(ebp+0x10) ": stmt length: too few inouts (1 required)\n")
    24546     (flush *(ebp+0x10))
    24547     (stop *(ebp+0x14) 1)
    24548     # never gets here
    24549
    24550 $check-mu-length-stmt:error-invalid-index-type:
    24551     (write-buffered *(ebp+0x10) "fn ")
    24552     8b/-> *(ebp+0xc) 0/r32/eax
    24553     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24554     (write-buffered *(ebp+0x10) %eax)
    24555     (write-buffered *(ebp+0x10) ": stmt length: second argument '")
    24556     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    24557     (write-buffered *(ebp+0x10) %eax)
    24558     (write-buffered *(ebp+0x10) "' must be an int or offset\n")
    24559     (flush *(ebp+0x10))
    24560     (stop *(ebp+0x14) 1)
    24561     # never gets here
    24562
    24563 $check-mu-length-stmt:error-index-offset-atom-type:
    24564     (write-buffered *(ebp+0x10) "fn ")
    24565     8b/-> *(ebp+0xc) 0/r32/eax
    24566     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24567     (write-buffered *(ebp+0x10) %eax)
    24568     (write-buffered *(ebp+0x10) ": stmt length: offset '")
    24569     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    24570     (write-buffered *(ebp+0x10) %eax)
    24571     (write-buffered *(ebp+0x10) "' must specify the type of array elements\n")
    24572     (flush *(ebp+0x10))
    24573     (stop *(ebp+0x14) 1)
    24574     # never gets here
    24575
    24576 $check-mu-length-stmt:error-index-on-stack:
    24577     (write-buffered *(ebp+0x10) "fn ")
    24578     8b/-> *(ebp+0xc) 0/r32/eax
    24579     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24580     (write-buffered *(ebp+0x10) %eax)
    24581     (write-buffered *(ebp+0x10) ": stmt length: second argument '")
    24582     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    24583     (write-buffered *(ebp+0x10) %eax)
    24584     (write-buffered *(ebp+0x10) "' must be in a register\n")
    24585     (flush *(ebp+0x10))
    24586     (stop *(ebp+0x14) 1)
    24587     # never gets here
    24588
    24589 $check-mu-length-stmt:error-index-needs-offset:
    24590     (write-buffered *(ebp+0x10) "fn ")
    24591     8b/-> *(ebp+0xc) 0/r32/eax
    24592     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24593     (write-buffered *(ebp+0x10) %eax)
    24594     (write-buffered *(ebp+0x10) ": stmt length: cannot take an int for array '")
    24595     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    24596     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    24597     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    24598     (write-buffered *(ebp+0x10) %eax)
    24599     (write-buffered *(ebp+0x10) "'; create an offset instead. See mu.md for details.\n")
    24600     (flush *(ebp+0x10))
    24601     (stop *(ebp+0x14) 1)
    24602     # never gets here
    24603
    24604 $check-mu-length-stmt:error-too-many-inouts:
    24605     (write-buffered *(ebp+0x10) "fn ")
    24606     8b/-> *(ebp+0xc) 0/r32/eax
    24607     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24608     (write-buffered *(ebp+0x10) %eax)
    24609     (write-buffered *(ebp+0x10) ": stmt length: too many inouts (1 required)\n")
    24610     (flush *(ebp+0x10))
    24611     (stop *(ebp+0x14) 1)
    24612     # never gets here
    24613
    24614 $check-mu-length-stmt:error-too-few-outputs:
    24615     (write-buffered *(ebp+0x10) "fn ")
    24616     8b/-> *(ebp+0xc) 0/r32/eax
    24617     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24618     (write-buffered *(ebp+0x10) %eax)
    24619     (write-buffered *(ebp+0x10) ": stmt length: must have an output\n")
    24620     (flush *(ebp+0x10))
    24621     (stop *(ebp+0x14) 1)
    24622     # never gets here
    24623
    24624 $check-mu-length-stmt:error-too-many-outputs:
    24625     (write-buffered *(ebp+0x10) "fn ")
    24626     8b/-> *(ebp+0xc) 0/r32/eax
    24627     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24628     (write-buffered *(ebp+0x10) %eax)
    24629     (write-buffered *(ebp+0x10) ": stmt length: too many outputs (1 required)\n")
    24630     (flush *(ebp+0x10))
    24631     (stop *(ebp+0x14) 1)
    24632     # never gets here
    24633
    24634 $check-mu-length-stmt:error-output-not-in-register:
    24635     (write-buffered *(ebp+0x10) "fn ")
    24636     8b/-> *(ebp+0xc) 0/r32/eax
    24637     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24638     (write-buffered *(ebp+0x10) %eax)
    24639     (write-buffered *(ebp+0x10) ": stmt length: output '")
    24640     (lookup *edi *(edi+4))  # Var-name Var-name => eax
    24641     (write-buffered *(ebp+0x10) %eax)
    24642     (write-buffered *(ebp+0x10) "' is not in a register\n")
    24643     (flush *(ebp+0x10))
    24644     (stop *(ebp+0x14) 1)
    24645     # never gets here
    24646
    24647 $check-mu-length-stmt:error-invalid-output-type:
    24648     (write-buffered *(ebp+0x10) "fn ")
    24649     8b/-> *(ebp+0xc) 0/r32/eax
    24650     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24651     (write-buffered *(ebp+0x10) %eax)
    24652     (write-buffered *(ebp+0x10) ": stmt length: output '")
    24653     (lookup *edi *(edi+4))  # Var-name Var-name => eax
    24654     (write-buffered *(ebp+0x10) %eax)
    24655     (write-buffered *(ebp+0x10) "' does not have the right type\n")
    24656     (flush *(ebp+0x10))
    24657     (stop *(ebp+0x14) 1)
    24658     # never gets here
    24659
    24660 check-mu-compute-offset-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    24661     # . prologue
    24662     55/push-ebp
    24663     89/<- %ebp 4/r32/esp
    24664     # . save registers
    24665     50/push-eax
    24666     51/push-ecx
    24667     52/push-edx
    24668     53/push-ebx
    24669     56/push-esi
    24670     57/push-edi
    24671     # esi = stmt
    24672     8b/-> *(ebp+8) 6/r32/esi
    24673     # - check for 0 inouts
    24674     # var base/ecx: (addr var) = stmt->inouts->value
    24675     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    24676 $check-mu-compute-offset-stmt:check-no-inouts:
    24677     3d/compare-eax-and 0/imm32
    24678     0f 84/jump-if-= $check-mu-compute-offset-stmt:error-too-few-inouts/disp32
    24679     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    24680     89/<- %ecx 0/r32/eax
    24681     # - check base type is either (addr array ...) in register or (array ...) on stack
    24682     # var base-type/ebx: (addr type-tree) = lookup(base->type)
    24683     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
    24684     89/<- %ebx 0/r32/eax
    24685     # if base-type is an atom, abort with a precise error
    24686     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
    24687     {
    24688       74/jump-if-= break/disp8
    24689       (simple-mu-type? %ebx 3)  # array => eax
    24690       3d/compare-eax-and 0/imm32/false
    24691       0f 85/jump-if-!= $check-mu-compute-offset-stmt:error-base-array-atom-type/disp32
    24692       0f 84/jump-if-= $check-mu-compute-offset-stmt:error-base-non-array-type/disp32
    24693     }
    24694 $check-mu-compute-offset-stmt:base-is-compound:
    24695     # if type->left not addr or array, abort
    24696     {
    24697       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
    24698       (simple-mu-type? %eax 2)  # addr => eax
    24699       3d/compare-eax-and 0/imm32/false
    24700       75/jump-if-!= break/disp8
    24701       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
    24702       (simple-mu-type? %eax 3)  # array => eax
    24703       3d/compare-eax-and 0/imm32/false
    24704       75/jump-if-!= break/disp8
    24705       e9/jump $check-mu-compute-offset-stmt:error-base-non-array-type/disp32
    24706     }
    24707     # if (type->left == addr) ensure type->right->left == array and type->register exists
    24708     {
    24709       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
    24710       (simple-mu-type? %eax 2)  # addr => eax
    24711       3d/compare-eax-and 0/imm32/false
    24712       74/jump-if-= break/disp8
    24713 $check-mu-compute-offset-stmt:base-is-addr:
    24714       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
    24715       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    24716       (simple-mu-type? %eax 3)  # array => eax
    24717       3d/compare-eax-and 0/imm32/false
    24718       0f 84/jump-if-= $check-mu-compute-offset-stmt:error-base-non-array-type/disp32
    24719     }
    24720     # if (base-type->left == addr) base-type = base-type->right
    24721     {
    24722       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
    24723       (simple-mu-type? %eax 2)  # addr => eax
    24724       3d/compare-eax-and 0/imm32/false
    24725       74/jump-if-= break/disp8
    24726       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
    24727       89/<- %ebx 0/r32/eax
    24728     }
    24729     # - check for 1 inout
    24730     # var index/ecx: (addr stmt-var) = stmt->inouts->next->value
    24731     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    24732     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    24733 $check-mu-compute-offset-stmt:check-single-inout:
    24734     3d/compare-eax-and 0/imm32
    24735     0f 84/jump-if-= $check-mu-compute-offset-stmt:error-too-few-inouts/disp32
    24736     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    24737     89/<- %ecx 0/r32/eax
    24738     # - check index is either a literal or register
    24739     # var index-type/edx: (addr type-tree)
    24740     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
    24741     89/<- %edx 0/r32/eax
    24742     # index type must be a literal or int
    24743     81 7/subop/compare *edx 0/imm32/false  # Type-tree-is-atom
    24744     0f 84/jump-if-= $check-mu-compute-offset-stmt:error-invalid-index-type/disp32
    24745     {
    24746 $check-mu-compute-offset-stmt:index-type-is-atom:
    24747       (simple-mu-type? %edx 0)  # literal => eax
    24748       3d/compare-eax-and 0/imm32/false
    24749       75/jump-if-!= break/disp8
    24750       (simple-mu-type? %edx 1)  # int => eax
    24751       3d/compare-eax-and 0/imm32/false
    24752       75/jump-if-!= break/disp8
    24753       e9/jump $check-mu-compute-offset-stmt:error-invalid-index-type/disp32
    24754     }
    24755     # - check for too many inouts
    24756     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    24757     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    24758     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    24759     3d/compare-eax-and 0/imm32/false
    24760     0f 85/jump-if-!= $check-mu-compute-offset-stmt:error-too-many-inouts/disp32
    24761     # - check for 0 outputs
    24762     # var output/edi: (addr var) = stmt->outputs->value
    24763     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    24764     3d/compare-eax-and 0/imm32/false
    24765     0f 84/jump-if-= $check-mu-compute-offset-stmt:error-too-few-outputs/disp32
    24766     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    24767     89/<- %edi 0/r32/eax
    24768     # - check output type
    24769     # must have a non-atomic type
    24770     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
    24771     89/<- %edx 0/r32/eax
    24772     81 7/subop/compare *edx 0/imm32/false  # Type-tree-is-atom
    24773     0f 85/jump-if-!= $check-mu-compute-offset-stmt:error-output-type-not-offset/disp32
    24774     # type must start with (offset ...)
    24775     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
    24776     (simple-mu-type? %eax 7)  # offset => eax
    24777     3d/compare-eax-and 0/imm32/false
    24778     0f 84/jump-if-= $check-mu-compute-offset-stmt:error-output-type-not-offset/disp32
    24779     # if tail(base-type) != tail(output-type) abort
    24780     (type-tail %ebx)  # => eax
    24781     89/<- %ebx 0/r32/eax
    24782     (type-tail %edx)  # => eax
    24783     (type-equal? %ebx %eax)  # => eax
    24784     3d/compare-eax-and 0/imm32/false
    24785     0f 84/jump-if-= $check-mu-compute-offset-stmt:error-bad-output-type/disp32
    24786     # - check for too many outputs
    24787     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    24788     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    24789     3d/compare-eax-and 0/imm32/false
    24790     0f 85/jump-if-!= $check-mu-compute-offset-stmt:error-too-many-outputs/disp32
    24791 $check-mu-compute-offset-stmt:end:
    24792     # . restore registers
    24793     5f/pop-to-edi
    24794     5e/pop-to-esi
    24795     5b/pop-to-ebx
    24796     5a/pop-to-edx
    24797     59/pop-to-ecx
    24798     58/pop-to-eax
    24799     # . epilogue
    24800     89/<- %esp 5/r32/ebp
    24801     5d/pop-to-ebp
    24802     c3/return
    24803
    24804 $check-mu-compute-offset-stmt:error-base-non-array-type:
    24805     (write-buffered *(ebp+0x10) "fn ")
    24806     8b/-> *(ebp+0xc) 0/r32/eax
    24807     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24808     (write-buffered *(ebp+0x10) %eax)
    24809     (write-buffered *(ebp+0x10) ": stmt compute-offset: var '")
    24810     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    24811     (write-buffered *(ebp+0x10) %eax)
    24812     (write-buffered *(ebp+0x10) "' is not an array\n")
    24813     (flush *(ebp+0x10))
    24814     (stop *(ebp+0x14) 1)
    24815     # never gets here
    24816
    24817 $check-mu-compute-offset-stmt:error-base-array-atom-type:
    24818     (write-buffered *(ebp+0x10) "fn ")
    24819     8b/-> *(ebp+0xc) 0/r32/eax
    24820     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24821     (write-buffered *(ebp+0x10) %eax)
    24822     (write-buffered *(ebp+0x10) ": stmt compute-offset: array '")
    24823     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    24824     (write-buffered *(ebp+0x10) %eax)
    24825     (write-buffered *(ebp+0x10) "' must specify the type of its elements\n")
    24826     (flush *(ebp+0x10))
    24827     (stop *(ebp+0x14) 1)
    24828     # never gets here
    24829
    24830 $check-mu-compute-offset-stmt:error-too-few-inouts:
    24831     (write-buffered *(ebp+0x10) "fn ")
    24832     8b/-> *(ebp+0xc) 0/r32/eax
    24833     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24834     (write-buffered *(ebp+0x10) %eax)
    24835     (write-buffered *(ebp+0x10) ": stmt compute-offset: too few inouts (2 required)\n")
    24836     (flush *(ebp+0x10))
    24837     (stop *(ebp+0x14) 1)
    24838     # never gets here
    24839
    24840 $check-mu-compute-offset-stmt:error-invalid-index-type:
    24841     (write-buffered *(ebp+0x10) "fn ")
    24842     8b/-> *(ebp+0xc) 0/r32/eax
    24843     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24844     (write-buffered *(ebp+0x10) %eax)
    24845     (write-buffered *(ebp+0x10) ": stmt compute-offset: second argument '")
    24846     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    24847     (write-buffered *(ebp+0x10) %eax)
    24848     (write-buffered *(ebp+0x10) "' must be an int\n")
    24849     (flush *(ebp+0x10))
    24850     (stop *(ebp+0x14) 1)
    24851     # never gets here
    24852
    24853 $check-mu-compute-offset-stmt:error-index-offset-atom-type:
    24854     (write-buffered *(ebp+0x10) "fn ")
    24855     8b/-> *(ebp+0xc) 0/r32/eax
    24856     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24857     (write-buffered *(ebp+0x10) %eax)
    24858     (write-buffered *(ebp+0x10) ": stmt compute-offset: offset '")
    24859     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    24860     (write-buffered *(ebp+0x10) %eax)
    24861     (write-buffered *(ebp+0x10) "' must specify the type of array elements\n")
    24862     (flush *(ebp+0x10))
    24863     (stop *(ebp+0x14) 1)
    24864     # never gets here
    24865
    24866 $check-mu-compute-offset-stmt:error-index-on-stack:
    24867     (write-buffered *(ebp+0x10) "fn ")
    24868     8b/-> *(ebp+0xc) 0/r32/eax
    24869     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24870     (write-buffered *(ebp+0x10) %eax)
    24871     (write-buffered *(ebp+0x10) ": stmt compute-offset: second argument '")
    24872     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    24873     (write-buffered *(ebp+0x10) %eax)
    24874     (write-buffered *(ebp+0x10) "' must be in a register\n")
    24875     (flush *(ebp+0x10))
    24876     (stop *(ebp+0x14) 1)
    24877     # never gets here
    24878
    24879 $check-mu-compute-offset-stmt:error-too-many-inouts:
    24880     (write-buffered *(ebp+0x10) "fn ")
    24881     8b/-> *(ebp+0xc) 0/r32/eax
    24882     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24883     (write-buffered *(ebp+0x10) %eax)
    24884     (write-buffered *(ebp+0x10) ": stmt compute-offset: too many inouts (2 required)\n")
    24885     (flush *(ebp+0x10))
    24886     (stop *(ebp+0x14) 1)
    24887     # never gets here
    24888
    24889 $check-mu-compute-offset-stmt:error-too-few-outputs:
    24890     (write-buffered *(ebp+0x10) "fn ")
    24891     8b/-> *(ebp+0xc) 0/r32/eax
    24892     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24893     (write-buffered *(ebp+0x10) %eax)
    24894     (write-buffered *(ebp+0x10) ": stmt compute-offset: must have an output\n")
    24895     (flush *(ebp+0x10))
    24896     (stop *(ebp+0x14) 1)
    24897     # never gets here
    24898
    24899 $check-mu-compute-offset-stmt:error-too-many-outputs:
    24900     (write-buffered *(ebp+0x10) "fn ")
    24901     8b/-> *(ebp+0xc) 0/r32/eax
    24902     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24903     (write-buffered *(ebp+0x10) %eax)
    24904     (write-buffered *(ebp+0x10) ": stmt compute-offset: too many outputs (1 required)\n")
    24905     (flush *(ebp+0x10))
    24906     (stop *(ebp+0x14) 1)
    24907     # never gets here
    24908
    24909 $check-mu-compute-offset-stmt:error-output-not-in-register:
    24910     (write-buffered *(ebp+0x10) "fn ")
    24911     8b/-> *(ebp+0xc) 0/r32/eax
    24912     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24913     (write-buffered *(ebp+0x10) %eax)
    24914     (write-buffered *(ebp+0x10) ": stmt compute-offset: output '")
    24915     (lookup *edi *(edi+4))  # Var-name Var-name => eax
    24916     (write-buffered *(ebp+0x10) %eax)
    24917     (write-buffered *(ebp+0x10) "' is not in a register\n")
    24918     (flush *(ebp+0x10))
    24919     (stop *(ebp+0x14) 1)
    24920     # never gets here
    24921
    24922 $check-mu-compute-offset-stmt:error-output-type-not-offset:
    24923     (write-buffered *(ebp+0x10) "fn ")
    24924     8b/-> *(ebp+0xc) 0/r32/eax
    24925     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24926     (write-buffered *(ebp+0x10) %eax)
    24927     (write-buffered *(ebp+0x10) ": stmt compute-offset: output '")
    24928     (lookup *edi *(edi+4))  # Var-name Var-name => eax
    24929     (write-buffered *(ebp+0x10) %eax)
    24930     (write-buffered *(ebp+0x10) "' must be an offset\n")
    24931     (flush *(ebp+0x10))
    24932     (stop *(ebp+0x14) 1)
    24933     # never gets here
    24934
    24935 $check-mu-compute-offset-stmt:error-bad-output-type:
    24936     (write-buffered *(ebp+0x10) "fn ")
    24937     8b/-> *(ebp+0xc) 0/r32/eax
    24938     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24939     (write-buffered *(ebp+0x10) %eax)
    24940     (write-buffered *(ebp+0x10) ": stmt compute-offset: output '")
    24941     (lookup *edi *(edi+4))  # Var-name Var-name => eax
    24942     (write-buffered *(ebp+0x10) %eax)
    24943     (write-buffered *(ebp+0x10) "' does not have the right type\n")
    24944     (flush *(ebp+0x10))
    24945     (stop *(ebp+0x14) 1)
    24946     # never gets here
    24947
    24948 check-mu-copy-object-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    24949     # . prologue
    24950     55/push-ebp
    24951     89/<- %ebp 4/r32/esp
    24952     # . save registers
    24953     50/push-eax
    24954     51/push-ecx
    24955     53/push-ebx
    24956     56/push-esi
    24957     57/push-edi
    24958     # esi = stmt
    24959     8b/-> *(ebp+8) 6/r32/esi
    24960 $check-mu-copy-object-stmt:check-for-output:
    24961     # if stmt->outputs abort
    24962     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    24963     3d/compare-eax-and 0/imm32
    24964     0f 85/jump-if-!= $check-mu-copy-object-stmt:error-too-many-outputs/disp32
    24965 $check-mu-copy-object-stmt:get-left:
    24966     # var dest/edi: (addr stmt-var) = stmt->inouts
    24967     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    24968     89/<- %edi 0/r32/eax
    24969     # zero inouts
    24970     3d/compare-eax-and 0/imm32
    24971     0f 84/jump-if-= $check-mu-copy-object-stmt:error-incorrect-inouts/disp32
    24972 $check-mu-copy-object-stmt:get-src:
    24973     # var src/esi: (addr stmt-var) = dest->next
    24974     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
    24975     89/<- %esi 0/r32/eax
    24976     # 1 inout
    24977     3d/compare-eax-and 0/imm32
    24978     0f 84/jump-if-= $check-mu-copy-object-stmt:error-incorrect-inouts/disp32
    24979     # > 2 inouts
    24980     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
    24981     3d/compare-eax-and 0/imm32
    24982     0f 85/jump-if-!= $check-mu-copy-object-stmt:error-incorrect-inouts/disp32
    24983 $check-mu-copy-object-stmt:types:
    24984     # var src-type/ecx: (addr type-tree) = src->value->type
    24985     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    24986     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    24987     89/<- %ecx 0/r32/eax
    24988     # if (src->is-deref?) src-type = src-type->payload
    24989     8b/-> *(esi+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 *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
    24994       # if src-type->right is null, src-type = src-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/<- %ecx 0/r32/eax
    25001     }
    25002     # if src-type is not addr, abort
    25003     (mu-addr-type? %ecx)  # => eax
    25004     3d/compare-eax-and 0/imm32/false
    25005     0f 84/jump-if-= $check-mu-copy-object-stmt:error-invalid-types/disp32
    25006     # var dest-type/ebx: (addr type-tree) = dest->value->type
    25007     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    25008     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    25009     89/<- %ebx 0/r32/eax
    25010     # if (dest->is-deref?) dest-type = dest-type->payload
    25011     8b/-> *(edi+0x10) 0/r32/eax  # Stmt-var-is-deref
    25012     3d/compare-eax-and 0/imm32/false
    25013     {
    25014       74/jump-if-= break/disp8
    25015       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
    25016       # if dest-type->right is null, dest-type = dest-type->left
    25017       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
    25018       {
    25019         75/jump-if-!= break/disp8
    25020         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    25021       }
    25022       89/<- %ebx 0/r32/eax
    25023     }
    25024     # if (dest-type != src-type) abort
    25025     (type-equal? %ecx %ebx)  # => eax
    25026     3d/compare-eax-and 0/imm32
    25027     0f 84/jump-if-= $check-mu-copy-object-stmt:error-invalid-types/disp32
    25028 $check-mu-copy-object-stmt:end:
    25029     # . restore registers
    25030     5f/pop-to-edi
    25031     5e/pop-to-esi
    25032     5b/pop-to-ebx
    25033     59/pop-to-ecx
    25034     58/pop-to-eax
    25035     # . epilogue
    25036     89/<- %esp 5/r32/ebp
    25037     5d/pop-to-ebp
    25038     c3/return
    25039
    25040 $check-mu-copy-object-stmt:error-incorrect-inouts:
    25041     (write-buffered *(ebp+0x10) "fn ")
    25042     8b/-> *(ebp+0xc) 0/r32/eax
    25043     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25044     (write-buffered *(ebp+0x10) %eax)
    25045     (write-buffered *(ebp+0x10) ": stmt 'copy-object' must have two inouts\n")
    25046     (flush *(ebp+0x10))
    25047     (stop *(ebp+0x14) 1)
    25048     # never gets here
    25049
    25050 $check-mu-copy-object-stmt:error-too-many-outputs:
    25051     (write-buffered *(ebp+0x10) "fn ")
    25052     8b/-> *(ebp+0xc) 0/r32/eax
    25053     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25054     (write-buffered *(ebp+0x10) %eax)
    25055     (write-buffered *(ebp+0x10) ": stmt 'copy-object' must not have any outputs\n")
    25056     (flush *(ebp+0x10))
    25057     (stop *(ebp+0x14) 1)
    25058     # never gets here
    25059
    25060 $check-mu-copy-object-stmt:error-invalid-types:
    25061     (write-buffered *(ebp+0x10) "fn ")
    25062     8b/-> *(ebp+0xc) 0/r32/eax
    25063     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25064     (write-buffered *(ebp+0x10) %eax)
    25065     (write-buffered *(ebp+0x10) ": stmt copy-object: two inouts with identical addr types expected\n")
    25066     (flush *(ebp+0x10))
    25067     (stop *(ebp+0x14) 1)
    25068     # never gets here
    25069
    25070 check-mu-clear-object-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    25071     # . prologue
    25072     55/push-ebp
    25073     89/<- %ebp 4/r32/esp
    25074     # . save registers
    25075     50/push-eax
    25076     51/push-ecx
    25077     53/push-ebx
    25078     56/push-esi
    25079     57/push-edi
    25080     # esi = stmt
    25081     8b/-> *(ebp+8) 6/r32/esi
    25082 $check-mu-clear-object-stmt:check-for-output:
    25083     # if stmt->outputs abort
    25084     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    25085     3d/compare-eax-and 0/imm32
    25086     0f 85/jump-if-!= $check-mu-clear-object-stmt:error-too-many-outputs/disp32
    25087 $check-mu-clear-object-stmt:get-left:
    25088     # var dest/edi: (addr stmt-var) = stmt->inouts
    25089     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    25090     89/<- %edi 0/r32/eax
    25091     # zero inouts
    25092     3d/compare-eax-and 0/imm32
    25093     0f 84/jump-if-= $check-mu-clear-object-stmt:error-incorrect-inouts/disp32
    25094 $check-mu-clear-object-stmt:get-src:
    25095     # > 1 inout
    25096     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
    25097     3d/compare-eax-and 0/imm32
    25098     0f 85/jump-if-!= $check-mu-clear-object-stmt:error-incorrect-inouts/disp32
    25099 $check-mu-clear-object-stmt:types:
    25100     # var src-type/ecx: (addr type-tree) = src->value->type
    25101     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    25102     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    25103     89/<- %ecx 0/r32/eax
    25104     # if (src->is-deref?) src-type = src-type->payload
    25105     8b/-> *(edi+0x10) 0/r32/eax  # Stmt-var-is-deref
    25106     3d/compare-eax-and 0/imm32/false
    25107     {
    25108       74/jump-if-= break/disp8
    25109       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
    25110       # if src-type->right is null, src-type = src-type->left
    25111       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
    25112       {
    25113         75/jump-if-!= break/disp8
    25114         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    25115       }
    25116       89/<- %ecx 0/r32/eax
    25117     }
    25118     # if src-type is not addr, abort
    25119     (mu-addr-type? %ecx)  # => eax
    25120     3d/compare-eax-and 0/imm32/false
    25121     0f 84/jump-if-= $check-mu-clear-object-stmt:error-invalid-type/disp32
    25122 $check-mu-clear-object-stmt:end:
    25123     # . restore registers
    25124     5f/pop-to-edi
    25125     5e/pop-to-esi
    25126     5b/pop-to-ebx
    25127     59/pop-to-ecx
    25128     58/pop-to-eax
    25129     # . epilogue
    25130     89/<- %esp 5/r32/ebp
    25131     5d/pop-to-ebp
    25132     c3/return
    25133
    25134 $check-mu-clear-object-stmt:error-incorrect-inouts:
    25135     (write-buffered *(ebp+0x10) "fn ")
    25136     8b/-> *(ebp+0xc) 0/r32/eax
    25137     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25138     (write-buffered *(ebp+0x10) %eax)
    25139     (write-buffered *(ebp+0x10) ": stmt 'clear-object' must have a single inout\n")
    25140     (flush *(ebp+0x10))
    25141     (stop *(ebp+0x14) 1)
    25142     # never gets here
    25143
    25144 $check-mu-clear-object-stmt:error-too-many-outputs:
    25145     (write-buffered *(ebp+0x10) "fn ")
    25146     8b/-> *(ebp+0xc) 0/r32/eax
    25147     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25148     (write-buffered *(ebp+0x10) %eax)
    25149     (write-buffered *(ebp+0x10) ": stmt 'clear-object' must not have any outputs\n")
    25150     (flush *(ebp+0x10))
    25151     (stop *(ebp+0x14) 1)
    25152     # never gets here
    25153
    25154 $check-mu-clear-object-stmt:error-invalid-type:
    25155     (write-buffered *(ebp+0x10) "fn ")
    25156     8b/-> *(ebp+0xc) 0/r32/eax
    25157     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25158     (write-buffered *(ebp+0x10) %eax)
    25159     (write-buffered *(ebp+0x10) ": stmt clear-object: inout must have an addr type\n")
    25160     (flush *(ebp+0x10))
    25161     (stop *(ebp+0x14) 1)
    25162     # never gets here
    25163
    25164 check-mu-allocate-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    25165     # . prologue
    25166     55/push-ebp
    25167     89/<- %ebp 4/r32/esp
    25168     # . save registers
    25169     50/push-eax
    25170     53/push-ebx
    25171     56/push-esi
    25172     57/push-edi
    25173     # esi = stmt
    25174     8b/-> *(ebp+8) 6/r32/esi
    25175 $check-mu-allocate-stmt:check-for-output:
    25176     # if stmt->outputs abort
    25177     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    25178     3d/compare-eax-and 0/imm32
    25179     0f 85/jump-if-!= $check-mu-allocate-stmt:error-too-many-outputs/disp32
    25180 $check-mu-allocate-stmt:get-target:
    25181     # var target/edi: (addr stmt-var) = stmt->inouts
    25182     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    25183     89/<- %edi 0/r32/eax
    25184     # zero inouts
    25185     3d/compare-eax-and 0/imm32
    25186     0f 84/jump-if-= $check-mu-allocate-stmt:error-incorrect-inouts/disp32
    25187     # > 1 inouts
    25188     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
    25189     3d/compare-eax-and 0/imm32
    25190     0f 85/jump-if-!= $check-mu-allocate-stmt:error-incorrect-inouts/disp32
    25191 $check-mu-allocate-stmt:check-type:
    25192     # var target-type/ebx: (addr type-tree) = target->value->type
    25193     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    25194     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    25195     89/<- %ebx 0/r32/eax
    25196     # if (target->is-deref?) target-type = target-type->payload
    25197     8b/-> *(edi+0x10) 0/r32/eax  # Stmt-var-is-deref
    25198     3d/compare-eax-and 0/imm32/false
    25199     {
    25200       74/jump-if-= break/disp8
    25201       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
    25202       # if target-type->right is null, target-type = target-type->left
    25203       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
    25204       {
    25205         75/jump-if-!= break/disp8
    25206         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    25207       }
    25208       89/<- %ebx 0/r32/eax
    25209     }
    25210     # if target-type is not addr, abort
    25211     (mu-addr-type? %ebx)  # => eax
    25212     3d/compare-eax-and 0/imm32/false
    25213     0f 84/jump-if-= $check-mu-allocate-stmt:error-invalid-type/disp32
    25214     # if target-type->right is an atom, abort
    25215     (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
    25216     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
    25217     0f 85/jump-if-!= $check-mu-allocate-stmt:error-invalid-type/disp32
    25218     # if target-type->right->left is not handle, abort
    25219     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    25220     (simple-mu-type? %eax 4)  # handle => eax
    25221     3d/compare-eax-and 0/imm32/false
    25222     0f 84/jump-if-= $check-mu-allocate-stmt:error-invalid-type/disp32
    25223 $check-mu-allocate-stmt:end:
    25224     # . restore registers
    25225     5f/pop-to-edi
    25226     5e/pop-to-esi
    25227     5b/pop-to-ebx
    25228     58/pop-to-eax
    25229     # . epilogue
    25230     89/<- %esp 5/r32/ebp
    25231     5d/pop-to-ebp
    25232     c3/return
    25233
    25234 $check-mu-allocate-stmt:error-incorrect-inouts:
    25235     (write-buffered *(ebp+0x10) "fn ")
    25236     8b/-> *(ebp+0xc) 0/r32/eax
    25237     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25238     (write-buffered *(ebp+0x10) %eax)
    25239     (write-buffered *(ebp+0x10) ": stmt 'allocate' must have a single inout\n")
    25240     (flush *(ebp+0x10))
    25241     (stop *(ebp+0x14) 1)
    25242     # never gets here
    25243
    25244 $check-mu-allocate-stmt:error-too-many-outputs:
    25245     (write-buffered *(ebp+0x10) "fn ")
    25246     8b/-> *(ebp+0xc) 0/r32/eax
    25247     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25248     (write-buffered *(ebp+0x10) %eax)
    25249     (write-buffered *(ebp+0x10) ": stmt 'allocate' must not have any outputs\n")
    25250     (flush *(ebp+0x10))
    25251     (stop *(ebp+0x14) 1)
    25252     # never gets here
    25253
    25254 $check-mu-allocate-stmt:error-invalid-type:
    25255     (write-buffered *(ebp+0x10) "fn ")
    25256     8b/-> *(ebp+0xc) 0/r32/eax
    25257     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25258     (write-buffered *(ebp+0x10) %eax)
    25259     (write-buffered *(ebp+0x10) ": stmt allocate: inout '")
    25260     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    25261     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    25262     (write-buffered *(ebp+0x10) %eax)
    25263     (write-buffered *(ebp+0x10) "' must have type (addr handle ...)\n")
    25264     (flush *(ebp+0x10))
    25265     (stop *(ebp+0x14) 1)
    25266     # never gets here
    25267
    25268 check-mu-populate-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    25269     # . prologue
    25270     55/push-ebp
    25271     89/<- %ebp 4/r32/esp
    25272     # . save registers
    25273     50/push-eax
    25274     53/push-ebx
    25275     56/push-esi
    25276     57/push-edi
    25277     # esi = stmt
    25278     8b/-> *(ebp+8) 6/r32/esi
    25279 $check-mu-populate-stmt:check-for-output:
    25280     # if stmt->outputs abort
    25281     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    25282     3d/compare-eax-and 0/imm32
    25283     0f 85/jump-if-!= $check-mu-populate-stmt:error-too-many-outputs/disp32
    25284 $check-mu-populate-stmt:get-target:
    25285     # var target/edi: (addr stmt-var) = stmt->inouts
    25286     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    25287     89/<- %edi 0/r32/eax
    25288     # zero inouts
    25289     3d/compare-eax-and 0/imm32
    25290     0f 84/jump-if-= $check-mu-populate-stmt:error-incorrect-inouts/disp32
    25291 $check-mu-populate-stmt:get-length:
    25292     # var length/esi: (addr stmt-var) = dest->next
    25293     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
    25294     89/<- %esi 0/r32/eax
    25295     # 1 inout
    25296     3d/compare-eax-and 0/imm32
    25297     0f 84/jump-if-= $check-mu-populate-stmt:error-incorrect-inouts/disp32
    25298     # > 2 inouts
    25299     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
    25300     3d/compare-eax-and 0/imm32
    25301     0f 85/jump-if-!= $check-mu-populate-stmt:error-incorrect-inouts/disp32
    25302 $check-mu-populate-stmt:check-target-type:
    25303     # var target-type/ebx: (addr type-tree) = target->value->type
    25304     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    25305     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    25306     89/<- %ebx 0/r32/eax
    25307 $check-mu-populate-stmt:check-target-type-deref:
    25308     # if (target->is-deref?) target-type = target-type->payload
    25309     8b/-> *(edi+0x10) 0/r32/eax  # Stmt-var-is-deref
    25310     3d/compare-eax-and 0/imm32/false
    25311     {
    25312       74/jump-if-= break/disp8
    25313       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
    25314       # if target-type->right is null, target-type = target-type->left
    25315       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
    25316       {
    25317         75/jump-if-!= break/disp8
    25318         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    25319       }
    25320       89/<- %ebx 0/r32/eax
    25321     }
    25322 $check-mu-populate-stmt:check-target-type-addr:
    25323     # if target-type is not addr, abort
    25324     (mu-addr-type? %ebx)  # => eax
    25325     3d/compare-eax-and 0/imm32/false
    25326     0f 84/jump-if-= $check-mu-populate-stmt:error-invalid-target-type/disp32
    25327     # if target-type->right is an atom, abort
    25328     (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
    25329     89/<- %ebx 0/r32/eax
    25330     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
    25331     0f 85/jump-if-!= $check-mu-populate-stmt:error-invalid-target-type/disp32
    25332 $check-mu-populate-stmt:check-target-type-handle:
    25333     # if target-type->right->left is not handle, abort
    25334     (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
    25335     (simple-mu-type? %eax 4)  # handle => eax
    25336     3d/compare-eax-and 0/imm32/false
    25337     0f 84/jump-if-= $check-mu-populate-stmt:error-invalid-target-type/disp32
    25338     # if target-type->right->right is an atom, abort
    25339     (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
    25340     89/<- %ebx 0/r32/eax
    25341     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
    25342     0f 85/jump-if-!= $check-mu-populate-stmt:error-invalid-target-type/disp32
    25343 $check-mu-populate-stmt:check-target-type-array:
    25344     # if target-type->right->right->left is not array, abort
    25345     (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
    25346     (simple-mu-type? %eax 3)  # array => eax
    25347     3d/compare-eax-and 0/imm32/false
    25348     0f 84/jump-if-= $check-mu-populate-stmt:error-invalid-target-type/disp32
    25349 $check-mu-populate-stmt:check-length-type:
    25350     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    25351     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    25352     89/<- %ebx 0/r32/eax
    25353     (simple-mu-type? %ebx 0)  # literal => eax
    25354     3d/compare-eax-and 0/imm32/false
    25355     75/jump-if-!= $check-mu-populate-stmt:end/disp8
    25356     (simple-mu-type? %ebx 1)  # int => eax
    25357     3d/compare-eax-and 0/imm32/false
    25358     0f 84/jump-if-= $check-mu-populate-stmt:error-invalid-length-type/disp32
    25359 $check-mu-populate-stmt:end:
    25360     # . restore registers
    25361     5f/pop-to-edi
    25362     5e/pop-to-esi
    25363     5b/pop-to-ebx
    25364     58/pop-to-eax
    25365     # . epilogue
    25366     89/<- %esp 5/r32/ebp
    25367     5d/pop-to-ebp
    25368     c3/return
    25369
    25370 $check-mu-populate-stmt:error-incorrect-inouts:
    25371     (write-buffered *(ebp+0x10) "fn ")
    25372     8b/-> *(ebp+0xc) 0/r32/eax
    25373     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25374     (write-buffered *(ebp+0x10) %eax)
    25375     (write-buffered *(ebp+0x10) ": stmt 'populate' must have two inouts\n")
    25376     (flush *(ebp+0x10))
    25377     (stop *(ebp+0x14) 1)
    25378     # never gets here
    25379
    25380 $check-mu-populate-stmt:error-too-many-outputs:
    25381     (write-buffered *(ebp+0x10) "fn ")
    25382     8b/-> *(ebp+0xc) 0/r32/eax
    25383     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25384     (write-buffered *(ebp+0x10) %eax)
    25385     (write-buffered *(ebp+0x10) ": stmt 'populate' must not have any outputs\n")
    25386     (flush *(ebp+0x10))
    25387     (stop *(ebp+0x14) 1)
    25388     # never gets here
    25389
    25390 $check-mu-populate-stmt:error-invalid-target-type:
    25391     (write-buffered *(ebp+0x10) "fn ")
    25392     8b/-> *(ebp+0xc) 0/r32/eax
    25393     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25394     (write-buffered *(ebp+0x10) %eax)
    25395     (write-buffered *(ebp+0x10) ": stmt populate: first inout '")
    25396     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    25397     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    25398     (write-buffered *(ebp+0x10) %eax)
    25399     (write-buffered *(ebp+0x10) "' must have type (addr handle array ...)\n")
    25400     (flush *(ebp+0x10))
    25401     (stop *(ebp+0x14) 1)
    25402     # never gets here
    25403
    25404 $check-mu-populate-stmt:error-invalid-length-type:
    25405     (write-buffered *(ebp+0x10) "fn ")
    25406     8b/-> *(ebp+0xc) 0/r32/eax
    25407     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25408     (write-buffered *(ebp+0x10) %eax)
    25409     (write-buffered *(ebp+0x10) ": stmt populate: second inout '")
    25410     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    25411     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    25412     (write-buffered *(ebp+0x10) %eax)
    25413     (write-buffered *(ebp+0x10) "' must be an int\n")
    25414     (flush *(ebp+0x10))
    25415     (stop *(ebp+0x14) 1)
    25416     # never gets here
    25417
    25418 check-mu-populate-stream-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    25419     # . prologue
    25420     55/push-ebp
    25421     89/<- %ebp 4/r32/esp
    25422     # . save registers
    25423     50/push-eax
    25424     53/push-ebx
    25425     56/push-esi
    25426     57/push-edi
    25427     # esi = stmt
    25428     8b/-> *(ebp+8) 6/r32/esi
    25429 $check-mu-populate-stream-stmt:check-for-output:
    25430     # if stmt->outputs abort
    25431     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    25432     3d/compare-eax-and 0/imm32
    25433     0f 85/jump-if-!= $check-mu-populate-stream-stmt:error-too-many-outputs/disp32
    25434 $check-mu-populate-stream-stmt:get-target:
    25435     # var target/edi: (addr stmt-var) = stmt->inouts
    25436     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    25437     89/<- %edi 0/r32/eax
    25438     # zero inouts
    25439     3d/compare-eax-and 0/imm32
    25440     0f 84/jump-if-= $check-mu-populate-stream-stmt:error-incorrect-inouts/disp32
    25441 $check-mu-populate-stream-stmt:get-length:
    25442     # var length/esi: (addr stmt-var) = dest->next
    25443     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
    25444     89/<- %esi 0/r32/eax
    25445     # 1 inout
    25446     3d/compare-eax-and 0/imm32
    25447     0f 84/jump-if-= $check-mu-populate-stream-stmt:error-incorrect-inouts/disp32
    25448     # > 2 inouts
    25449     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
    25450     3d/compare-eax-and 0/imm32
    25451     0f 85/jump-if-!= $check-mu-populate-stream-stmt:error-incorrect-inouts/disp32
    25452 $check-mu-populate-stream-stmt:check-target-type:
    25453     # var target-type/ebx: (addr type-tree) = target->value->type
    25454     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    25455     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    25456     89/<- %ebx 0/r32/eax
    25457 $check-mu-populate-stream-stmt:check-target-type-deref:
    25458     # if (target->is-deref?) target-type = target-type->payload
    25459     8b/-> *(edi+0x10) 0/r32/eax  # Stmt-var-is-deref
    25460     3d/compare-eax-and 0/imm32/false
    25461     {
    25462       74/jump-if-= break/disp8
    25463       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
    25464       # if target-type->right is null, target-type = target-type->left
    25465       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
    25466       {
    25467         75/jump-if-!= break/disp8
    25468         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    25469       }
    25470       89/<- %ebx 0/r32/eax
    25471     }
    25472 $check-mu-populate-stream-stmt:check-target-type-addr:
    25473     # if target-type is not addr, abort
    25474     (mu-addr-type? %ebx)  # => 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     # if target-type->right is an atom, abort
    25478     (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
    25479     89/<- %ebx 0/r32/eax
    25480     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
    25481     0f 85/jump-if-!= $check-mu-populate-stream-stmt:error-invalid-target-type/disp32
    25482 $check-mu-populate-stream-stmt:check-target-type-handle:
    25483     # if target-type->right->left is not handle, abort
    25484     (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
    25485     (simple-mu-type? %eax 4)  # handle => eax
    25486     3d/compare-eax-and 0/imm32/false
    25487     0f 84/jump-if-= $check-mu-populate-stream-stmt:error-invalid-target-type/disp32
    25488     # if target-type->right->right is an atom, abort
    25489     (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
    25490     89/<- %ebx 0/r32/eax
    25491     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
    25492     0f 85/jump-if-!= $check-mu-populate-stream-stmt:error-invalid-target-type/disp32
    25493 $check-mu-populate-stream-stmt:check-target-type-stream:
    25494     # if target-type->right->right->left is not stream, abort
    25495     (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
    25496     (simple-mu-type? %eax 0xb)  # stream => eax
    25497     3d/compare-eax-and 0/imm32/false
    25498     0f 84/jump-if-= $check-mu-populate-stream-stmt:error-invalid-target-type/disp32
    25499 $check-mu-populate-stream-stmt:check-length-type:
    25500     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    25501     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    25502     89/<- %ebx 0/r32/eax
    25503     (simple-mu-type? %ebx 0)  # literal => eax
    25504     3d/compare-eax-and 0/imm32/false
    25505     75/jump-if-!= $check-mu-populate-stream-stmt:end/disp8
    25506     (simple-mu-type? %ebx 1)  # int => eax
    25507     3d/compare-eax-and 0/imm32/false
    25508     0f 84/jump-if-= $check-mu-populate-stream-stmt:error-invalid-length-type/disp32
    25509 $check-mu-populate-stream-stmt:end:
    25510     # . restore registers
    25511     5f/pop-to-edi
    25512     5e/pop-to-esi
    25513     5b/pop-to-ebx
    25514     58/pop-to-eax
    25515     # . epilogue
    25516     89/<- %esp 5/r32/ebp
    25517     5d/pop-to-ebp
    25518     c3/return
    25519
    25520 $check-mu-populate-stream-stmt:error-incorrect-inouts:
    25521     (write-buffered *(ebp+0x10) "fn ")
    25522     8b/-> *(ebp+0xc) 0/r32/eax
    25523     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25524     (write-buffered *(ebp+0x10) %eax)
    25525     (write-buffered *(ebp+0x10) ": stmt 'populate-stream' must have two inouts\n")
    25526     (flush *(ebp+0x10))
    25527     (stop *(ebp+0x14) 1)
    25528     # never gets here
    25529
    25530 $check-mu-populate-stream-stmt:error-too-many-outputs:
    25531     (write-buffered *(ebp+0x10) "fn ")
    25532     8b/-> *(ebp+0xc) 0/r32/eax
    25533     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25534     (write-buffered *(ebp+0x10) %eax)
    25535     (write-buffered *(ebp+0x10) ": stmt 'populate-stream' must not have any outputs\n")
    25536     (flush *(ebp+0x10))
    25537     (stop *(ebp+0x14) 1)
    25538     # never gets here
    25539
    25540 $check-mu-populate-stream-stmt:error-invalid-target-type:
    25541     (write-buffered *(ebp+0x10) "fn ")
    25542     8b/-> *(ebp+0xc) 0/r32/eax
    25543     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25544     (write-buffered *(ebp+0x10) %eax)
    25545     (write-buffered *(ebp+0x10) ": stmt populate-stream: first inout '")
    25546     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    25547     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    25548     (write-buffered *(ebp+0x10) %eax)
    25549     (write-buffered *(ebp+0x10) "' must have type (addr handle stream ...)\n")
    25550     (flush *(ebp+0x10))
    25551     (stop *(ebp+0x14) 1)
    25552     # never gets here
    25553
    25554 $check-mu-populate-stream-stmt:error-invalid-length-type:
    25555     (write-buffered *(ebp+0x10) "fn ")
    25556     8b/-> *(ebp+0xc) 0/r32/eax
    25557     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25558     (write-buffered *(ebp+0x10) %eax)
    25559     (write-buffered *(ebp+0x10) ": stmt populate-stream: second inout '")
    25560     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    25561     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    25562     (write-buffered *(ebp+0x10) %eax)
    25563     (write-buffered *(ebp+0x10) "' must be an int\n")
    25564     (flush *(ebp+0x10))
    25565     (stop *(ebp+0x14) 1)
    25566     # never gets here
    25567
    25568 check-mu-read-from-stream-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    25569     # . prologue
    25570     55/push-ebp
    25571     89/<- %ebp 4/r32/esp
    25572     # . save registers
    25573     50/push-eax
    25574     51/push-ecx
    25575     52/push-edx
    25576     53/push-ebx
    25577     56/push-esi
    25578     57/push-edi
    25579     # esi = stmt
    25580     8b/-> *(ebp+8) 6/r32/esi
    25581     # - check for 0 inouts
    25582     # var base/ecx: (addr var) = stmt->inouts->value
    25583     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    25584 $check-mu-read-from-stream-stmt:check-no-inouts:
    25585     3d/compare-eax-and 0/imm32
    25586     0f 84/jump-if-= $check-mu-read-from-stream-stmt:error-too-few-inouts/disp32
    25587     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    25588     89/<- %ecx 0/r32/eax
    25589     # - check base type is (addr stream T)
    25590     # var base-type/ebx: (addr type-tree) = lookup(base->type)
    25591     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
    25592     89/<- %ebx 0/r32/eax
    25593 $check-mu-read-from-stream-stmt:check-base-is-compound:
    25594     # if base-type is an atom, abort
    25595     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
    25596     0f 85/jump-if-!= $check-mu-read-from-stream-stmt:error-invalid-base-type/disp32
    25597 $check-mu-read-from-stream-stmt:check-base-is-addr:
    25598     # if type->left not addr, abort
    25599     (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
    25600     (simple-mu-type? %eax 2)  # addr => eax
    25601     3d/compare-eax-and 0/imm32/false
    25602     0f 84/jump-if-= $check-mu-read-from-stream-stmt:error-invalid-base-type/disp32
    25603 $check-mu-read-from-stream-stmt:check-base-is-addr-to-stream:
    25604     # base-type = base-type->right
    25605     (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
    25606     89/<- %ebx 0/r32/eax
    25607     # ensure base-type->left == stream
    25608     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    25609     (simple-mu-type? %eax 0xb)  # stream => eax
    25610     3d/compare-eax-and 0/imm32/false
    25611     0f 84/jump-if-= $check-mu-read-from-stream-stmt:error-invalid-base-type/disp32
    25612     # - check target type is (addr T)
    25613     # var target/ecx: (addr stmt-var) = stmt->inouts->next->value
    25614     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    25615     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    25616 $check-mu-read-from-stream-stmt:check-single-inout:
    25617     3d/compare-eax-and 0/imm32
    25618     0f 84/jump-if-= $check-mu-read-from-stream-stmt:error-too-few-inouts/disp32
    25619     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    25620     89/<- %ecx 0/r32/eax
    25621     # var target-type/edx: (addr type-tree)
    25622     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
    25623     89/<- %edx 0/r32/eax
    25624     # if target-type is an atom, it must be a literal or int
    25625 $check-mu-read-from-stream-stmt:check-target-is-compound:
    25626     81 7/subop/compare *edx 0/imm32/false  # Type-tree-is-atom
    25627     0f 85/jump-if-!= $check-mu-read-from-stream-stmt:error-target-type-not-address/disp32
    25628 $check-mu-read-from-stream-stmt:check-target-type:
    25629     # target type must start with (addr ...)
    25630     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
    25631     (simple-mu-type? %eax 2)  # addr => eax
    25632     3d/compare-eax-and 0/imm32/false
    25633     0f 84/jump-if-= $check-mu-read-from-stream-stmt:error-target-type-not-address/disp32
    25634     # if tail(base-type) != tail(target-type) abort
    25635     (type-tail %ebx)  # => eax
    25636     89/<- %ebx 0/r32/eax
    25637     (type-tail %edx)  # => eax
    25638     (type-equal? %ebx %eax)  # => eax
    25639     3d/compare-eax-and 0/imm32/false
    25640     0f 84/jump-if-= $check-mu-read-from-stream-stmt:error-invalid-target-type/disp32
    25641 $check-mu-read-from-stream-stmt:check-too-many-inouts:
    25642     # - check for too many inouts
    25643     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    25644     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    25645     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    25646     3d/compare-eax-and 0/imm32/false
    25647     0f 85/jump-if-!= $check-mu-read-from-stream-stmt:error-too-many-inouts/disp32
    25648 $check-mu-read-from-stream-stmt:check-unexpected-output:
    25649     # - check for any output
    25650     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    25651     3d/compare-eax-and 0/imm32/false
    25652     0f 85/jump-if-!= $check-mu-read-from-stream-stmt:error-unexpected-output/disp32
    25653 $check-mu-read-from-stream-stmt:end:
    25654     # . restore registers
    25655     5f/pop-to-edi
    25656     5e/pop-to-esi
    25657     5b/pop-to-ebx
    25658     5a/pop-to-edx
    25659     59/pop-to-ecx
    25660     58/pop-to-eax
    25661     # . epilogue
    25662     89/<- %esp 5/r32/ebp
    25663     5d/pop-to-ebp
    25664     c3/return
    25665
    25666 $check-mu-read-from-stream-stmt:error-invalid-base-type:
    25667     (write-buffered *(ebp+0x10) "fn ")
    25668     8b/-> *(ebp+0xc) 0/r32/eax
    25669     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25670     (write-buffered *(ebp+0x10) %eax)
    25671     (write-buffered *(ebp+0x10) ": stmt read-from-stream: var '")
    25672     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    25673     (write-buffered *(ebp+0x10) %eax)
    25674     (write-buffered *(ebp+0x10) "' must be an addr to a stream\n")
    25675     (flush *(ebp+0x10))
    25676     (stop *(ebp+0x14) 1)
    25677     # never gets here
    25678
    25679 $check-mu-read-from-stream-stmt:error-too-few-inouts:
    25680     (write-buffered *(ebp+0x10) "fn ")
    25681     8b/-> *(ebp+0xc) 0/r32/eax
    25682     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25683     (write-buffered *(ebp+0x10) %eax)
    25684     (write-buffered *(ebp+0x10) ": stmt read-from-stream: too few inouts (2 required)\n")
    25685     (flush *(ebp+0x10))
    25686     (stop *(ebp+0x14) 1)
    25687     # never gets here
    25688
    25689 $check-mu-read-from-stream-stmt:error-target-type-not-address:
    25690     (write-buffered *(ebp+0x10) "fn ")
    25691     8b/-> *(ebp+0xc) 0/r32/eax
    25692     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25693     (write-buffered *(ebp+0x10) %eax)
    25694     (write-buffered *(ebp+0x10) ": stmt read-from-stream: target '")
    25695     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    25696     (write-buffered *(ebp+0x10) %eax)
    25697     (write-buffered *(ebp+0x10) "' must be an addr\n")
    25698     (flush *(ebp+0x10))
    25699     (stop *(ebp+0x14) 1)
    25700     # never gets here
    25701
    25702 $check-mu-read-from-stream-stmt:error-invalid-target-type:
    25703     (write-buffered *(ebp+0x10) "fn ")
    25704     8b/-> *(ebp+0xc) 0/r32/eax
    25705     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25706     (write-buffered *(ebp+0x10) %eax)
    25707     (write-buffered *(ebp+0x10) ": stmt read-from-stream: second inout '")
    25708     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    25709     (write-buffered *(ebp+0x10) %eax)
    25710     (write-buffered *(ebp+0x10) "' does not have the right type\n")
    25711     (flush *(ebp+0x10))
    25712     (stop *(ebp+0x14) 1)
    25713     # never gets here
    25714
    25715 $check-mu-read-from-stream-stmt:error-too-many-inouts:
    25716     (write-buffered *(ebp+0x10) "fn ")
    25717     8b/-> *(ebp+0xc) 0/r32/eax
    25718     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25719     (write-buffered *(ebp+0x10) %eax)
    25720     (write-buffered *(ebp+0x10) ": stmt read-from-stream: too many inouts (2 required)\n")
    25721     (flush *(ebp+0x10))
    25722     (stop *(ebp+0x14) 1)
    25723     # never gets here
    25724
    25725 $check-mu-read-from-stream-stmt:error-unexpected-output:
    25726     (write-buffered *(ebp+0x10) "fn ")
    25727     8b/-> *(ebp+0xc) 0/r32/eax
    25728     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25729     (write-buffered *(ebp+0x10) %eax)
    25730     (write-buffered *(ebp+0x10) ": stmt read-from-stream: unexpected output\n")
    25731     (flush *(ebp+0x10))
    25732     (stop *(ebp+0x14) 1)
    25733     # never gets here
    25734
    25735 check-mu-write-to-stream-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    25736     # . prologue
    25737     55/push-ebp
    25738     89/<- %ebp 4/r32/esp
    25739     # . save registers
    25740     50/push-eax
    25741     51/push-ecx
    25742     52/push-edx
    25743     53/push-ebx
    25744     56/push-esi
    25745     57/push-edi
    25746     # esi = stmt
    25747     8b/-> *(ebp+8) 6/r32/esi
    25748     # - check for 0 inouts
    25749     # var base/ecx: (addr var) = stmt->inouts->value
    25750     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    25751 $check-mu-write-to-stream-stmt:check-no-inouts:
    25752     3d/compare-eax-and 0/imm32
    25753     0f 84/jump-if-= $check-mu-write-to-stream-stmt:error-too-few-inouts/disp32
    25754     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    25755     89/<- %ecx 0/r32/eax
    25756     # - check base type is (addr stream T)
    25757     # var base-type/ebx: (addr type-tree) = lookup(base->type)
    25758     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
    25759     89/<- %ebx 0/r32/eax
    25760 $check-mu-write-to-stream-stmt:check-base-is-compound:
    25761     # if base-type is an atom, abort
    25762     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
    25763     0f 85/jump-if-!= $check-mu-write-to-stream-stmt:error-invalid-base-type/disp32
    25764 $check-mu-write-to-stream-stmt:check-base-is-addr:
    25765     # if type->left not addr, abort
    25766     (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
    25767     (simple-mu-type? %eax 2)  # addr => eax
    25768     3d/compare-eax-and 0/imm32/false
    25769     0f 84/jump-if-= $check-mu-write-to-stream-stmt:error-invalid-base-type/disp32
    25770 $check-mu-write-to-stream-stmt:check-base-is-addr-to-stream:
    25771     # base-type = base-type->right
    25772     (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
    25773     89/<- %ebx 0/r32/eax
    25774     # ensure base-type->left == stream
    25775     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    25776     (simple-mu-type? %eax 0xb)  # stream => eax
    25777     3d/compare-eax-and 0/imm32/false
    25778     0f 84/jump-if-= $check-mu-write-to-stream-stmt:error-invalid-base-type/disp32
    25779     # - check target type is (addr T)
    25780     # var target/ecx: (addr stmt-var) = stmt->inouts->next->value
    25781     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    25782     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    25783 $check-mu-write-to-stream-stmt:check-single-inout:
    25784     3d/compare-eax-and 0/imm32
    25785     0f 84/jump-if-= $check-mu-write-to-stream-stmt:error-too-few-inouts/disp32
    25786     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    25787     89/<- %ecx 0/r32/eax
    25788     # var target-type/edx: (addr type-tree)
    25789     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
    25790     89/<- %edx 0/r32/eax
    25791     # if target-type is an atom, it must be a literal or int
    25792 $check-mu-write-to-stream-stmt:check-target-is-compound:
    25793     81 7/subop/compare *edx 0/imm32/false  # Type-tree-is-atom
    25794     0f 85/jump-if-!= $check-mu-write-to-stream-stmt:error-target-type-not-address/disp32
    25795 $check-mu-write-to-stream-stmt:check-target-type:
    25796     # target type must start with (addr ...)
    25797     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
    25798     (simple-mu-type? %eax 2)  # addr => eax
    25799     3d/compare-eax-and 0/imm32/false
    25800     0f 84/jump-if-= $check-mu-write-to-stream-stmt:error-target-type-not-address/disp32
    25801     # if tail(base-type) != tail(target-type) abort
    25802     (type-tail %ebx)  # => eax
    25803     89/<- %ebx 0/r32/eax
    25804     (type-tail %edx)  # => eax
    25805     (type-equal? %ebx %eax)  # => eax
    25806     3d/compare-eax-and 0/imm32/false
    25807     0f 84/jump-if-= $check-mu-write-to-stream-stmt:error-invalid-target-type/disp32
    25808 $check-mu-write-to-stream-stmt:check-too-many-inouts:
    25809     # - check for too many inouts
    25810     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    25811     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    25812     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    25813     3d/compare-eax-and 0/imm32/false
    25814     0f 85/jump-if-!= $check-mu-write-to-stream-stmt:error-too-many-inouts/disp32
    25815 $check-mu-write-to-stream-stmt:check-unexpected-output:
    25816     # - check for any output
    25817     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    25818     3d/compare-eax-and 0/imm32/false
    25819     0f 85/jump-if-!= $check-mu-write-to-stream-stmt:error-unexpected-output/disp32
    25820 $check-mu-write-to-stream-stmt:end:
    25821     # . restore registers
    25822     5f/pop-to-edi
    25823     5e/pop-to-esi
    25824     5b/pop-to-ebx
    25825     5a/pop-to-edx
    25826     59/pop-to-ecx
    25827     58/pop-to-eax
    25828     # . epilogue
    25829     89/<- %esp 5/r32/ebp
    25830     5d/pop-to-ebp
    25831     c3/return
    25832
    25833 $check-mu-write-to-stream-stmt:error-invalid-base-type:
    25834     (write-buffered *(ebp+0x10) "fn ")
    25835     8b/-> *(ebp+0xc) 0/r32/eax
    25836     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25837     (write-buffered *(ebp+0x10) %eax)
    25838     (write-buffered *(ebp+0x10) ": stmt write-to-stream: var '")
    25839     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    25840     (write-buffered *(ebp+0x10) %eax)
    25841     (write-buffered *(ebp+0x10) "' must be an addr to a stream\n")
    25842     (flush *(ebp+0x10))
    25843     (stop *(ebp+0x14) 1)
    25844     # never gets here
    25845
    25846 $check-mu-write-to-stream-stmt:error-too-few-inouts:
    25847     (write-buffered *(ebp+0x10) "fn ")
    25848     8b/-> *(ebp+0xc) 0/r32/eax
    25849     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25850     (write-buffered *(ebp+0x10) %eax)
    25851     (write-buffered *(ebp+0x10) ": stmt write-to-stream: too few inouts (2 required)\n")
    25852     (flush *(ebp+0x10))
    25853     (stop *(ebp+0x14) 1)
    25854     # never gets here
    25855
    25856 $check-mu-write-to-stream-stmt:error-target-type-not-address:
    25857     (write-buffered *(ebp+0x10) "fn ")
    25858     8b/-> *(ebp+0xc) 0/r32/eax
    25859     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25860     (write-buffered *(ebp+0x10) %eax)
    25861     (write-buffered *(ebp+0x10) ": stmt write-to-stream: target '")
    25862     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    25863     (write-buffered *(ebp+0x10) %eax)
    25864     (write-buffered *(ebp+0x10) "' must be an addr\n")
    25865     (flush *(ebp+0x10))
    25866     (stop *(ebp+0x14) 1)
    25867     # never gets here
    25868
    25869 $check-mu-write-to-stream-stmt:error-invalid-target-type:
    25870     (write-buffered *(ebp+0x10) "fn ")
    25871     8b/-> *(ebp+0xc) 0/r32/eax
    25872     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25873     (write-buffered *(ebp+0x10) %eax)
    25874     (write-buffered *(ebp+0x10) ": stmt write-to-stream: second inout '")
    25875     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    25876     (write-buffered *(ebp+0x10) %eax)
    25877     (write-buffered *(ebp+0x10) "' does not have the right type\n")
    25878     (flush *(ebp+0x10))
    25879     (stop *(ebp+0x14) 1)
    25880     # never gets here
    25881
    25882 $check-mu-write-to-stream-stmt:error-too-many-inouts:
    25883     (write-buffered *(ebp+0x10) "fn ")
    25884     8b/-> *(ebp+0xc) 0/r32/eax
    25885     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25886     (write-buffered *(ebp+0x10) %eax)
    25887     (write-buffered *(ebp+0x10) ": stmt write-to-stream: too many inouts (2 required)\n")
    25888     (flush *(ebp+0x10))
    25889     (stop *(ebp+0x14) 1)
    25890     # never gets here
    25891
    25892 $check-mu-write-to-stream-stmt:error-unexpected-output:
    25893     (write-buffered *(ebp+0x10) "fn ")
    25894     8b/-> *(ebp+0xc) 0/r32/eax
    25895     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25896     (write-buffered *(ebp+0x10) %eax)
    25897     (write-buffered *(ebp+0x10) ": stmt write-to-stream: unexpected output\n")
    25898     (flush *(ebp+0x10))
    25899     (stop *(ebp+0x14) 1)
    25900     # never gets here
    25901
    25902 check-mu-convert-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    25903     # . prologue
    25904     55/push-ebp
    25905     89/<- %ebp 4/r32/esp
    25906     # . save registers
    25907     50/push-eax
    25908     51/push-ecx
    25909     52/push-edx
    25910     56/push-esi
    25911     57/push-edi
    25912 $check-mu-convert-stmt:get-output:
    25913     # esi = stmt
    25914     8b/-> *(ebp+8) 6/r32/esi
    25915     # var output/edi: (addr stmt-var) = stmt->outputs
    25916     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    25917     89/<- %edi 0/r32/eax
    25918     # zero outputs
    25919     3d/compare-eax-and 0/imm32
    25920     0f 84/jump-if-= $check-mu-convert-stmt:error-no-output/disp32
    25921     # > 1 output
    25922     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
    25923     3d/compare-eax-and 0/imm32
    25924     0f 85/jump-if-!= $check-mu-convert-stmt:error-too-many-outputs/disp32
    25925 $check-mu-convert-stmt:get-inout:
    25926     # var inout/esi: (addr stmt-var) = stmt->inouts
    25927     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    25928     89/<- %esi 0/r32/eax
    25929     # zero inouts
    25930     3d/compare-eax-and 0/imm32
    25931     0f 84/jump-if-= $check-mu-convert-stmt:error-no-inout/disp32
    25932     # > 1 inout
    25933     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
    25934     3d/compare-eax-and 0/imm32
    25935     0f 85/jump-if-!= $check-mu-convert-stmt:error-too-many-inouts/disp32
    25936 $check-mu-convert-stmt:types:
    25937     # var inout-type/ecx: (addr type-tree) = inout->value->type
    25938     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    25939     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    25940     89/<- %ecx 0/r32/eax
    25941     # if (inout->is-deref?) inout-type = inout-type->payload
    25942     8b/-> *(esi+0x10) 0/r32/eax  # Stmt-var-is-deref
    25943     3d/compare-eax-and 0/imm32/false
    25944     {
    25945       74/jump-if-= break/disp8
    25946       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
    25947       # if inout-type->right is null, t = inout-type->left
    25948       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
    25949       {
    25950         75/jump-if-!= break/disp8
    25951         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    25952       }
    25953       89/<- %ecx 0/r32/eax
    25954     }
    25955     # if input is not int or float, abort
    25956     {
    25957       (simple-mu-type? %ecx 1)  # int => eax
    25958       3d/compare-eax-and 0/imm32/false
    25959       75/jump-if-!= break/disp8
    25960       (simple-mu-type? %ecx 0xf)  # float => eax
    25961       3d/compare-eax-and 0/imm32/false
    25962       75/jump-if-!= break/disp8
    25963       e9/jump $check-mu-convert-stmt:error-invalid-inout-type/disp32
    25964     }
    25965     # if output not in register, abort
    25966     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    25967     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    25968     3d/compare-eax-and 0/imm32
    25969     0f 84/jump-if-= $check-mu-convert-stmt:error-output-not-in-register/disp32
    25970     # var output-type/edx: (addr type-tree) = output->value->type
    25971     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    25972     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    25973     89/<- %edx 0/r32/eax
    25974     # if output is not int or float, abort
    25975     {
    25976       (simple-mu-type? %edx 1)  # int => eax
    25977       3d/compare-eax-and 0/imm32/false
    25978       75/jump-if-!= break/disp8
    25979       (simple-mu-type? %edx 0xf)  # float => eax
    25980       3d/compare-eax-and 0/imm32/false
    25981       75/jump-if-!= break/disp8
    25982       e9/jump $check-mu-convert-stmt:error-invalid-output-type/disp32
    25983     }
    25984     # if both are ints, abort
    25985     {
    25986       (simple-mu-type? %edx 1)  # int => eax
    25987       3d/compare-eax-and 0/imm32/false
    25988       74/jump-if-= break/disp8
    25989       (simple-mu-type? %ecx 1)  # int => eax
    25990       3d/compare-eax-and 0/imm32/false
    25991       74/jump-if-= break/disp8
    25992       e9/jump $check-mu-convert-stmt:error-int-to-int/disp32
    25993     }
    25994     # if both are floats, abort
    25995     {
    25996       (simple-mu-type? %edx 0xf)  # float => eax
    25997       3d/compare-eax-and 0/imm32/false
    25998       74/jump-if-= break/disp8
    25999       (simple-mu-type? %ecx 0xf)  # float => eax
    26000       3d/compare-eax-and 0/imm32/false
    26001       74/jump-if-= break/disp8
    26002       e9/jump $check-mu-convert-stmt:error-float-to-float/disp32
    26003     }
    26004 $check-mu-convert-stmt:end:
    26005     # . restore registers
    26006     5f/pop-to-edi
    26007     5e/pop-to-esi
    26008     5a/pop-to-edx
    26009     59/pop-to-ecx
    26010     58/pop-to-eax
    26011     # . epilogue
    26012     89/<- %esp 5/r32/ebp
    26013     5d/pop-to-ebp
    26014     c3/return
    26015
    26016 $check-mu-convert-stmt:error-no-inout:
    26017     (write-buffered *(ebp+0x10) "fn ")
    26018     8b/-> *(ebp+0xc) 0/r32/eax
    26019     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    26020     (write-buffered *(ebp+0x10) %eax)
    26021     (write-buffered *(ebp+0x10) ": stmt 'convert' expects an inout\n")
    26022     (flush *(ebp+0x10))
    26023     (stop *(ebp+0x14) 1)
    26024     # never gets here
    26025
    26026 $check-mu-convert-stmt:error-too-many-inouts:
    26027     (write-buffered *(ebp+0x10) "fn ")
    26028     8b/-> *(ebp+0xc) 0/r32/eax
    26029     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    26030     (write-buffered *(ebp+0x10) %eax)
    26031     (write-buffered *(ebp+0x10) ": stmt 'convert' must have just one inout\n")
    26032     (flush *(ebp+0x10))
    26033     (stop *(ebp+0x14) 1)
    26034     # never gets here
    26035
    26036 $check-mu-convert-stmt:error-no-output:
    26037     (write-buffered *(ebp+0x10) "fn ")
    26038     8b/-> *(ebp+0xc) 0/r32/eax
    26039     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    26040     (write-buffered *(ebp+0x10) %eax)
    26041     (write-buffered *(ebp+0x10) ": stmt 'convert' expects an output\n")
    26042     (flush *(ebp+0x10))
    26043     (stop *(ebp+0x14) 1)
    26044     # never gets here
    26045
    26046 $check-mu-convert-stmt:error-output-not-in-register:
    26047     (write-buffered *(ebp+0x10) "fn ")
    26048     8b/-> *(ebp+0xc) 0/r32/eax
    26049     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    26050     (write-buffered *(ebp+0x10) %eax)
    26051     (write-buffered *(ebp+0x10) ": stmt convert: output '")
    26052     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    26053     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    26054     (write-buffered *(ebp+0x10) %eax)
    26055     (write-buffered *(ebp+0x10) "' not in a register\n")
    26056     (flush *(ebp+0x10))
    26057     (stop *(ebp+0x14) 1)
    26058     # never gets here
    26059
    26060 $check-mu-convert-stmt:error-too-many-outputs:
    26061     (write-buffered *(ebp+0x10) "fn ")
    26062     8b/-> *(ebp+0xc) 0/r32/eax
    26063     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    26064     (write-buffered *(ebp+0x10) %eax)
    26065     (write-buffered *(ebp+0x10) ": stmt 'convert' must have just one output\n")
    26066     (flush *(ebp+0x10))
    26067     (stop *(ebp+0x14) 1)
    26068     # never gets here
    26069
    26070 $check-mu-convert-stmt:error-invalid-inout-type:
    26071     (write-buffered *(ebp+0x10) "fn ")
    26072     8b/-> *(ebp+0xc) 0/r32/eax
    26073     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    26074     (write-buffered *(ebp+0x10) %eax)
    26075     (write-buffered *(ebp+0x10) ": stmt convert: inout '")
    26076     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    26077     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    26078     (write-buffered *(ebp+0x10) %eax)
    26079     (write-buffered *(ebp+0x10) "' must be an int or float\n")
    26080     (flush *(ebp+0x10))
    26081     (stop *(ebp+0x14) 1)
    26082     # never gets here
    26083
    26084 $check-mu-convert-stmt:error-invalid-output-type:
    26085     (write-buffered *(ebp+0x10) "fn ")
    26086     8b/-> *(ebp+0xc) 0/r32/eax
    26087     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    26088     (write-buffered *(ebp+0x10) %eax)
    26089     (write-buffered *(ebp+0x10) ": stmt convert: output '")
    26090     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    26091     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    26092     (write-buffered *(ebp+0x10) %eax)
    26093     (write-buffered *(ebp+0x10) "' must be an int or float\n")
    26094     (flush *(ebp+0x10))
    26095     (stop *(ebp+0x14) 1)
    26096     # never gets here
    26097
    26098 $check-mu-convert-stmt:error-int-to-int:
    26099     (write-buffered *(ebp+0x10) "fn ")
    26100     8b/-> *(ebp+0xc) 0/r32/eax
    26101     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    26102     (write-buffered *(ebp+0x10) %eax)
    26103     (write-buffered *(ebp+0x10) ": stmt convert: no need to convert int to int\n")
    26104     (flush *(ebp+0x10))
    26105     (stop *(ebp+0x14) 1)
    26106     # never gets here
    26107
    26108 $check-mu-convert-stmt:error-float-to-float:
    26109     (write-buffered *(ebp+0x10) "fn ")
    26110     8b/-> *(ebp+0xc) 0/r32/eax
    26111     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    26112     (write-buffered *(ebp+0x10) %eax)
    26113     (write-buffered *(ebp+0x10) ": stmt convert: no need to convert float to float\n")
    26114     (flush *(ebp+0x10))
    26115     (stop *(ebp+0x14) 1)
    26116     # never gets here
    26117
    26118 check-mu-call:  # stmt: (addr stmt), callee: (addr function), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    26119     # . prologue
    26120     55/push-ebp
    26121     89/<- %ebp 4/r32/esp
    26122     # var type-parameters: (addr table (handle array byte) (addr type-tree) 8)
    26123     68/push 0/imm32
    26124     # var type-parameters-storage: (table (handle array byte) (addr type-tree) 8)
    26125     81 5/subop/subtract %esp 0x60/imm32
    26126     68/push 0x60/imm32/size
    26127     68/push 0/imm32/read
    26128     68/push 0/imm32/write
    26129     # save a pointer to type-parameters-storage at type-parameters
    26130     89/<- *(ebp-4) 4/r32/esp
    26131     (clear-stream *(ebp-4))
    26132     # . save registers
    26133     50/push-eax
    26134     51/push-ecx
    26135     52/push-edx
    26136     53/push-ebx
    26137     56/push-esi
    26138     57/push-edi
    26139     # esi = stmt
    26140     8b/-> *(ebp+8) 6/r32/esi
    26141     # edi = callee
    26142     8b/-> *(ebp+0xc) 7/r32/edi
    26143     # var inouts/ecx: (addr stmt-var) = lookup(stmt->inouts)
    26144     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    26145     89/<- %ecx 0/r32/eax
    26146     # var expected/edx: (addr list var) = lookup(f->inouts)
    26147     (lookup *(edi+8) *(edi+0xc))  # Function-inouts Function-inouts => eax
    26148     89/<- %edx 0/r32/eax
    26149     {
    26150 $check-mu-call:check-for-inouts:
    26151       # if (inouts == 0) break
    26152       81 7/subop/compare %ecx 0/imm32
    26153       0f 84/jump-if-= break/disp32
    26154       # if (expected == 0) error
    26155       81 7/subop/compare %edx 0/imm32
    26156       0f 84/jump-if-= break/disp32
    26157 $check-mu-call:check-null-addr:
    26158       # if (inouts->value->name == "0") continue
    26159       (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
    26160       (lookup *eax *(eax+4))  # Var-name Var-name => eax
    26161       (string-equal? %eax "0")  # => eax
    26162       3d/compare-eax-and 0/imm32/false
    26163       0f 85/jump-if-!= $check-mu-call:continue-to-next-inout/disp32
    26164 $check-mu-call:check-inout-type:
    26165       # var t/ebx: (addr type-tree) = inouts->value->type
    26166       (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
    26167       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    26168       89/<- %ebx 0/r32/eax
    26169       # if (inouts->is-deref?) t = t->right
    26170       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
    26171       {
    26172         74/jump-if-= break/disp8
    26173         (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
    26174         89/<- %ebx 0/r32/eax
    26175         # if t->right is null, t = t->left
    26176         81 7/subop/compare *(ebx+0xc) 0/imm32  # Type-tree-right
    26177         75/jump-if-!= break/disp8
    26178         (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
    26179         89/<- %ebx 0/r32/eax
    26180       }
    26181       # var v2/eax: (addr v) = lookup(expected->value)
    26182       (lookup *edx *(edx+4))  # List-value List-value => eax
    26183       # var t2/eax: (addr type-tree) = lookup(v2->type)
    26184       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    26185       # if (t != t2) error
    26186       (type-match? %eax %ebx *(ebp-4))  # => eax
    26187       3d/compare-eax-and 0/imm32/false
    26188       {
    26189         0f 85/jump-if-!= break/disp32
    26190         (write-buffered *(ebp+0x14) "fn ")
    26191         8b/-> *(ebp+0x10) 0/r32/eax
    26192         (lookup *eax *(eax+4))  # Function-name Function-name => eax
    26193         (write-buffered *(ebp+0x14) %eax)
    26194         (write-buffered *(ebp+0x14) ": call ")
    26195         (lookup *edi *(edi+4))  # Function-name Function-name => eax
    26196         (write-buffered *(ebp+0x14) %eax)
    26197         (write-buffered *(ebp+0x14) ": type for inout '")
    26198         (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
    26199         (lookup *eax *(eax+4))  # Var-name Var-name => eax
    26200         (write-buffered *(ebp+0x14) %eax)
    26201         (write-buffered *(ebp+0x14) "' is not right\n")
    26202         (flush *(ebp+0x14))
    26203         (stop *(ebp+0x18) 1)
    26204       }
    26205 $check-mu-call:continue-to-next-inout:
    26206       # inouts = lookup(inouts->next)
    26207       (lookup *(ecx+8) *(ecx+0xc))  # Stmt-var-next Stmt-var-next => eax
    26208       89/<- %ecx 0/r32/eax
    26209       # expected = lookup(expected->next)
    26210       (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
    26211       89/<- %edx 0/r32/eax
    26212       #
    26213       e9/jump loop/disp32
    26214     }
    26215 $check-mu-call:check-inout-count:
    26216     # if (inouts == expected) proceed
    26217     39/compare %ecx 2/r32/edx
    26218     {
    26219       0f 84/jump-if-= break/disp32
    26220       # exactly one of the two is null
    26221       # if (inouts == 0) error("too many inouts")
    26222       {
    26223         81 7/subop/compare %ecx 0/imm32
    26224         0f 84/jump-if-= break/disp32
    26225         (write-buffered *(ebp+0x14) "fn ")
    26226         8b/-> *(ebp+0x10) 0/r32/eax
    26227         (lookup *eax *(eax+4))  # Function-name Function-name => eax
    26228         (write-buffered *(ebp+0x14) %eax)
    26229         (write-buffered *(ebp+0x14) ": call ")
    26230         (lookup *edi *(edi+4))  # Function-name Function-name => eax
    26231         (write-buffered *(ebp+0x14) %eax)
    26232         (write-buffered *(ebp+0x14) ": too many inouts\n")
    26233         (flush *(ebp+0x14))
    26234         (stop *(ebp+0x18) 1)
    26235       }
    26236       # if (expected == 0) error("too few inouts")
    26237       {
    26238         81 7/subop/compare %edx 0/imm32
    26239         0f 84/jump-if-= break/disp32
    26240         (write-buffered *(ebp+0x14) "fn ")
    26241         8b/-> *(ebp+0x10) 0/r32/eax
    26242         (lookup *eax *(eax+4))  # Function-name Function-name => eax
    26243         (write-buffered *(ebp+0x14) %eax)
    26244         (write-buffered *(ebp+0x14) ": call ")
    26245         (lookup *edi *(edi+4))  # Function-name Function-name => eax
    26246         (write-buffered *(ebp+0x14) %eax)
    26247         (write-buffered *(ebp+0x14) ": too few inouts\n")
    26248         (flush *(ebp+0x14))
    26249         (stop *(ebp+0x18) 1)
    26250       }
    26251     }
    26252 $check-mu-call:check-outputs:
    26253     # var outputs/ecx: (addr stmt-var) = lookup(stmt->outputs)
    26254     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    26255     89/<- %ecx 0/r32/eax
    26256     # var expected/edx: (addr list var) = lookup(f->outputs)
    26257     (lookup *(edi+0x10) *(edi+0x14))  # Function-outputs Function-outputs => eax
    26258     89/<- %edx 0/r32/eax
    26259     {
    26260 $check-mu-call:check-for-outputs:
    26261       # if (outputs == 0) break
    26262       81 7/subop/compare %ecx 0/imm32
    26263       0f 84/jump-if-= break/disp32
    26264       # if (expected == 0) error
    26265       81 7/subop/compare %edx 0/imm32
    26266       0f 84/jump-if-= break/disp32
    26267 $check-mu-call:check-output-type:
    26268       # var v/eax: (addr v) = lookup(outputs->value)
    26269       (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
    26270       # var t/ebx: (addr type-tree) = lookup(v->type)
    26271       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    26272       89/<- %ebx 0/r32/eax
    26273       # if (outputs->is-deref?) t = t->right  # TODO: check that t->left is an addr
    26274       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
    26275       {
    26276         74/jump-if-= break/disp8
    26277         (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
    26278         89/<- %ebx 0/r32/eax
    26279       }
    26280       # var v2/eax: (addr v) = lookup(expected->value)
    26281       (lookup *edx *(edx+4))  # List-value List-value => eax
    26282       # var t2/eax: (addr type-tree) = lookup(v2->type)
    26283       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    26284       # if (t != t2) error
    26285       (type-match? %eax %ebx *(ebp-4))  # => eax
    26286       3d/compare-eax-and 0/imm32/false
    26287       {
    26288         0f 85/jump-if-!= break/disp32
    26289         (write-buffered *(ebp+0x14) "fn ")
    26290         8b/-> *(ebp+0x10) 0/r32/eax
    26291         (lookup *eax *(eax+4))  # Function-name Function-name => eax
    26292         (write-buffered *(ebp+0x14) %eax)
    26293         (write-buffered *(ebp+0x14) ": call ")
    26294         (lookup *edi *(edi+4))  # Function-name Function-name => eax
    26295         (write-buffered *(ebp+0x14) %eax)
    26296         (write-buffered *(ebp+0x14) ": type for output '")
    26297         (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
    26298         (lookup *eax *(eax+4))  # Var-name Var-name => eax
    26299         (write-buffered *(ebp+0x14) %eax)
    26300         (write-buffered *(ebp+0x14) "' is not right\n")
    26301         (flush *(ebp+0x14))
    26302         (stop *(ebp+0x18) 1)
    26303       }
    26304 $check-mu-call:check-output-register:
    26305       # var v/eax: (addr v) = lookup(outputs->value)
    26306       (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
    26307       # var r/ebx: (addr array byte) = lookup(v->register)
    26308       (lookup *(eax+18) *(eax+0x1c))  # Var-register Var-register => eax
    26309       89/<- %ebx 0/r32/eax
    26310       # if (r == 0) error
    26311       3d/compare-eax-and 0/imm32
    26312       {
    26313         0f 85/jump-if-!= break/disp32
    26314         (write-buffered *(ebp+0x14) "fn ")
    26315         8b/-> *(ebp+0x10) 0/r32/eax
    26316         (lookup *eax *(eax+4))  # Function-name Function-name => eax
    26317         (write-buffered *(ebp+0x14) %eax)
    26318         (write-buffered *(ebp+0x14) ": call ")
    26319         (lookup *edi *(edi+4))  # Function-name Function-name => eax
    26320         (write-buffered *(ebp+0x14) %eax)
    26321         (write-buffered *(ebp+0x14) ": output '")
    26322         (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
    26323         (lookup *eax *(eax+4))  # Var-name Var-name => eax
    26324         (write-buffered *(ebp+0x14) %eax)
    26325         (write-buffered *(ebp+0x14) "' is not in a register\n")
    26326         (flush *(ebp+0x14))
    26327         (stop *(ebp+0x18) 1)
    26328       }
    26329       # var v2/eax: (addr v) = lookup(expected->value)
    26330       (lookup *edx *(edx+4))  # Stmt-var-value Stmt-var-value => eax
    26331       # var r2/eax: (addr array byte) = lookup(v2->register)
    26332       (lookup *(eax+18) *(eax+0x1c))  # Var-register Var-register => eax
    26333       # if (r != r2) error
    26334       (string-equal? %eax %ebx)  # => eax
    26335       3d/compare-eax-and 0/imm32/false
    26336       {
    26337         0f 85/jump-if-!= break/disp32
    26338         (write-buffered *(ebp+0x14) "fn ")
    26339         8b/-> *(ebp+0x10) 0/r32/eax
    26340         (lookup *eax *(eax+4))  # Function-name Function-name => eax
    26341         (write-buffered *(ebp+0x14) %eax)
    26342         (write-buffered *(ebp+0x14) ": call ")
    26343         (lookup *edi *(edi+4))  # Function-name Function-name => eax
    26344         (write-buffered *(ebp+0x14) %eax)
    26345         (write-buffered *(ebp+0x14) ": register for output '")
    26346         (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
    26347         (lookup *eax *(eax+4))  # Var-name Var-name => eax
    26348         (write-buffered *(ebp+0x14) %eax)
    26349         (write-buffered *(ebp+0x14) "' is not right\n")
    26350         (flush *(ebp+0x14))
    26351         (stop *(ebp+0x18) 1)
    26352       }
    26353 $check-mu-call:continue-to-next-output:
    26354       # outputs = lookup(outputs->next)
    26355       (lookup *(ecx+8) *(ecx+0xc))  # Stmt-var-next Stmt-var-next => eax
    26356       89/<- %ecx 0/r32/eax
    26357       # expected = lookup(expected->next)
    26358       (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
    26359       89/<- %edx 0/r32/eax
    26360       #
    26361       e9/jump loop/disp32
    26362     }
    26363 $check-mu-call:check-output-count:
    26364     # if (outputs == expected) proceed
    26365     39/compare %ecx 2/r32/edx
    26366     {
    26367       0f 84/jump-if-= break/disp32
    26368       # exactly one of the two is null
    26369       # if (outputs == 0) error("too many outputs")
    26370       {
    26371         81 7/subop/compare %ecx 0/imm32
    26372         0f 84/jump-if-= break/disp32
    26373         (write-buffered *(ebp+0x14) "fn ")
    26374         8b/-> *(ebp+0x10) 0/r32/eax
    26375         (lookup *eax *(eax+4))  # Function-name Function-name => eax
    26376         (write-buffered *(ebp+0x14) %eax)
    26377         (write-buffered *(ebp+0x14) ": call ")
    26378         (lookup *edi *(edi+4))  # Function-name Function-name => eax
    26379         (write-buffered *(ebp+0x14) %eax)
    26380         (write-buffered *(ebp+0x14) ": too many outputs\n")
    26381         (flush *(ebp+0x14))
    26382         (stop *(ebp+0x18) 1)
    26383       }
    26384       # if (expected == 0) error("too few outputs")
    26385       {
    26386         81 7/subop/compare %edx 0/imm32
    26387         0f 84/jump-if-= break/disp32
    26388         (write-buffered *(ebp+0x14) "fn ")
    26389         8b/-> *(ebp+0x10) 0/r32/eax
    26390         (lookup *eax *(eax+4))  # Function-name Function-name => eax
    26391         (write-buffered *(ebp+0x14) %eax)
    26392         (write-buffered *(ebp+0x14) ": call ")
    26393         (lookup *edi *(edi+4))  # Function-name Function-name => eax
    26394         (write-buffered *(ebp+0x14) %eax)
    26395         (write-buffered *(ebp+0x14) ": too few outputs\n")
    26396         (flush *(ebp+0x14))
    26397         (stop *(ebp+0x18) 1)
    26398       }
    26399     }
    26400 $check-mu-call:end:
    26401     # . restore registers
    26402     5f/pop-to-edi
    26403     5e/pop-to-esi
    26404     5b/pop-to-ebx
    26405     5a/pop-to-edx
    26406     59/pop-to-ecx
    26407     58/pop-to-eax
    26408     # . reclaim locals exclusively on the stack
    26409     81 0/subop/add %esp 0x70/imm32
    26410     # . epilogue
    26411     89/<- %esp 5/r32/ebp
    26412     5d/pop-to-ebp
    26413     c3/return
    26414
    26415 # like type-equal? but takes literals type parameters into account
    26416 type-match?:  # def: (addr type-tree), call: (addr type-tree), type-parameters: (addr table (handle array byte) (addr type-tree)) -> result/eax: boolean
    26417     # . prologue
    26418     55/push-ebp
    26419     89/<- %ebp 4/r32/esp
    26420     # if (call is literal and def is numberlike) return true
    26421     {
    26422 $type-match?:check-literal-int:
    26423       (simple-mu-type? *(ebp+0xc) 0)  # literal => eax
    26424       3d/compare-eax-and 0/imm32/false
    26425       74/jump-if-= break/disp8
    26426       (mu-numberlike-output? *(ebp+8))  # => eax
    26427       3d/compare-eax-and 0/imm32/false
    26428       74/jump-if-= break/disp8
    26429       b8/copy-to-eax 1/imm32/true
    26430       e9/jump $type-match?:end/disp32
    26431     }
    26432     # if (call is literal-string and def is string) return true
    26433     {
    26434 $type-match?:check-literal-string:
    26435       (simple-mu-type? *(ebp+0xc) 0x10)  # literal-string => eax
    26436       3d/compare-eax-and 0/imm32/false
    26437       74/jump-if-= break/disp8
    26438       (mu-string-type? *(ebp+8))  # => eax
    26439       3d/compare-eax-and 0/imm32/false
    26440       74/jump-if-= break/disp8
    26441       b8/copy-to-eax 1/imm32/true
    26442       e9/jump $type-match?:end/disp32
    26443     }
    26444 $type-match?:baseline:
    26445     # otherwise fall back
    26446     (type-component-match? *(ebp+8) *(ebp+0xc) *(ebp+0x10))  # => eax
    26447 $type-match?:end:
    26448     # . epilogue
    26449     89/<- %esp 5/r32/ebp
    26450     5d/pop-to-ebp
    26451     c3/return
    26452
    26453 type-component-match?:  # def: (addr type-tree), call: (addr type-tree), type-parameters: (addr table (handle array byte) (addr type-tree)) -> result/eax: boolean
    26454     # . prologue
    26455     55/push-ebp
    26456     89/<- %ebp 4/r32/esp
    26457     # . save registers
    26458     51/push-ecx
    26459     52/push-edx
    26460     53/push-ebx
    26461     # ecx = def
    26462     8b/-> *(ebp+8) 1/r32/ecx
    26463     # edx = call
    26464     8b/-> *(ebp+0xc) 2/r32/edx
    26465 $type-component-match?:compare-addr:
    26466     # if (def == call) return true
    26467     8b/-> %ecx 0/r32/eax  # Var-type
    26468     39/compare %edx 0/r32/eax  # Var-type
    26469     b8/copy-to-eax 1/imm32/true
    26470     0f 84/jump-if-= $type-component-match?:end/disp32
    26471     # if (def == 0) return false
    26472     b8/copy-to-eax 0/imm32/false
    26473     81 7/subop/compare %ecx 0/imm32  # Type-tree-is-atom
    26474     0f 84/jump-if-= $type-component-match?:end/disp32
    26475     # if (call == 0) return false
    26476     81 7/subop/compare %edx 0/imm32  # Type-tree-is-atom
    26477     0f 84/jump-if-= $type-component-match?:end/disp32
    26478     # if def is a type parameter, just check in type-parameters
    26479     {
    26480 $type-component-match?:check-type-parameter:
    26481       81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
    26482       74/jump-if-= break/disp8
    26483       81 7/subop/compare *(ecx+4) 0xa/imm32/type-parameter  # Type-tree-value
    26484       75/jump-if-!= break/disp8
    26485 $type-component-match?:type-parameter:
    26486       (type-parameter-match? *(ecx+8) *(ecx+0xc)  %edx  *(ebp+0x10))  # => eax
    26487       e9/jump $type-component-match?:end/disp32
    26488     }
    26489     # if def is a list containing just a type parameter, just check in type-parameters
    26490     {
    26491 $type-component-match?:check-list-type-parameter:
    26492       # if def is a list..
    26493       81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
    26494       75/jump-if-!= break/disp8
    26495       #   ..that's a singleton
    26496       81 7/subop/compare *(ecx+0xc) 0/imm32  # Type-tree-left
    26497       75/jump-if-!= break/disp8
    26498       #   ..and whose head is a type parameter
    26499       (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
    26500       81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
    26501       74/jump-if-= break/disp8
    26502       81 7/subop/compare *(eax+4) 0xa/imm32/type-parameter  # Type-tree-value
    26503       75/jump-if-!= break/disp8
    26504 $type-component-match?:list-type-parameter:
    26505       (type-parameter-match? *(eax+8) *(eax+0xc)  %edx  *(ebp+0x10))  # => eax
    26506       e9/jump $type-component-match?:end/disp32
    26507     }
    26508 $type-component-match?:compare-atom-state:
    26509     # if (def->is-atom? != call->is-atom?) return false
    26510     8b/-> *ecx 3/r32/ebx  # Type-tree-is-atom
    26511     39/compare *edx 3/r32/ebx  # Type-tree-is-atom
    26512     b8/copy-to-eax 0/imm32/false
    26513     0f 85/jump-if-!= $type-component-match?:end/disp32
    26514     # if def->is-atom? return (def->value == call->value)
    26515     {
    26516 $type-component-match?:check-atom:
    26517       81 7/subop/compare %ebx 0/imm32/false
    26518       74/jump-if-= break/disp8
    26519 $type-component-match?:is-atom:
    26520       8b/-> *(ecx+4) 0/r32/eax  # Type-tree-value
    26521       39/compare *(edx+4) 0/r32/eax  # Type-tree-value
    26522       0f 94/set-if-= %al
    26523       25/and-eax-with 0xff/imm32
    26524       e9/jump $type-component-match?:end/disp32
    26525     }
    26526 $type-component-match?:check-left:
    26527     # if (!type-component-match?(def->left, call->left)) return false
    26528     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
    26529     89/<- %ebx 0/r32/eax
    26530     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
    26531     (type-component-match? %ebx %eax *(ebp+0x10))  # => eax
    26532     3d/compare-eax-and 0/imm32/false
    26533     74/jump-if-= $type-component-match?:end/disp8
    26534 $type-component-match?:check-right:
    26535     # return type-component-match?(def->right, call->right)
    26536     (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
    26537     89/<- %ebx 0/r32/eax
    26538     (lookup *(edx+0xc) *(edx+0x10))  # Type-tree-right Type-tree-right => eax
    26539     (type-component-match? %ebx %eax *(ebp+0x10))  # => eax
    26540 $type-component-match?:end:
    26541     # . restore registers
    26542     5b/pop-to-ebx
    26543     5a/pop-to-edx
    26544     59/pop-to-ecx
    26545     # . epilogue
    26546     89/<- %esp 5/r32/ebp
    26547     5d/pop-to-ebp
    26548     c3/return
    26549
    26550 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
    26551     # . prologue
    26552     55/push-ebp
    26553     89/<- %ebp 4/r32/esp
    26554     # . save registers
    26555     51/push-ecx
    26556     #
    26557     (get-or-insert-handle *(ebp+0x14)  *(ebp+8) *(ebp+0xc)  0xc)  # => eax
    26558     # if parameter wasn't saved, save it
    26559     {
    26560       81 7/subop/compare *eax 0/imm32
    26561       75/jump-if-!= break/disp8
    26562       8b/-> *(ebp+0x10) 1/r32/ecx
    26563       89/<- *eax 1/r32/ecx
    26564     }
    26565     #
    26566     (type-equal? *(ebp+0x10) *eax)  # => eax
    26567 $type-parameter-match?:end:
    26568     # . restore registers
    26569     59/pop-to-ecx
    26570     # . epilogue
    26571     89/<- %esp 5/r32/ebp
    26572     5d/pop-to-ebp
    26573     c3/return
    26574
    26575 size-of:  # v: (addr var) -> result/eax: int
    26576     # . prologue
    26577     55/push-ebp
    26578     89/<- %ebp 4/r32/esp
    26579     # . save registers
    26580     51/push-ecx
    26581     # var t/ecx: (addr type-tree) = lookup(v->type)
    26582     8b/-> *(ebp+8) 1/r32/ecx
    26583 #?     (write-buffered Stderr "size-of ")
    26584 #?     (write-int32-hex-buffered Stderr %ecx)
    26585 #?     (write-buffered Stderr Newline)
    26586 #?     (write-buffered Stderr "type allocid: ")
    26587 #?     (write-int32-hex-buffered Stderr *(ecx+8))
    26588 #?     (write-buffered Stderr Newline)
    26589 #?     (flush Stderr)
    26590     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
    26591     89/<- %ecx 0/r32/eax
    26592     # if mu-array?(t) return size-of-array(t)
    26593     {
    26594       (mu-array? %ecx)  # => eax
    26595       3d/compare-eax-and 0/imm32/false
    26596       74/jump-if-= break/disp8
    26597       (size-of-array %ecx)  # => eax
    26598       eb/jump $size-of:end/disp8
    26599     }
    26600     # if mu-stream?(t) return size-of-stream(t)
    26601     {
    26602       (mu-stream? %ecx)  # => eax
    26603       3d/compare-eax-and 0/imm32/false
    26604       74/jump-if-= break/disp8
    26605       (size-of-stream %ecx)  # => eax
    26606       eb/jump $size-of:end/disp8
    26607     }
    26608     # if (!t->is-atom?) t = lookup(t->left)
    26609     {
    26610       81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
    26611       75/jump-if-!= break/disp8
    26612       (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
    26613       89/<- %ecx 0/r32/eax
    26614     }
    26615     # TODO: assert t->is-atom?
    26616     (size-of-type-id *(ecx+4))  # Type-tree-value => eax
    26617 $size-of:end:
    26618     # . restore registers
    26619     59/pop-to-ecx
    26620     # . epilogue
    26621     89/<- %esp 5/r32/ebp
    26622     5d/pop-to-ebp
    26623     c3/return
    26624
    26625 size-of-deref:  # v: (addr var) -> result/eax: int
    26626     # . prologue
    26627     55/push-ebp
    26628     89/<- %ebp 4/r32/esp
    26629     # . save registers
    26630     51/push-ecx
    26631     # var t/ecx: (addr type-tree) = lookup(v->type)
    26632     8b/-> *(ebp+8) 1/r32/ecx
    26633     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
    26634     89/<- %ecx 0/r32/eax
    26635     # TODO: assert(t is an addr)
    26636     # t = lookup(t->right)
    26637     (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
    26638     89/<- %ecx 0/r32/eax
    26639     # if mu-array?(t) return size-of-array(t)
    26640     {
    26641       (mu-array? %ecx)  # => eax
    26642       3d/compare-eax-and 0/imm32/false
    26643       74/jump-if-= break/disp8
    26644       (size-of-array %ecx)  # => eax
    26645       eb/jump $size-of-deref:end/disp8
    26646     }
    26647     # if mu-stream?(t) return size-of-stream(t)
    26648     {
    26649       (mu-stream? %ecx)  # => eax
    26650       3d/compare-eax-and 0/imm32/false
    26651       74/jump-if-= break/disp8
    26652       (size-of-stream %ecx)  # => eax
    26653       eb/jump $size-of-deref:end/disp8
    26654     }
    26655     # if (!t->is-atom?) t = lookup(t->left)
    26656     {
    26657       81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
    26658       75/jump-if-!= break/disp8
    26659       (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
    26660       89/<- %ecx 0/r32/eax
    26661     }
    26662     # TODO: assert t->is-atom?
    26663     (size-of-type-id *(ecx+4))  # Type-tree-value => eax
    26664 $size-of-deref:end:
    26665     # . restore registers
    26666     59/pop-to-ecx
    26667     # . epilogue
    26668     89/<- %esp 5/r32/ebp
    26669     5d/pop-to-ebp
    26670     c3/return
    26671
    26672 mu-array?:  # t: (addr type-tree) -> result/eax: boolean
    26673     # . prologue
    26674     55/push-ebp
    26675     89/<- %ebp 4/r32/esp
    26676     # . save registers
    26677     51/push-ecx
    26678     # ecx = t
    26679     8b/-> *(ebp+8) 1/r32/ecx
    26680     # if t->is-atom?, return false
    26681     81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
    26682     75/jump-if-!= $mu-array?:return-false/disp8
    26683     # if !t->left->is-atom?, return false
    26684     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
    26685     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
    26686     74/jump-if-= $mu-array?:return-false/disp8
    26687     # return t->left->value == array
    26688     81 7/subop/compare *(eax+4) 3/imm32/array-type-id  # Type-tree-value
    26689     0f 94/set-if-= %al
    26690     25/and-eax-with 0xff/imm32
    26691     eb/jump $mu-array?:end/disp8
    26692 $mu-array?:return-false:
    26693     b8/copy-to-eax 0/imm32/false
    26694 $mu-array?:end:
    26695     # . restore registers
    26696     59/pop-to-ecx
    26697     # . epilogue
    26698     89/<- %esp 5/r32/ebp
    26699     5d/pop-to-ebp
    26700     c3/return
    26701
    26702 # size of a statically allocated array where the size is part of the type expression
    26703 size-of-array:  # a: (addr type-tree) -> result/eax: int
    26704     # . prologue
    26705     55/push-ebp
    26706     89/<- %ebp 4/r32/esp
    26707     # . save registers
    26708     51/push-ecx
    26709     52/push-edx
    26710     #
    26711     8b/-> *(ebp+8) 1/r32/ecx
    26712     # TODO: assert that a->left is 'array'
    26713     (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
    26714     89/<- %ecx 0/r32/eax
    26715     # var elem-type/edx: type-id = a->right->left->value
    26716     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
    26717     8b/-> *(eax+4) 2/r32/edx  # Type-tree-value
    26718     # TODO: assert that a->right->right->left->value == size
    26719     # var array-size/ecx: int = a->right->right->left->value-size
    26720     (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
    26721     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    26722     8b/-> *(eax+8) 1/r32/ecx  # Type-tree-value-size
    26723     # return 4 + array-size * size-of(elem-type)
    26724     (size-of-type-id-as-array-element %edx)  # => eax
    26725     f7 4/subop/multiply-into-edx-eax %ecx
    26726     05/add-to-eax 4/imm32  # for array size
    26727     # TODO: check edx for overflow
    26728 $size-of-array:end:
    26729     # . restore registers
    26730     5a/pop-to-edx
    26731     59/pop-to-ecx
    26732     # . epilogue
    26733     89/<- %esp 5/r32/ebp
    26734     5d/pop-to-ebp
    26735     c3/return
    26736
    26737 mu-stream?:  # t: (addr type-tree) -> result/eax: boolean
    26738     # . prologue
    26739     55/push-ebp
    26740     89/<- %ebp 4/r32/esp
    26741     # . save registers
    26742     51/push-ecx
    26743     # ecx = t
    26744     8b/-> *(ebp+8) 1/r32/ecx
    26745     # if t->is-atom?, return false
    26746     81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
    26747     75/jump-if-!= $mu-stream?:return-false/disp8
    26748     # if !t->left->is-atom?, return false
    26749     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
    26750     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
    26751     74/jump-if-= $mu-stream?:return-false/disp8
    26752     # return t->left->value == stream
    26753     81 7/subop/compare *(eax+4) 0xb/imm32/stream-type-id  # Type-tree-value
    26754     0f 94/set-if-= %al
    26755     25/and-eax-with 0xff/imm32
    26756     eb/jump $mu-stream?:end/disp8
    26757 $mu-stream?:return-false:
    26758     b8/copy-to-eax 0/imm32/false
    26759 $mu-stream?:end:
    26760     # . restore registers
    26761     59/pop-to-ecx
    26762     # . epilogue
    26763     89/<- %esp 5/r32/ebp
    26764     5d/pop-to-ebp
    26765     c3/return
    26766
    26767 # size of a statically allocated stream where the size is part of the type expression
    26768 size-of-stream:  # a: (addr type-tree) -> result/eax: int
    26769     # . prologue
    26770     55/push-ebp
    26771     89/<- %ebp 4/r32/esp
    26772     #
    26773     (size-of-array *(ebp+8))  # assumes we ignore the actual type name 'array' in the type
    26774     05/add-to-eax 8/imm32  # for read/write pointers
    26775 $size-of-stream:end:
    26776     # . epilogue
    26777     89/<- %esp 5/r32/ebp
    26778     5d/pop-to-ebp
    26779     c3/return
    26780
    26781 size-of-type-id:  # t: type-id -> result/eax: int
    26782     # . prologue
    26783     55/push-ebp
    26784     89/<- %ebp 4/r32/esp
    26785     # . save registers
    26786     51/push-ecx
    26787     # var out/ecx: (handle typeinfo)
    26788     68/push 0/imm32
    26789     68/push 0/imm32
    26790     89/<- %ecx 4/r32/esp
    26791     # eax = t
    26792     8b/-> *(ebp+8) 0/r32/eax
    26793     # if t is a literal, return 0
    26794     3d/compare-eax-and 0/imm32
    26795     0f 84/jump-if-= $size-of-type-id:end/disp32  # eax changes type from type-id to int
    26796     # if t is a byte, return 4 (because we don't really support non-multiples of 4)
    26797     3d/compare-eax-and 8/imm32/byte
    26798     {
    26799       75/jump-if-!= break/disp8
    26800       b8/copy-to-eax 4/imm32
    26801       eb/jump $size-of-type-id:end/disp8
    26802     }
    26803     # if t is a handle, return 8
    26804     3d/compare-eax-and 4/imm32/handle
    26805     {
    26806       75/jump-if-!= break/disp8
    26807       b8/copy-to-eax 8/imm32
    26808       eb/jump $size-of-type-id:end/disp8  # eax changes type from type-id to int
    26809     }
    26810     # if t is a slice, return 8
    26811     3d/compare-eax-and 0xc/imm32/slice
    26812     {
    26813       75/jump-if-!= break/disp8
    26814       b8/copy-to-eax 8/imm32
    26815       eb/jump $size-of-type-id:end/disp8  # eax changes type from type-id to int
    26816     }
    26817     # if t is a user-defined type, return its size
    26818     # TODO: support non-atom type
    26819     (find-typeinfo %eax %ecx)
    26820     {
    26821       81 7/subop/compare *ecx 0/imm32
    26822       74/jump-if-= break/disp8
    26823 $size-of-type-id:user-defined:
    26824       (lookup *ecx *(ecx+4))  # => eax
    26825       8b/-> *(eax+0xc) 0/r32/eax  # Typeinfo-total-size-in-bytes
    26826       eb/jump $size-of-type-id:end/disp8
    26827     }
    26828     # otherwise return the word size
    26829     b8/copy-to-eax 4/imm32
    26830 $size-of-type-id:end:
    26831     # . reclaim locals
    26832     81 0/subop/add %esp 8/imm32
    26833     # . restore registers
    26834     59/pop-to-ecx
    26835     # . epilogue
    26836     89/<- %esp 5/r32/ebp
    26837     5d/pop-to-ebp
    26838     c3/return
    26839
    26840 # Minor violation of our type system since it returns an addr. But we could
    26841 # replace it with a handle some time.
    26842 # Returns null if t is an atom.
    26843 type-tail:  # t: (addr type-tree) -> out/eax: (addr type-tree)
    26844     # . prologue
    26845     55/push-ebp
    26846     89/<- %ebp 4/r32/esp
    26847     # . save registers
    26848     51/push-ecx
    26849     # eax = 0
    26850     b8/copy-to-eax 0/imm32
    26851     # ecx = t
    26852     8b/-> *(ebp+8) 1/r32/ecx
    26853 $type-tail:check-atom:
    26854     # if t->is-atom? return 0
    26855     81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
    26856     0f 85/jump-if-!= $type-tail:end/disp32
    26857     # var tail = t->right
    26858     (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
    26859     89/<- %ecx 0/r32/eax
    26860 $type-tail:check-singleton:
    26861     # if (tail->right == 0) return tail->left
    26862     {
    26863       81 7/subop/compare *(ecx+0xc) 0/imm32  # Type-tree-right
    26864       75/jump-if-!= break/disp8
    26865       (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
    26866       e9/jump $type-tail:end/disp32
    26867     }
    26868     # if tail->right->left is an array-capacity, return tail->left
    26869     {
    26870 $type-tail:check-array-capacity:
    26871       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
    26872       81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
    26873       75/jump-if-!= break/disp8
    26874 $type-tail:check-array-capacity-1:
    26875       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    26876       3d/compare-eax-and 0/imm32
    26877       74/jump-if-= break/disp8
    26878 $type-tail:check-array-capacity-2:
    26879       (simple-mu-type? %eax 9)  # array-capacity => eax
    26880       3d/compare-eax-and 0/imm32/false
    26881       74/jump-if-= break/disp8
    26882 $type-tail:array-capacity:
    26883       (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
    26884       eb/jump $type-tail:end/disp8
    26885     }
    26886 $type-tail:check-compound-left:
    26887     # if !tail->left->is-atom? return tail->left
    26888     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
    26889     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
    26890     74/jump-if-= $type-tail:end/disp8
    26891 $type-tail:return-tail:
    26892     # return tail
    26893     89/<- %eax 1/r32/ecx
    26894 $type-tail:end:
    26895     # . restore registers
    26896     59/pop-to-ecx
    26897     # . epilogue
    26898     89/<- %esp 5/r32/ebp
    26899     5d/pop-to-ebp
    26900     c3/return
    26901
    26902 type-equal?:  # a: (addr type-tree), b: (addr type-tree) -> result/eax: boolean
    26903     # . prologue
    26904     55/push-ebp
    26905     89/<- %ebp 4/r32/esp
    26906     # . save registers
    26907     51/push-ecx
    26908     52/push-edx
    26909     53/push-ebx
    26910     # ecx = a
    26911     8b/-> *(ebp+8) 1/r32/ecx
    26912     # edx = b
    26913     8b/-> *(ebp+0xc) 2/r32/edx
    26914 $type-equal?:compare-addr:
    26915     # if (a == b) return true
    26916     8b/-> %ecx 0/r32/eax  # Var-type
    26917     39/compare %edx 0/r32/eax  # Var-type
    26918     b8/copy-to-eax 1/imm32/true
    26919     0f 84/jump-if-= $type-equal?:end/disp32
    26920 $type-equal?:compare-null-a:
    26921     # if (a == 0) return false
    26922     b8/copy-to-eax 0/imm32/false
    26923     81 7/subop/compare %ecx 0/imm32
    26924     0f 84/jump-if-= $type-equal?:end/disp32
    26925 $type-equal?:compare-null-b:
    26926     # if (b == 0) return false
    26927     81 7/subop/compare %edx 0/imm32
    26928     0f 84/jump-if-= $type-equal?:end/disp32
    26929 $type-equal?:compare-atom-state:
    26930     # if (a->is-atom? != b->is-atom?) return false
    26931     8b/-> *ecx 3/r32/ebx  # Type-tree-is-atom
    26932     39/compare *edx 3/r32/ebx  # Type-tree-is-atom
    26933     b8/copy-to-eax 0/imm32/false
    26934     0f 85/jump-if-!= $type-equal?:end/disp32
    26935     # if a->is-atom? return (a->value == b->value)
    26936     {
    26937 $type-equal?:check-atom:
    26938       81 7/subop/compare %ebx 0/imm32/false
    26939       74/jump-if-= break/disp8
    26940 $type-equal?:is-atom:
    26941       8b/-> *(ecx+4) 0/r32/eax  # Type-tree-value
    26942       39/compare *(edx+4) 0/r32/eax  # Type-tree-value
    26943       0f 94/set-if-= %al
    26944       25/and-eax-with 0xff/imm32
    26945       e9/jump $type-equal?:end/disp32
    26946     }
    26947 $type-equal?:check-left:
    26948     # if (!type-equal?(a->left, b->left)) return false
    26949     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
    26950     89/<- %ebx 0/r32/eax
    26951     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
    26952     (type-equal? %eax %ebx)  # => eax
    26953     3d/compare-eax-and 0/imm32/false
    26954     74/jump-if-= $type-equal?:end/disp8
    26955 $type-equal?:check-right:
    26956     # return type-equal?(a->right, b->right)
    26957     (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
    26958     89/<- %ebx 0/r32/eax
    26959     (lookup *(edx+0xc) *(edx+0x10))  # Type-tree-right Type-tree-right => eax
    26960     (type-equal? %eax %ebx)  # => eax
    26961 $type-equal?:end:
    26962     # . restore registers
    26963     5b/pop-to-ebx
    26964     5a/pop-to-edx
    26965     59/pop-to-ecx
    26966     # . epilogue
    26967     89/<- %esp 5/r32/ebp
    26968     5d/pop-to-ebp
    26969     c3/return
    26970
    26971 #######################################################
    26972 # Code-generation
    26973 #######################################################
    26974
    26975 == data
    26976
    26977 # Global state added to each var record when performing code-generation.
    26978 Curr-local-stack-offset:  # (addr int)
    26979     0/imm32
    26980
    26981 == code
    26982
    26983 # We may not need to pass err/ed everywhere here. I think they're relics of Mu
    26984 # getting type checks later in life.
    26985 # But we do need them for runtime checks, particularly array index bounds checks.
    26986 # So perhaps it's not worth taking them out. They're a safety net.
    26987
    26988 emit-subx:  # out: (addr buffered-file), err: (addr buffered-file), ed: (addr exit-descriptor)
    26989     # . prologue
    26990     55/push-ebp
    26991     89/<- %ebp 4/r32/esp
    26992     # . save registers
    26993     50/push-eax
    26994     # var curr/eax: (addr function) = *Program->functions
    26995     (lookup *_Program-functions *_Program-functions->payload)  # => eax
    26996     {
    26997       # if (curr == null) break
    26998       3d/compare-eax-and 0/imm32
    26999       0f 84/jump-if-= break/disp32
    27000       (emit-subx-function *(ebp+8) %eax *(ebp+0xc) *(ebp+0x10))
    27001       # curr = lookup(curr->next)
    27002       (lookup *(eax+0x20) *(eax+0x24))  # Function-next Function-next => eax
    27003       e9/jump loop/disp32
    27004     }
    27005 $emit-subx:end:
    27006     # . restore registers
    27007     58/pop-to-eax
    27008     # . epilogue
    27009     89/<- %esp 5/r32/ebp
    27010     5d/pop-to-ebp
    27011     c3/return
    27012
    27013 emit-subx-function:  # out: (addr buffered-file), f: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    27014     # . prologue
    27015     55/push-ebp
    27016     89/<- %ebp 4/r32/esp
    27017     # some preprocessing
    27018     (populate-mu-type-offsets-in-inouts *(ebp+0xc))
    27019     # . save registers
    27020     50/push-eax
    27021     51/push-ecx
    27022     52/push-edx
    27023     # initialize some global state
    27024     c7 0/subop/copy *Curr-block-depth 1/imm32  # Important: keep this in sync with the parse phase
    27025     c7 0/subop/copy *Curr-local-stack-offset 0/imm32
    27026     # ecx = f
    27027     8b/-> *(ebp+0xc) 1/r32/ecx
    27028     # var vars/edx: (stack (addr var) 256)
    27029     81 5/subop/subtract %esp 0xc00/imm32
    27030     68/push 0xc00/imm32/size
    27031     68/push 0/imm32/top
    27032     89/<- %edx 4/r32/esp
    27033     # var name/eax: (addr array byte) = lookup(f->name)
    27034     (lookup *ecx *(ecx+4))  # Function-name Function-name => eax
    27035     #
    27036     (write-buffered *(ebp+8) %eax)
    27037     (write-buffered *(ebp+8) ":\n")
    27038     (emit-subx-prologue *(ebp+8))
    27039     # var body/eax: (addr block) = lookup(f->body)
    27040     (lookup *(ecx+0x18) *(ecx+0x1c))  # Function-body Function-body => eax
    27041     #
    27042     (emit-subx-block *(ebp+8) %eax %edx *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    27043     (emit-subx-epilogue *(ebp+8))
    27044     # TODO: validate that *Curr-block-depth and *Curr-local-stack-offset have
    27045     # been cleaned up
    27046 $emit-subx-function:end:
    27047     # . reclaim locals
    27048     81 0/subop/add %esp 0xc08/imm32
    27049     # . restore registers
    27050     5a/pop-to-edx
    27051     59/pop-to-ecx
    27052     58/pop-to-eax
    27053     # . epilogue
    27054     89/<- %esp 5/r32/ebp
    27055     5d/pop-to-ebp
    27056     c3/return
    27057
    27058 populate-mu-type-offsets-in-inouts:  # f: (addr function)
    27059     # . prologue
    27060     55/push-ebp
    27061     89/<- %ebp 4/r32/esp
    27062     # . save registers
    27063     50/push-eax
    27064     51/push-ecx
    27065     52/push-edx
    27066     53/push-ebx
    27067     57/push-edi
    27068     # var next-offset/edx: int = 8
    27069     ba/copy-to-edx 8/imm32
    27070     # var curr/ecx: (addr list var) = lookup(f->inouts)
    27071     8b/-> *(ebp+8) 1/r32/ecx
    27072     (lookup *(ecx+8) *(ecx+0xc))  # Function-inouts Function-inouts => eax
    27073     89/<- %ecx 0/r32/eax
    27074     {
    27075 $populate-mu-type-offsets-in-inouts:loop:
    27076       81 7/subop/compare %ecx 0/imm32
    27077       74/jump-if-= break/disp8
    27078       # var v/ebx: (addr var) = lookup(curr->value)
    27079       (lookup *ecx *(ecx+4))  # List-value List-value => eax
    27080       89/<- %ebx 0/r32/eax
    27081 #?       (lookup *ebx *(ebx+4))
    27082 #?       (write-buffered Stderr "setting offset of fn inout ")
    27083 #?       (write-buffered Stderr %eax)
    27084 #?       (write-buffered Stderr "@")
    27085 #?       (write-int32-hex-buffered Stderr %ebx)
    27086 #?       (write-buffered Stderr " to ")
    27087 #?       (write-int32-hex-buffered Stderr %edx)
    27088 #?       (write-buffered Stderr Newline)
    27089 #?       (flush Stderr)
    27090       # v->offset = next-offset
    27091       89/<- *(ebx+0x14) 2/r32/edx  # Var-offset
    27092       # next-offset += size-of(v)
    27093       (size-of %ebx)  # => eax
    27094       01/add-to %edx 0/r32/eax
    27095       # curr = lookup(curr->next)
    27096       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
    27097       89/<- %ecx 0/r32/eax
    27098       #
    27099       eb/jump loop/disp8
    27100     }
    27101 $populate-mu-type-offsets-in-inouts:end:
    27102     # . restore registers
    27103     5f/pop-to-edi
    27104     5b/pop-to-ebx
    27105     5a/pop-to-edx
    27106     59/pop-to-ecx
    27107     58/pop-to-eax
    27108     # . epilogue
    27109     89/<- %esp 5/r32/ebp
    27110     5d/pop-to-ebp
    27111     c3/return
    27112
    27113 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)
    27114     # . prologue
    27115     55/push-ebp
    27116     89/<- %ebp 4/r32/esp
    27117     # . save registers
    27118     50/push-eax
    27119     51/push-ecx
    27120     53/push-ebx
    27121     56/push-esi
    27122     # esi = stmts
    27123     8b/-> *(ebp+0xc) 6/r32/esi
    27124     #
    27125     {
    27126 $emit-subx-stmt-list:loop:
    27127       81 7/subop/compare %esi 0/imm32
    27128       0f 84/jump-if-= break/disp32
    27129       # var curr-stmt/ecx: (addr stmt) = lookup(stmts->value)
    27130       (lookup *esi *(esi+4))  # List-value List-value => eax
    27131       89/<- %ecx 0/r32/eax
    27132       {
    27133 $emit-subx-stmt-list:check-for-block:
    27134         81 7/subop/compare *ecx 0/imm32/block  # Stmt-tag
    27135         75/jump-if-!= break/disp8
    27136 $emit-subx-stmt-list:block:
    27137         (emit-subx-block *(ebp+8) %ecx *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
    27138       }
    27139       {
    27140 $emit-subx-stmt-list:check-for-stmt:
    27141         81 7/subop/compare *ecx 1/imm32/stmt1  # Stmt-tag
    27142         0f 85/jump-if-!= break/disp32
    27143 $emit-subx-stmt-list:stmt1:
    27144         {
    27145           (mu-branch? %ecx)  # => eax
    27146           3d/compare-eax-and 0/imm32/false
    27147           0f 84/jump-if-= break/disp32
    27148 $emit-subx-stmt-list:branch-stmt:
    27149 +-- 25 lines: # unconditional return ----------------------------------------------------------------------------------------------------------------------------------------------------
    27174 +-- 27 lines: # unconditional loops -----------------------------------------------------------------------------------------------------------------------------------------------------
    27201 +-- 16 lines: # unconditional breaks ----------------------------------------------------------------------------------------------------------------------------------------------------
    27217 +-- 38 lines: # simple conditional branches without a target ----------------------------------------------------------------------------------------------------------------------------
    27255 +-- 19 lines: # conditional branches with an explicit target ----------------------------------------------------------------------------------------------------------------------------
    27274         }
    27275 $emit-subx-stmt-list:1-to-1:
    27276         (emit-subx-stmt *(ebp+8) %ecx Primitives *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
    27277         e9/jump $emit-subx-stmt-list:continue/disp32
    27278       }
    27279       {
    27280 $emit-subx-stmt-list:check-for-var-def:
    27281         81 7/subop/compare *ecx 2/imm32/var-def  # Stmt-tag
    27282         75/jump-if-!= break/disp8
    27283 $emit-subx-stmt-list:var-def:
    27284         (emit-subx-var-def *(ebp+8) %ecx *(ebp+0x18) *(ebp+0x1c))
    27285         (push *(ebp+0x10) *(ecx+4))  # Vardef-var
    27286         (push *(ebp+0x10) *(ecx+8))  # Vardef-var
    27287         (push *(ebp+0x10) 0)  # Live-var-register-spilled = 0 for vars on the stack
    27288         #
    27289         eb/jump $emit-subx-stmt-list:continue/disp8
    27290       }
    27291       {
    27292 $emit-subx-stmt-list:check-for-reg-var-def:
    27293         81 7/subop/compare *ecx 3/imm32/reg-var-def  # Stmt-tag
    27294         0f 85/jump-if-!= break/disp32
    27295 $emit-subx-stmt-list:reg-var-def:
    27296         # TODO: ensure that there's exactly one output
    27297         (push-output-and-maybe-emit-spill *(ebp+8) %ecx *(ebp+0x10) %esi *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
    27298         # emit the instruction as usual
    27299         (emit-subx-stmt *(ebp+8) %ecx Primitives *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
    27300         #
    27301         eb/jump $emit-subx-stmt-list:continue/disp8
    27302       }
    27303 $emit-subx-stmt-list:continue:
    27304       # TODO: raise an error on unrecognized Stmt-tag
    27305       (lookup *(esi+8) *(esi+0xc))  # List-next List-next => eax
    27306       89/<- %esi 0/r32/eax
    27307       e9/jump loop/disp32
    27308     }
    27309 $emit-subx-stmt-list:emit-cleanup:
    27310     (emit-cleanup-code-until-depth *(ebp+8) *(ebp+0x10) *Curr-block-depth)
    27311 $emit-subx-stmt-list:clean-up:
    27312     (clean-up-stack-offset-state *(ebp+0x10) *Curr-block-depth)
    27313     (clean-up-blocks *(ebp+0x10) *Curr-block-depth *(ebp+0x14))
    27314 $emit-subx-stmt-list:end:
    27315     # . restore registers
    27316     5e/pop-to-esi
    27317     5b/pop-to-ebx
    27318     59/pop-to-ecx
    27319     58/pop-to-eax
    27320     # . epilogue
    27321     89/<- %esp 5/r32/ebp
    27322     5d/pop-to-ebp
    27323     c3/return
    27324
    27325 # 'later-stmts' includes 'stmt', but will behave the same even without it; reg-var-def stmts are guaranteed not to write to function outputs.
    27326 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)
    27327     # . prologue
    27328     55/push-ebp
    27329     89/<- %ebp 4/r32/esp
    27330     # . save registers
    27331     50/push-eax
    27332     51/push-ecx
    27333     52/push-edx
    27334     # ecx = stmt
    27335     8b/-> *(ebp+0xc) 1/r32/ecx
    27336     # var sv/eax: (addr stmt-var) = lookup(curr-stmt->outputs)
    27337     (lookup *(ecx+0x14) *(ecx+0x18))  # Regvardef-outputs Regvardef-outputs => eax
    27338     # TODO: assert !sv->is-deref?
    27339     # var v/ecx: (addr var) = lookup(sv->value)
    27340     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    27341     89/<- %ecx 0/r32/eax
    27342     # v->block-depth = *Curr-block-depth
    27343     8b/-> *Curr-block-depth 0/r32/eax
    27344     89/<- *(ecx+0x10) 0/r32/eax  # Var-block-depth
    27345 #?     (write-buffered Stderr "var ")
    27346 #?     (lookup *ecx *(ecx+4))
    27347 #?     (write-buffered Stderr %eax)
    27348 #?     (write-buffered Stderr " at depth ")
    27349 #?     (write-int32-hex-buffered Stderr *(ecx+0x10))
    27350 #?     (write-buffered Stderr Newline)
    27351 #?     (flush Stderr)
    27352     # ensure that v is in a register
    27353     81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
    27354     0f 84/jump-if-= $push-output-and-maybe-emit-spill:abort/disp32
    27355     # var emit-spill?/edx: boolean = not-yet-spilled-this-block? && will-not-write-some-register?(fn)
    27356     (not-yet-spilled-this-block? %ecx *(ebp+0x10))  # => eax
    27357     89/<- %edx 0/r32/eax
    27358     3d/compare-eax-and 0/imm32/false
    27359     0f 84/jump-if-= $push-output-and-maybe-emit-spill:push/disp32
    27360     (will-not-write-some-register? %ecx *(ebp+0x14) *(ebp+0x18))  # => eax
    27361     89/<- %edx 0/r32/eax
    27362     # check emit-spill?
    27363     3d/compare-eax-and 0/imm32/false
    27364     0f 84/jump-if-= $push-output-and-maybe-emit-spill:push/disp32
    27365     # TODO: assert(size-of(output) == 4)
    27366     # *Curr-local-stack-offset -= 4
    27367     81 5/subop/subtract *Curr-local-stack-offset 4/imm32
    27368     # emit spill
    27369     (lookup *(ecx+0x18) *(ecx+0x1c))  # Var-register Var-register => eax
    27370     (emit-push-register *(ebp+8) %eax)
    27371 $push-output-and-maybe-emit-spill:push:
    27372     8b/-> *(ebp+0xc) 1/r32/ecx
    27373     (lookup *(ecx+0x14) *(ecx+0x18))  # Regvardef-outputs Regvardef-outputs => eax
    27374     # push(vars, {sv->value, emit-spill?})
    27375     (push *(ebp+0x10) *eax)  # Stmt-var-value
    27376     (push *(ebp+0x10) *(eax+4))  # Stmt-var-value
    27377     (push *(ebp+0x10) %edx)
    27378 $push-output-and-maybe-emit-spill:end:
    27379     # . restore registers
    27380     5a/pop-to-edx
    27381     59/pop-to-ecx
    27382     58/pop-to-eax
    27383     # . epilogue
    27384     89/<- %esp 5/r32/ebp
    27385     5d/pop-to-ebp
    27386     c3/return
    27387
    27388 $push-output-and-maybe-emit-spill:abort:
    27389     # error("var '" var->name "' initialized from an instruction must live in a register\n")
    27390     (write-buffered *(ebp+0x1c) "var '")
    27391     (write-buffered *(ebp+0x1c) *eax)  # Var-name
    27392     (write-buffered *(ebp+0x1c) "' initialized from an instruction must live in a register\n")
    27393     (flush *(ebp+0x1c))
    27394     (stop *(ebp+0x20) 1)
    27395     # never gets here
    27396
    27397 emit-subx-cleanup-and-unconditional-nonlocal-branch:  # out: (addr buffered-file), stmt: (addr stmt1), vars: (addr stack live-var)
    27398     # . prologue
    27399     55/push-ebp
    27400     89/<- %ebp 4/r32/esp
    27401     # . save registers
    27402     50/push-eax
    27403     51/push-ecx
    27404     # ecx = stmt
    27405     8b/-> *(ebp+0xc) 1/r32/ecx
    27406     # var target/eax: (addr array byte) = curr-stmt->inouts->value->name
    27407     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    27408     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    27409     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    27410     # clean up until target block
    27411     (emit-cleanup-code-until-target *(ebp+8) *(ebp+0x10) %eax)
    27412     # emit jump to target block
    27413     (emit-indent *(ebp+8) *Curr-block-depth)
    27414     (write-buffered *(ebp+8) "e9/jump ")
    27415     (write-buffered *(ebp+8) %eax)
    27416     (lookup *(ecx+4) *(ecx+8))  # Stmt1-operation Stmt1-operation => eax
    27417     (string-starts-with? %eax "break")
    27418     3d/compare-eax-and 0/imm32/false
    27419     {
    27420       74/jump-if-= break/disp8
    27421       (write-buffered *(ebp+8) ":break/disp32\n")
    27422       eb/jump $emit-subx-cleanup-and-unconditional-nonlocal-branch:end/disp8
    27423     }
    27424     (write-buffered *(ebp+8) ":loop/disp32\n")
    27425 $emit-subx-cleanup-and-unconditional-nonlocal-branch:end:
    27426     # . restore registers
    27427     59/pop-to-ecx
    27428     58/pop-to-eax
    27429     # . epilogue
    27430     89/<- %esp 5/r32/ebp
    27431     5d/pop-to-ebp
    27432     c3/return
    27433
    27434 emit-outputs:  # out: (addr buffered-file), return-stmt: (addr stmt1), fn: (addr function)
    27435     # . prologue
    27436     55/push-ebp
    27437     89/<- %ebp 4/r32/esp
    27438     # . save registers
    27439     50/push-eax
    27440     51/push-ecx
    27441     56/push-esi
    27442     57/push-edi
    27443     # var curr-inout/esi: (addr stmt-var) = return-stmt->inouts
    27444     8b/-> *(ebp+0xc) 0/r32/eax
    27445     (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    27446     89/<- %esi 0/r32/eax
    27447     # var curr-output/edi: (addr list var) = fn->outputs
    27448     8b/-> *(ebp+0x10) 0/r32/eax
    27449     (lookup *(eax+0x10) *(eax+0x14))  # Function-outputs Function-outputs => eax
    27450     89/<- %edi 0/r32/eax
    27451     {
    27452 $emit-outputs:loop:
    27453       81 7/subop/compare %esi 0/imm32
    27454       0f 84/jump-if-= break/disp32
    27455       # emit copy to output register
    27456       # var curr-output-register/ecx: (addr array byte) = curr-output->value->register
    27457       (lookup *edi *(edi+4))  # List-value List-value => eax
    27458       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    27459       89/<- %ecx 0/r32/eax
    27460       # if curr-output-register starts with "x", emit a floating-point copy
    27461       8a/copy-byte *(ecx+4) 0/r32/AL
    27462       25/and-eax-with 0xff/imm32
    27463       3d/compare-eax-and 0x78/imm32/x
    27464       {
    27465         75/jump-if-!= break/disp8
    27466         (emit-float-output *(ebp+8) %esi %ecx)
    27467         eb/jump $emit-outputs:continue/disp8
    27468       }
    27469       # otherwise emit an int copy
    27470       (emit-int-output *(ebp+8) %esi %ecx)
    27471 $emit-outputs:continue:
    27472       # curr-inout = curr-inout->next
    27473       (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
    27474       89/<- %esi 0/r32/eax
    27475       # curr-output = curr-output->next
    27476       (lookup *(edi+8) *(edi+0xc))  # List-next List-next => eax
    27477       89/<- %edi 0/r32/eax
    27478       #
    27479       e9/jump loop/disp32
    27480     }
    27481 $emit-outputs:end:
    27482     # . restore registers
    27483     5f/pop-to-edi
    27484     5e/pop-to-esi
    27485     59/pop-to-ecx
    27486     58/pop-to-eax
    27487     # . epilogue
    27488     89/<- %esp 5/r32/ebp
    27489     5d/pop-to-ebp
    27490     c3/return
    27491
    27492 emit-int-output:  # out: (addr buffered-file), return-var: (addr stmt-var), dest-reg: (addr array byte)
    27493     # . prologue
    27494     55/push-ebp
    27495     89/<- %ebp 4/r32/esp
    27496     # . save registers
    27497     50/push-eax
    27498     51/push-ecx
    27499     # ecx = return-var->value
    27500     8b/-> *(ebp+0xc) 0/r32/eax
    27501     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    27502     89/<- %ecx 0/r32/eax
    27503     # if curr-var is a literal, emit copy of a literal to the output
    27504     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
    27505     (simple-mu-type? %eax 0)  # literal => eax
    27506     {
    27507       3d/compare-eax-and 0/imm32/false
    27508       0f 84/jump-if-= break/disp32
    27509       (emit-indent *(ebp+8) *Curr-block-depth)
    27510       (write-buffered *(ebp+8) "c7 0/subop/copy %")
    27511       (write-buffered *(ebp+8) *(ebp+0x10))
    27512       (write-buffered *(ebp+8) " ")
    27513       (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    27514       (write-buffered *(ebp+8) %eax)
    27515       (write-buffered *(ebp+8) "/imm32\n")
    27516       e9/jump $emit-int-output:end/disp32
    27517     }
    27518     # otherwise emit an integer copy
    27519     (emit-indent *(ebp+8) *Curr-block-depth)
    27520     (write-buffered *(ebp+8) "8b/->")
    27521     (emit-subx-var-as-rm32 *(ebp+8) *(ebp+0xc))
    27522     (write-buffered *(ebp+8) " ")
    27523     (get Mu-registers *(ebp+0x10) 0xc "Mu-registers")  # => eax
    27524     (write-int32-hex-buffered *(ebp+8) *eax)
    27525     (write-buffered *(ebp+8) "/r32\n")
    27526 $emit-int-output:end:
    27527     # . restore registers
    27528     59/pop-to-ecx
    27529     58/pop-to-eax
    27530     # . epilogue
    27531     89/<- %esp 5/r32/ebp
    27532     5d/pop-to-ebp
    27533     c3/return
    27534
    27535 emit-float-output:  # out: (addr buffered-file), return-var: (addr stmt-var), dest-reg: (addr array byte)
    27536     # . prologue
    27537     55/push-ebp
    27538     89/<- %ebp 4/r32/esp
    27539     # . save registers
    27540     50/push-eax
    27541     #
    27542     (emit-indent *(ebp+8) *Curr-block-depth)
    27543     (write-buffered *(ebp+8) "f3 0f 10/->")
    27544     (emit-subx-var-as-rm32 *(ebp+8) *(ebp+0xc))
    27545     (write-buffered *(ebp+8) " ")
    27546     (get Mu-registers *(ebp+0x10) 0xc "Mu-registers")  # => eax
    27547     (write-int32-hex-buffered *(ebp+8) *eax)
    27548     (write-buffered *(ebp+8) "/x32\n")
    27549 $emit-float-output:end:
    27550     # . restore registers
    27551     58/pop-to-eax
    27552     # . epilogue
    27553     89/<- %esp 5/r32/ebp
    27554     5d/pop-to-ebp
    27555     c3/return
    27556
    27557 mu-branch?:  # stmt: (addr stmt1) -> result/eax: boolean
    27558     # . prologue
    27559     55/push-ebp
    27560     89/<- %ebp 4/r32/esp
    27561     # . save registers
    27562     51/push-ecx
    27563     # ecx = lookup(stmt->operation)
    27564     8b/-> *(ebp+8) 1/r32/ecx
    27565     (lookup *(ecx+4) *(ecx+8))  # Stmt1-operation Stmt1-operation => eax
    27566     89/<- %ecx 0/r32/eax
    27567     # if (stmt->operation starts with "loop") return true
    27568     (string-starts-with? %ecx "loop")  # => eax
    27569     3d/compare-eax-and 0/imm32/false
    27570     75/jump-if-not-equal $mu-branch?:end/disp8
    27571     # if (stmt->operation starts with "break") return true
    27572     (string-starts-with? %ecx "break")  # => eax
    27573     3d/compare-eax-and 0/imm32/false
    27574     75/jump-if-not-equal $mu-branch?:end/disp8
    27575     # otherwise return (stmt->operation starts with "return")
    27576     (string-starts-with? %ecx "return")  # => eax
    27577 $mu-branch?:end:
    27578     # . restore registers
    27579     59/pop-to-ecx
    27580     # . epilogue
    27581     89/<- %esp 5/r32/ebp
    27582     5d/pop-to-ebp
    27583     c3/return
    27584
    27585 emit-reverse-break:  # out: (addr buffered-file), stmt: (addr stmt1)
    27586     # . prologue
    27587     55/push-ebp
    27588     89/<- %ebp 4/r32/esp
    27589     # . save registers
    27590     50/push-eax
    27591     # eax = stmt
    27592     8b/-> *(ebp+0xc) 0/r32/eax
    27593     #
    27594     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
    27595     (get Reverse-branch %eax 0x10 "reverse-branch: ")  # => eax: (addr handle array byte)
    27596     (emit-indent *(ebp+8) *Curr-block-depth)
    27597     (lookup *eax *(eax+4))  # => eax
    27598     (write-buffered *(ebp+8) %eax)
    27599     (write-buffered *(ebp+8) " break/disp32\n")
    27600 $emit-reverse-break:end:
    27601     # . restore registers
    27602     58/pop-to-eax
    27603     # . epilogue
    27604     89/<- %esp 5/r32/ebp
    27605     5d/pop-to-ebp
    27606     c3/return
    27607
    27608 == data
    27609
    27610 # Table from Mu branch instructions to the reverse SubX opcodes for them.
    27611 Reverse-branch:  # (table (handle array byte) (handle array byte))
    27612   # a table is a stream
    27613   0x240/imm32/write
    27614   0/imm32/read
    27615   0x240/imm32/size
    27616   # data
    27617   0x11/imm32/alloc-id   _string-break-if-=/imm32                0x11/imm32/alloc-id   _string_0f_85_jump_label/imm32
    27618   0x11/imm32/alloc-id   _string-loop-if-=/imm32                 0x11/imm32/alloc-id   _string_0f_85_jump_label/imm32
    27619   0x11/imm32/alloc-id   _string-break-if-!=/imm32               0x11/imm32/alloc-id   _string_0f_84_jump_label/imm32
    27620   0x11/imm32/alloc-id   _string-loop-if-!=/imm32                0x11/imm32/alloc-id   _string_0f_84_jump_label/imm32
    27621   0x11/imm32/alloc-id   _string-break-if-</imm32                0x11/imm32/alloc-id   _string_0f_8d_jump_label/imm32
    27622   0x11/imm32/alloc-id   _string-loop-if-</imm32                 0x11/imm32/alloc-id   _string_0f_8d_jump_label/imm32
    27623   0x11/imm32/alloc-id   _string-break-if->/imm32                0x11/imm32/alloc-id   _string_0f_8e_jump_label/imm32
    27624   0x11/imm32/alloc-id   _string-loop-if->/imm32                 0x11/imm32/alloc-id   _string_0f_8e_jump_label/imm32
    27625   0x11/imm32/alloc-id   _string-break-if-<=/imm32               0x11/imm32/alloc-id   _string_0f_8f_jump_label/imm32
    27626   0x11/imm32/alloc-id   _string-loop-if-<=/imm32                0x11/imm32/alloc-id   _string_0f_8f_jump_label/imm32
    27627   0x11/imm32/alloc-id   _string-break-if->=/imm32               0x11/imm32/alloc-id   _string_0f_8c_jump_label/imm32
    27628   0x11/imm32/alloc-id   _string-loop-if->=/imm32                0x11/imm32/alloc-id   _string_0f_8c_jump_label/imm32
    27629   0x11/imm32/alloc-id   _string-break-if-addr</imm32            0x11/imm32/alloc-id   _string_0f_83_jump_label/imm32
    27630   0x11/imm32/alloc-id   _string-loop-if-addr</imm32             0x11/imm32/alloc-id   _string_0f_83_jump_label/imm32
    27631   0x11/imm32/alloc-id   _string-break-if-addr>/imm32            0x11/imm32/alloc-id   _string_0f_86_jump_label/imm32
    27632   0x11/imm32/alloc-id   _string-loop-if-addr>/imm32             0x11/imm32/alloc-id   _string_0f_86_jump_label/imm32
    27633   0x11/imm32/alloc-id   _string-break-if-addr<=/imm32           0x11/imm32/alloc-id   _string_0f_87_jump_label/imm32
    27634   0x11/imm32/alloc-id   _string-loop-if-addr<=/imm32            0x11/imm32/alloc-id   _string_0f_87_jump_label/imm32
    27635   0x11/imm32/alloc-id   _string-break-if-addr>=/imm32           0x11/imm32/alloc-id   _string_0f_82_jump_label/imm32
    27636   0x11/imm32/alloc-id   _string-loop-if-addr>=/imm32            0x11/imm32/alloc-id   _string_0f_82_jump_label/imm32
    27637   0x11/imm32/alloc-id   _string-break-if-float</imm32           0x11/imm32/alloc-id   _string_0f_83_jump_label/imm32
    27638   0x11/imm32/alloc-id   _string-loop-if-float</imm32            0x11/imm32/alloc-id   _string_0f_83_jump_label/imm32
    27639   0x11/imm32/alloc-id   _string-break-if-float>/imm32           0x11/imm32/alloc-id   _string_0f_86_jump_label/imm32
    27640   0x11/imm32/alloc-id   _string-loop-if-float>/imm32            0x11/imm32/alloc-id   _string_0f_86_jump_label/imm32
    27641   0x11/imm32/alloc-id   _string-break-if-float<=/imm32          0x11/imm32/alloc-id   _string_0f_87_jump_label/imm32
    27642   0x11/imm32/alloc-id   _string-loop-if-float<=/imm32           0x11/imm32/alloc-id   _string_0f_87_jump_label/imm32
    27643   0x11/imm32/alloc-id   _string-break-if-float>=/imm32          0x11/imm32/alloc-id   _string_0f_82_jump_label/imm32
    27644   0x11/imm32/alloc-id   _string-loop-if-float>=/imm32           0x11/imm32/alloc-id   _string_0f_82_jump_label/imm32
    27645   0x11/imm32/alloc-id   _string-break-if-carry/imm32            0x11/imm32/alloc-id   _string_0f_83_jump_label/imm32
    27646   0x11/imm32/alloc-id   _string-loop-if-carry/imm32             0x11/imm32/alloc-id   _string_0f_83_jump_label/imm32
    27647   0x11/imm32/alloc-id   _string-break-if-not-carry/imm32        0x11/imm32/alloc-id   _string_0f_82_jump_label/imm32
    27648   0x11/imm32/alloc-id   _string-loop-if-not-carry/imm32         0x11/imm32/alloc-id   _string_0f_82_jump_label/imm32
    27649   0x11/imm32/alloc-id   _string-break-if-overflow/imm32         0x11/imm32/alloc-id   _string_0f_81_jump_label/imm32
    27650   0x11/imm32/alloc-id   _string-loop-if-overflow/imm32          0x11/imm32/alloc-id   _string_0f_81_jump_label/imm32
    27651   0x11/imm32/alloc-id   _string-break-if-not-overflow/imm32     0x11/imm32/alloc-id   _string_0f_80_jump_label/imm32
    27652   0x11/imm32/alloc-id   _string-loop-if-not-overflow/imm32      0x11/imm32/alloc-id   _string_0f_80_jump_label/imm32
    27653
    27654 == code
    27655
    27656 emit-unconditional-jump-to-depth:  # out: (addr buffered-file), vars: (addr stack live-var), depth: int, label-suffix: (addr array byte)
    27657     # . prologue
    27658     55/push-ebp
    27659     89/<- %ebp 4/r32/esp
    27660     # . save registers
    27661     50/push-eax
    27662     51/push-ecx
    27663     52/push-edx
    27664     53/push-ebx
    27665     56/push-esi
    27666     # ecx = vars
    27667     8b/-> *(ebp+0xc) 1/r32/ecx
    27668     # var eax: int = vars->top
    27669     8b/-> *ecx 0/r32/eax
    27670     # var curr/esi: (addr handle var) = &vars->data[vars->top - 12]
    27671     8d/copy-address *(ecx+eax-4) 6/r32/esi  # vars + 8 + vars->top - 12/Live-var-size
    27672     # var min/ecx: (addr handle var) = vars->data
    27673     8d/copy-address *(ecx+8) 1/r32/ecx
    27674     # edx = depth
    27675     8b/-> *(ebp+0x10) 2/r32/edx
    27676     {
    27677 $emit-unconditional-jump-to-depth:loop:
    27678       # if (curr < min) break
    27679       39/compare %esi 1/r32/ecx
    27680       0f 82/jump-if-addr< break/disp32
    27681       # var v/ebx: (addr var) = lookup(*curr)
    27682       (lookup *esi *(esi+4))  # => eax
    27683       89/<- %ebx 0/r32/eax
    27684       # if (v->block-depth < until-block-depth) break
    27685       39/compare *(ebx+0x10) 2/r32/edx  # Var-block-depth
    27686       0f 8c/jump-if-< break/disp32
    27687       {
    27688 $emit-unconditional-jump-to-depth:check:
    27689         # if v->block-depth != until-block-depth, continue
    27690         39/compare *(ebx+0x10) 2/r32/edx  # Var-block-depth
    27691         0f 85/jump-if-!= break/disp32
    27692 $emit-unconditional-jump-to-depth:depth-found:
    27693         # if v is not a literal, continue
    27694         (size-of %ebx)  # => eax
    27695         3d/compare-eax-and 0/imm32
    27696         0f 85/jump-if-!= break/disp32
    27697 $emit-unconditional-jump-to-depth:label-found:
    27698         # emit unconditional jump, then return
    27699         (emit-indent *(ebp+8) *Curr-block-depth)
    27700         (write-buffered *(ebp+8) "e9/jump ")
    27701         (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
    27702         (write-buffered *(ebp+8) %eax)
    27703         (write-buffered *(ebp+8) ":")
    27704         (write-buffered *(ebp+8) *(ebp+0x14))
    27705         (write-buffered *(ebp+8) "/disp32\n")
    27706         eb/jump $emit-unconditional-jump-to-depth:end/disp8
    27707       }
    27708       # curr -= 12
    27709       81 5/subop/subtract %esi 0xc/imm32
    27710       e9/jump loop/disp32
    27711     }
    27712     # TODO: error if no label at 'depth' was found
    27713 $emit-unconditional-jump-to-depth:end:
    27714     # . restore registers
    27715     5e/pop-to-esi
    27716     5b/pop-to-ebx
    27717     5a/pop-to-edx
    27718     59/pop-to-ecx
    27719     58/pop-to-eax
    27720     # . epilogue
    27721     89/<- %esp 5/r32/ebp
    27722     5d/pop-to-ebp
    27723     c3/return
    27724
    27725 # emit clean-up code for 'vars' until some block depth
    27726 # doesn't actually modify 'vars' so we need traverse manually inside the stack
    27727 emit-cleanup-code-until-depth:  # out: (addr buffered-file), vars: (addr stack live-var), until-block-depth: int
    27728     # . prologue
    27729     55/push-ebp
    27730     89/<- %ebp 4/r32/esp
    27731     # . save registers
    27732     50/push-eax
    27733     51/push-ecx
    27734     52/push-edx
    27735     53/push-ebx
    27736     56/push-esi
    27737 #?     (write-buffered Stderr "--- cleanup\n")
    27738 #?     (flush Stderr)
    27739     # ecx = vars
    27740     8b/-> *(ebp+0xc) 1/r32/ecx
    27741     # var esi: int = vars->top
    27742     8b/-> *ecx 6/r32/esi
    27743     # var curr/esi: (addr handle var) = &vars->data[vars->top - 12]
    27744     8d/copy-address *(ecx+esi-4) 6/r32/esi  # vars + 8 + vars->top - 12/Live-var-size
    27745     # var min/ecx: (addr handle var) = vars->data
    27746     81 0/subop/add %ecx 8/imm32
    27747     # edx = until-block-depth
    27748     8b/-> *(ebp+0x10) 2/r32/edx
    27749     {
    27750 $emit-cleanup-code-until-depth:loop:
    27751       # if (curr < min) break
    27752       39/compare %esi 1/r32/ecx
    27753       0f 82/jump-if-addr< break/disp32
    27754       # var v/ebx: (addr var) = lookup(*curr)
    27755       (lookup *esi *(esi+4))  # => eax
    27756       89/<- %ebx 0/r32/eax
    27757 #?       (lookup *ebx *(ebx+4))  # Var-name
    27758 #?       (write-buffered Stderr "var ")
    27759 #?       (write-buffered Stderr %eax)
    27760 #?       (write-buffered Stderr Newline)
    27761 #?       (flush Stderr)
    27762       # if (v->block-depth < until-block-depth) break
    27763       39/compare *(ebx+0x10) 2/r32/edx  # Var-block-depth
    27764       0f 8c/jump-if-< break/disp32
    27765       # if v is in a register
    27766       81 7/subop/compare *(ebx+0x18) 0/imm32  # Var-register
    27767       {
    27768         0f 84/jump-if-= break/disp32
    27769         {
    27770 $emit-cleanup-code-until-depth:check-for-previous-spill:
    27771           8b/-> *(esi+8) 0/r32/eax  # Live-var-register-spilled
    27772           3d/compare-eax-and 0/imm32/false
    27773           74/jump-if-= break/disp8
    27774 $emit-cleanup-code-until-depth:reclaim-var-in-register:
    27775           (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
    27776           (emit-pop-register *(ebp+8) %eax)
    27777         }
    27778         eb/jump $emit-cleanup-code-until-depth:continue/disp8
    27779       }
    27780       # otherwise v is on the stack
    27781       {
    27782         75/jump-if-!= break/disp8
    27783 $emit-cleanup-code-until-depth:var-on-stack:
    27784         (size-of %ebx)  # => eax
    27785         # don't emit code for labels
    27786         3d/compare-eax-and 0/imm32
    27787         74/jump-if-= break/disp8
    27788 $emit-cleanup-code-until-depth:reclaim-var-on-stack:
    27789         (emit-indent *(ebp+8) *Curr-block-depth)
    27790         (write-buffered *(ebp+8) "81 0/subop/add %esp ")
    27791         (write-int32-hex-buffered *(ebp+8) %eax)
    27792         (write-buffered *(ebp+8) "/imm32\n")
    27793       }
    27794 $emit-cleanup-code-until-depth:continue:
    27795       # curr -= 12
    27796       81 5/subop/subtract %esi 0xc/imm32
    27797       e9/jump loop/disp32
    27798     }
    27799 $emit-cleanup-code-until-depth:end:
    27800     # . restore registers
    27801     5e/pop-to-esi
    27802     5b/pop-to-ebx
    27803     5a/pop-to-edx
    27804     59/pop-to-ecx
    27805     58/pop-to-eax
    27806     # . epilogue
    27807     89/<- %esp 5/r32/ebp
    27808     5d/pop-to-ebp
    27809     c3/return
    27810
    27811 # emit clean-up code for 'vars' that don't conflict with output registers
    27812 # doesn't actually modify 'vars' so we need traverse manually inside the stack
    27813 emit-cleanup-code-for-non-outputs:  # out: (addr buffered-file), vars: (addr stack live-var), fn: (addr function)
    27814     # . prologue
    27815     55/push-ebp
    27816     89/<- %ebp 4/r32/esp
    27817     # . save registers
    27818     50/push-eax
    27819     51/push-ecx
    27820     52/push-edx
    27821     53/push-ebx
    27822     56/push-esi
    27823     57/push-edi
    27824     # ecx = vars
    27825     8b/-> *(ebp+0xc) 1/r32/ecx
    27826     # var esi: int = vars->top
    27827     8b/-> *ecx 6/r32/esi
    27828     # var curr/esi: (addr handle var) = &vars->data[vars->top - 12]
    27829     8d/copy-address *(ecx+esi-4) 6/r32/esi  # vars + 8 + vars->top - 12/Live-var-size
    27830     # var min/ecx: (addr handle var) = vars->data
    27831     81 0/subop/add %ecx 8/imm32
    27832     {
    27833 $emit-cleanup-code-for-non-outputs:loop:
    27834       # if (curr < min) break
    27835       39/compare %esi 1/r32/ecx
    27836       0f 82/jump-if-addr< break/disp32
    27837       # var v/ebx: (addr var) = lookup(*curr)
    27838       (lookup *esi *(esi+4))  # => eax
    27839       89/<- %ebx 0/r32/eax
    27840       # if v is in a register
    27841       81 7/subop/compare *(ebx+0x18) 0/imm32  # Var-register
    27842       {
    27843         0f 84/jump-if-= break/disp32
    27844         {
    27845 $emit-cleanup-code-for-non-outputs:check-for-previous-spill:
    27846           8b/-> *(esi+8) 0/r32/eax  # Live-var-register-spilled
    27847           3d/compare-eax-and 0/imm32/false
    27848           0f 84/jump-if-= break/disp32
    27849 $emit-cleanup-code-for-non-outputs:reclaim-var-in-register:
    27850           # var reg/edi: (addr array name) = v->register
    27851           (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
    27852           89/<- %edi 0/r32/eax
    27853           # if reg is not in function outputs, emit a pop
    27854           (reg-in-function-outputs? *(ebp+0x10) %edi)  # => eax
    27855           3d/compare-eax-and 0/imm32/false
    27856           {
    27857             75/jump-if-!= break/disp8
    27858             (emit-pop-register *(ebp+8) %edi)
    27859             eb/jump $emit-cleanup-code-for-non-outputs:reclaim-var-in-register-done/disp8
    27860           }
    27861           # otherwise just drop it from the stack
    27862           (emit-indent *(ebp+8) *Curr-block-depth)
    27863           (write-buffered *(ebp+8) "81 0/subop/add %esp 4/imm32\n")
    27864         }
    27865 $emit-cleanup-code-for-non-outputs:reclaim-var-in-register-done:
    27866         eb/jump $emit-cleanup-code-for-non-outputs:continue/disp8
    27867       }
    27868       # otherwise v is on the stack
    27869       {
    27870         75/jump-if-!= break/disp8
    27871 $emit-cleanup-code-for-non-outputs:var-on-stack:
    27872         (size-of %ebx)  # => eax
    27873         # don't emit code for labels
    27874         3d/compare-eax-and 0/imm32
    27875         74/jump-if-= break/disp8
    27876 $emit-cleanup-code-for-non-outputs:reclaim-var-on-stack:
    27877         (emit-indent *(ebp+8) *Curr-block-depth)
    27878         (write-buffered *(ebp+8) "81 0/subop/add %esp ")
    27879         (write-int32-hex-buffered *(ebp+8) %eax)
    27880         (write-buffered *(ebp+8) "/imm32\n")
    27881       }
    27882 $emit-cleanup-code-for-non-outputs:continue:
    27883       # curr -= 12
    27884       81 5/subop/subtract %esi 0xc/imm32
    27885       e9/jump loop/disp32
    27886     }
    27887 $emit-cleanup-code-for-non-outputs:end:
    27888     # . restore registers
    27889     5f/pop-to-edi
    27890     5e/pop-to-esi
    27891     5b/pop-to-ebx
    27892     5a/pop-to-edx
    27893     59/pop-to-ecx
    27894     58/pop-to-eax
    27895     # . epilogue
    27896     89/<- %esp 5/r32/ebp
    27897     5d/pop-to-ebp
    27898     c3/return
    27899
    27900 emit-push-register:  # out: (addr buffered-file), reg: (addr array byte)
    27901     # . prologue
    27902     55/push-ebp
    27903     89/<- %ebp 4/r32/esp
    27904     # eax = reg
    27905     8b/-> *(ebp+0xc) 0/r32/eax
    27906     # var prefix/eax: byte = reg->data[0]
    27907     8a/copy-byte *(eax+4) 0/r32/AL
    27908     25/and-eax-with 0xff/imm32
    27909     # if (prefix == 'x') push xmm register
    27910     {
    27911       3d/compare-eax-and 0x78/imm32/x
    27912       0f 85/jump-if-!= break/disp32
    27913       # TODO validate register
    27914       (emit-indent *(ebp+8) *Curr-block-depth)
    27915       (write-buffered *(ebp+8) "81 5/subop/subtract %esp 4/imm32\n")
    27916       (emit-indent *(ebp+8) *Curr-block-depth)
    27917       (write-buffered *(ebp+8) "f3 0f 11/<- *esp ")
    27918       # var prefix/eax: byte = reg->data[3]
    27919       8b/-> *(ebp+0xc) 0/r32/eax
    27920       8a/copy-byte *(eax+7) 0/r32/AL
    27921       25/and-eax-with 0xff/imm32
    27922       (write-byte-buffered *(ebp+8) %eax)
    27923       (write-buffered *(ebp+8) "/x32\n")
    27924       e9/jump $emit-push-register:end/disp32
    27925     }
    27926     # otherwise push gp register
    27927     (emit-indent *(ebp+8) *Curr-block-depth)
    27928     (write-buffered *(ebp+8) "ff 6/subop/push %")
    27929     (write-buffered *(ebp+8) *(ebp+0xc))
    27930     (write-buffered *(ebp+8) Newline)
    27931 $emit-push-register:end:
    27932     # . epilogue
    27933     89/<- %esp 5/r32/ebp
    27934     5d/pop-to-ebp
    27935     c3/return
    27936
    27937 emit-pop-register:  # out: (addr buffered-file), reg: (addr array byte)
    27938     # . prologue
    27939     55/push-ebp
    27940     89/<- %ebp 4/r32/esp
    27941     # . save registers
    27942     50/push-eax
    27943     # eax = reg
    27944     8b/-> *(ebp+0xc) 0/r32/eax
    27945     # var prefix/eax: byte = reg->data[0]
    27946     8a/copy-byte *(eax+4) 0/r32/AL
    27947     25/and-eax-with 0xff/imm32
    27948     # if (prefix == 'x') pop to xmm register
    27949     {
    27950       3d/compare-eax-and 0x78/imm32/x
    27951       0f 85/jump-if-!= break/disp32
    27952       # TODO validate register
    27953       (emit-indent *(ebp+8) *Curr-block-depth)
    27954       (write-buffered *(ebp+8) "f3 0f 10/-> *esp ")
    27955       # var prefix/eax: byte = reg->data[3]
    27956       8b/-> *(ebp+0xc) 0/r32/eax
    27957       8a/copy-byte *(eax+7) 0/r32/AL
    27958       25/and-eax-with 0xff/imm32
    27959       (write-byte-buffered *(ebp+8) %eax)
    27960       (write-buffered *(ebp+8) "/x32\n")
    27961       (emit-indent *(ebp+8) *Curr-block-depth)
    27962       (write-buffered *(ebp+8) "81 0/subop/add %esp 4/imm32\n")
    27963       e9/jump $emit-pop-register:end/disp32
    27964     }
    27965     # otherwise pop to gp register
    27966     (emit-indent *(ebp+8) *Curr-block-depth)
    27967     (write-buffered *(ebp+8) "8f 0/subop/pop %")
    27968     (write-buffered *(ebp+8) *(ebp+0xc))
    27969     (write-buffered *(ebp+8) Newline)
    27970 $emit-pop-register:end:
    27971     # . restore registers
    27972     58/pop-to-eax
    27973     # . epilogue
    27974     89/<- %esp 5/r32/ebp
    27975     5d/pop-to-ebp
    27976     c3/return
    27977
    27978 # emit clean-up code for 'vars' until a given label is encountered
    27979 # doesn't actually modify 'vars' so we need traverse manually inside the stack
    27980 emit-cleanup-code-until-target:  # out: (addr buffered-file), vars: (addr stack live-var), until-block-label: (addr array byte)
    27981     # . prologue
    27982     55/push-ebp
    27983     89/<- %ebp 4/r32/esp
    27984     # . save registers
    27985     50/push-eax
    27986     51/push-ecx
    27987     52/push-edx
    27988     53/push-ebx
    27989     # ecx = vars
    27990     8b/-> *(ebp+0xc) 1/r32/ecx
    27991     # var eax: int = vars->top
    27992     8b/-> *ecx 0/r32/eax
    27993     # var curr/edx: (addr handle var) = &vars->data[vars->top - 12]
    27994     8d/copy-address *(ecx+eax-4) 2/r32/edx  # vars + 8 + vars->top - 12/Live-var-size
    27995     # var min/ecx: (addr handle var) = vars->data
    27996     81 0/subop/add %ecx 8/imm32
    27997     {
    27998 $emit-cleanup-code-until-target:loop:
    27999       # if (curr < min) break
    28000       39/compare %edx 1/r32/ecx
    28001       0f 82/jump-if-addr< break/disp32
    28002       # var v/ebx: (handle var) = lookup(*curr)
    28003       (lookup *edx *(edx+4))  # => eax
    28004       89/<- %ebx 0/r32/eax
    28005       # if (v->name == until-block-label) break
    28006       (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
    28007       (string-equal? %eax *(ebp+0x10))  # => eax
    28008       3d/compare-eax-and 0/imm32/false
    28009       0f 85/jump-if-!= break/disp32
    28010       # if v is in a register
    28011       81 7/subop/compare *(ebx+0x18) 0/imm32  # Var-register
    28012       {
    28013         0f 84/jump-if-= break/disp32
    28014         {
    28015 $emit-cleanup-code-until-target:check-for-previous-spill:
    28016           8b/-> *(edx+8) 0/r32/eax  # Live-var-register-spilled
    28017           3d/compare-eax-and 0/imm32/false
    28018           74/jump-if-= break/disp8
    28019 $emit-cleanup-code-until-target:reclaim-var-in-register:
    28020           (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
    28021           (emit-pop-register *(ebp+8) %eax)
    28022         }
    28023         eb/jump $emit-cleanup-code-until-target:continue/disp8
    28024       }
    28025       # otherwise v is on the stack
    28026       {
    28027         75/jump-if-!= break/disp8
    28028 $emit-cleanup-code-until-target:reclaim-var-on-stack:
    28029         (size-of %ebx)  # => eax
    28030         # don't emit code for labels
    28031         3d/compare-eax-and 0/imm32
    28032         74/jump-if-= break/disp8
    28033         #
    28034         (emit-indent *(ebp+8) *Curr-block-depth)
    28035         (write-buffered *(ebp+8) "81 0/subop/add %esp ")
    28036         (write-int32-hex-buffered *(ebp+8) %eax)
    28037         (write-buffered *(ebp+8) "/imm32\n")
    28038       }
    28039 $emit-cleanup-code-until-target:continue:
    28040       # curr -= 12
    28041       81 5/subop/subtract %edx 0xc/imm32
    28042       e9/jump loop/disp32
    28043     }
    28044 $emit-cleanup-code-until-target:end:
    28045     # . restore registers
    28046     5b/pop-to-ebx
    28047     5a/pop-to-edx
    28048     59/pop-to-ecx
    28049     58/pop-to-eax
    28050     # . epilogue
    28051     89/<- %esp 5/r32/ebp
    28052     5d/pop-to-ebp
    28053     c3/return
    28054
    28055 # update Curr-local-stack-offset assuming vars until some block depth are popped
    28056 # doesn't actually modify 'vars', so we need traverse manually inside the stack
    28057 clean-up-stack-offset-state:  # vars: (addr stack live-var), until-block-depth: int
    28058     # . prologue
    28059     55/push-ebp
    28060     89/<- %ebp 4/r32/esp
    28061     # . save registers
    28062     50/push-eax
    28063     51/push-ecx
    28064     52/push-edx
    28065     53/push-ebx
    28066     56/push-esi
    28067     # ecx = vars
    28068     8b/-> *(ebp+8) 1/r32/ecx
    28069     # var esi: int = vars->top
    28070     8b/-> *ecx 6/r32/esi
    28071     # var curr/esi: (addr handle var) = &vars->data[vars->top - 12]
    28072     8d/copy-address *(ecx+esi-4) 6/r32/esi  # vars + 8 + vars->top - 12/Live-var-size
    28073     # var min/ecx: (addr handle var) = vars->data
    28074     81 0/subop/add %ecx 8/imm32
    28075     # edx = until-block-depth
    28076     8b/-> *(ebp+0xc) 2/r32/edx
    28077     {
    28078 $clean-up-stack-offset-state:loop:
    28079       # if (curr < min) break
    28080       39/compare %esi 1/r32/ecx
    28081       0f 82/jump-if-addr< break/disp32
    28082       # var v/ebx: (addr var) = lookup(*curr)
    28083       (lookup *esi *(esi+4))  # => eax
    28084       89/<- %ebx 0/r32/eax
    28085       # if (v->block-depth < until-block-depth) break
    28086       39/compare *(ebx+0x10) 2/r32/edx  # Var-block-depth
    28087       0f 8c/jump-if-< break/disp32
    28088       # if v is in a register
    28089       81 7/subop/compare *(ebx+0x18) 0/imm32  # Var-register
    28090       {
    28091         0f 84/jump-if-= break/disp32
    28092         {
    28093 $clean-up-stack-offset-state:check-for-previous-spill:
    28094           8b/-> *(esi+8) 0/r32/eax  # Live-var-register-spilled
    28095           3d/compare-eax-and 0/imm32/false
    28096           74/jump-if-= break/disp8
    28097 $clean-up-stack-offset-state:reclaim-var-in-register:
    28098           81 0/subop/add *Curr-local-stack-offset 4/imm32
    28099         }
    28100         eb/jump $clean-up-stack-offset-state:continue/disp8
    28101       }
    28102       # otherwise v is on the stack
    28103       {
    28104         75/jump-if-!= break/disp8
    28105 $clean-up-stack-offset-state:var-on-stack:
    28106         (size-of %ebx)  # => eax
    28107         01/add-to *Curr-local-stack-offset 0/r32/eax
    28108       }
    28109 $clean-up-stack-offset-state:continue:
    28110       # curr -= 12
    28111       81 5/subop/subtract %esi 0xc/imm32
    28112       e9/jump loop/disp32
    28113     }
    28114 $clean-up-stack-offset-state:end:
    28115     # . restore registers
    28116     5e/pop-to-esi
    28117     5b/pop-to-ebx
    28118     5a/pop-to-edx
    28119     59/pop-to-ecx
    28120     58/pop-to-eax
    28121     # . epilogue
    28122     89/<- %esp 5/r32/ebp
    28123     5d/pop-to-ebp
    28124     c3/return
    28125
    28126 # Return true if there isn't a variable in 'vars' with the same block-depth
    28127 # and register as 'v'.
    28128 # 'v' is guaranteed not to be within 'vars'.
    28129 not-yet-spilled-this-block?:  # v: (addr var), vars: (addr stack live-var) -> result/eax: boolean
    28130     # . prologue
    28131     55/push-ebp
    28132     89/<- %ebp 4/r32/esp
    28133     # . save registers
    28134     51/push-ecx
    28135     52/push-edx
    28136     53/push-ebx
    28137     56/push-esi
    28138     57/push-edi
    28139     # ecx = vars
    28140     8b/-> *(ebp+0xc) 1/r32/ecx
    28141     # var eax: int = vars->top
    28142     8b/-> *ecx 0/r32/eax
    28143     # var curr/edx: (addr handle var) = &vars->data[vars->top - 12]
    28144     8d/copy-address *(ecx+eax-4) 2/r32/edx  # vars + 8 + vars->top - 12/Live-var-size
    28145     # var min/ecx: (addr handle var) = vars->data
    28146     8d/copy-address *(ecx+8) 1/r32/ecx
    28147     # var depth/ebx: int = v->block-depth
    28148     8b/-> *(ebp+8) 3/r32/ebx
    28149     8b/-> *(ebx+0x10) 3/r32/ebx  # Var-block-depth
    28150     # var needle/esi: (addr array byte) = v->register
    28151     8b/-> *(ebp+8) 6/r32/esi
    28152     (lookup *(esi+0x18) *(esi+0x1c))  # Var-register Var-register => eax
    28153     89/<- %esi 0/r32/eax
    28154     {
    28155 $not-yet-spilled-this-block?:loop:
    28156       # if (curr < min) break
    28157       39/compare %edx 1/r32/ecx
    28158       0f 82/jump-if-addr< break/disp32
    28159       # var cand/edi: (addr var) = lookup(*curr)
    28160       (lookup *edx *(edx+4))  # => eax
    28161       89/<- %edi 0/r32/eax
    28162       # if (cand->block-depth < depth) break
    28163       39/compare *(edi+0x10) 3/r32/ebx  # Var-block-depth
    28164       0f 8c/jump-if-< break/disp32
    28165       # var cand-reg/edi: (array array byte) = cand->reg
    28166       (lookup *(edi+0x18) *(edi+0x1c))  # Var-register Var-register => eax
    28167       89/<- %edi 0/r32/eax
    28168       # if (cand-reg == null) continue
    28169       {
    28170 $not-yet-spilled-this-block?:check-reg:
    28171         81 7/subop/compare %edi 0/imm32
    28172         0f 84/jump-if-= break/disp32
    28173         # if (cand-reg == needle) return true
    28174         (string-equal? %esi %edi)  # => eax
    28175         3d/compare-eax-and 0/imm32/false
    28176         74/jump-if-= break/disp8
    28177 $not-yet-spilled-this-block?:return-false:
    28178         b8/copy-to-eax 0/imm32/false
    28179         eb/jump $not-yet-spilled-this-block?:end/disp8
    28180       }
    28181 $not-yet-spilled-this-block?:continue:
    28182       # curr -= 12
    28183       81 5/subop/subtract %edx 0xc/imm32
    28184       e9/jump loop/disp32
    28185     }
    28186 $not-yet-spilled-this-block?:return-true:
    28187     # return true
    28188     b8/copy-to-eax 1/imm32/true
    28189 $not-yet-spilled-this-block?:end:
    28190     # . restore registers
    28191     5f/pop-to-edi
    28192     5e/pop-to-esi
    28193     5b/pop-to-ebx
    28194     5a/pop-to-edx
    28195     59/pop-to-ecx
    28196     # . epilogue
    28197     89/<- %esp 5/r32/ebp
    28198     5d/pop-to-ebp
    28199     c3/return
    28200
    28201 # could the register of 'v' ever be written to by one of the vars in fn-outputs?
    28202 will-not-write-some-register?:  # v: (addr var), stmts: (addr list stmt), fn: (addr function) -> result/eax: boolean
    28203     # . prologue
    28204     55/push-ebp
    28205     89/<- %ebp 4/r32/esp
    28206     # eax = v
    28207     8b/-> *(ebp+8) 0/r32/eax
    28208     # var reg/eax: (addr array byte) = lookup(v->register)
    28209     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    28210     # var target/eax: (addr var) = find-register(fn-outputs, reg)
    28211     (find-register *(ebp+0x10) %eax)  # => eax
    28212     # if (target == 0) return true
    28213     {
    28214       3d/compare-eax-and 0/imm32
    28215       75/jump-if-!= break/disp8
    28216       b8/copy-to-eax 1/imm32/true
    28217       eb/jump $will-not-write-some-register?:end/disp8
    28218     }
    28219     # return !assigns-in-stmts?(stmts, target)
    28220     (assigns-in-stmts? *(ebp+0xc) %eax)  # => eax
    28221     3d/compare-eax-and 0/imm32/false
    28222     # assume: true = 1, so no need to mask with 0x000000ff
    28223     0f 94/set-if-= %al
    28224 $will-not-write-some-register?:end:
    28225     # . epilogue
    28226     89/<- %esp 5/r32/ebp
    28227     5d/pop-to-ebp
    28228     c3/return
    28229
    28230 # return fn output with matching register
    28231 # always returns false if 'reg' is null
    28232 find-register:  # fn: (addr function), reg: (addr array byte) -> result/eax: (addr var)
    28233     # . prologue
    28234     55/push-ebp
    28235     89/<- %ebp 4/r32/esp
    28236     # . save registers
    28237     51/push-ecx
    28238     # var curr/ecx: (addr list var) = lookup(fn->outputs)
    28239     8b/-> *(ebp+8) 1/r32/ecx
    28240     (lookup *(ecx+0x10) *(ecx+0x14))  # Function-outputs Function-outputs => eax
    28241     89/<- %ecx 0/r32/eax
    28242     {
    28243 $find-register:loop:
    28244       # if (curr == 0) break
    28245       81 7/subop/compare %ecx 0/imm32
    28246       74/jump-if-= break/disp8
    28247       # eax = curr->value->register
    28248       (lookup *ecx *(ecx+4))  # List-value List-value => eax
    28249       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    28250       # if (eax == reg) return curr->value
    28251 $find-register:compare:
    28252       (string-equal? *(ebp+0xc) %eax)  # => eax
    28253       {
    28254         3d/compare-eax-and 0/imm32/false
    28255         74/jump-if-= break/disp8
    28256 $find-register:found:
    28257         (lookup *ecx *(ecx+4))  # List-value List-value => eax
    28258         eb/jump $find-register:end/disp8
    28259       }
    28260       # curr = lookup(curr->next)
    28261       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
    28262       89/<- %ecx 0/r32/eax
    28263       #
    28264       eb/jump loop/disp8
    28265     }
    28266 $find-register:end:
    28267     # . restore registers
    28268     59/pop-to-ecx
    28269     # . epilogue
    28270     89/<- %esp 5/r32/ebp
    28271     5d/pop-to-ebp
    28272     c3/return
    28273
    28274 assigns-in-stmts?:  # stmts: (addr list stmt), v: (addr var) -> result/eax: boolean
    28275     # . prologue
    28276     55/push-ebp
    28277     89/<- %ebp 4/r32/esp
    28278     # . save registers
    28279     51/push-ecx
    28280     # var curr/ecx: (addr list stmt) = stmts
    28281     8b/-> *(ebp+8) 1/r32/ecx
    28282     {
    28283       # if (curr == 0) break
    28284       81 7/subop/compare %ecx 0/imm32
    28285       74/jump-if-= break/disp8
    28286       # if assigns-in-stmt?(curr->value, v) return true
    28287       (lookup *ecx *(ecx+4))  # List-value List-value => eax
    28288       (assigns-in-stmt? %eax *(ebp+0xc))  # => eax
    28289       3d/compare-eax-and 0/imm32/false
    28290       75/jump-if-!= break/disp8
    28291       # curr = lookup(curr->next)
    28292       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
    28293       89/<- %ecx 0/r32/eax
    28294       #
    28295       eb/jump loop/disp8
    28296     }
    28297 $assigns-in-stmts?:end:
    28298     # . restore registers
    28299     59/pop-to-ecx
    28300     # . epilogue
    28301     89/<- %esp 5/r32/ebp
    28302     5d/pop-to-ebp
    28303     c3/return
    28304
    28305 assigns-in-stmt?:  # stmt: (addr stmt), v: (addr var) -> result/eax: boolean
    28306     # . prologue
    28307     55/push-ebp
    28308     89/<- %ebp 4/r32/esp
    28309     # . save registers
    28310     51/push-ecx
    28311     # ecx = stmt
    28312     8b/-> *(ebp+8) 1/r32/ecx
    28313     # if stmt is a stmt1, return assigns-in-stmt-vars?(stmt->outputs, v)
    28314     {
    28315       81 7/subop/compare *ecx 1/imm32/stmt1  # Stmt-tag
    28316       75/jump-if-!= break/disp8
    28317       (lookup *(ecx+0x14) *(ecx+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    28318       (assigns-in-stmt-vars? %eax *(ebp+0xc))  # => eax
    28319       eb/jump $assigns-in-stmt?:end/disp8
    28320     }
    28321     # if stmt is a block, return assigns-in-stmts?(stmt->stmts, v)
    28322     {
    28323       81 7/subop/compare *ecx 0/imm32/block  # Stmt-tag
    28324       75/jump-if-!= break/disp8
    28325       (lookup *(ecx+4) *(ecx+8))  # Block-stmts Block-stmts => eax
    28326       (assigns-in-stmts? %eax *(ebp+0xc))  # => eax
    28327       eb/jump $assigns-in-stmt?:end/disp8
    28328     }
    28329     # otherwise return false
    28330     b8/copy 0/imm32/false
    28331 $assigns-in-stmt?:end:
    28332     # . restore registers
    28333     59/pop-to-ecx
    28334     # . epilogue
    28335     89/<- %esp 5/r32/ebp
    28336     5d/pop-to-ebp
    28337     c3/return
    28338
    28339 assigns-in-stmt-vars?:  # stmt-var: (addr stmt-var), v: (addr var) -> result/eax: boolean
    28340     # . prologue
    28341     55/push-ebp
    28342     89/<- %ebp 4/r32/esp
    28343     # . save registers
    28344     51/push-ecx
    28345     # var curr/ecx: (addr stmt-var) = stmt-var
    28346     8b/-> *(ebp+8) 1/r32/ecx
    28347     {
    28348       # if (curr == 0) break
    28349       81 7/subop/compare %ecx 0/imm32
    28350       74/jump-if-= break/disp8
    28351       # eax = lookup(curr->value)
    28352       (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
    28353       # if (eax == v  &&  curr->is-deref? == false) return true
    28354       {
    28355         39/compare *(ebp+0xc) 0/r32/eax
    28356         75/jump-if-!= break/disp8
    28357         81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
    28358         75/jump-if-!= break/disp8
    28359         b8/copy-to-eax 1/imm32/true
    28360         eb/jump $assigns-in-stmt-vars?:end/disp8
    28361       }
    28362       # curr = lookup(curr->next)
    28363       (lookup *(ecx+8) *(ecx+0xc))  # Stmt-var-next Stmt-var-next => eax
    28364       89/<- %ecx 0/r32/eax
    28365       #
    28366       eb/jump loop/disp8
    28367     }
    28368 $assigns-in-stmt-vars?:end:
    28369     # . restore registers
    28370     59/pop-to-ecx
    28371     # . epilogue
    28372     89/<- %esp 5/r32/ebp
    28373     5d/pop-to-ebp
    28374     c3/return
    28375
    28376 # is there a var before 'v' with the same block-depth and register on the 'vars' stack?
    28377 # v is guaranteed to be within vars
    28378 # 'start' is provided as an optimization, a pointer within vars
    28379 # *start == v
    28380 same-register-spilled-before?:  # v: (addr var), vars: (addr stack (handle var)), start: (addr var) -> result/eax: boolean
    28381     # . prologue
    28382     55/push-ebp
    28383     89/<- %ebp 4/r32/esp
    28384     # . save registers
    28385     51/push-ecx
    28386     52/push-edx
    28387     53/push-ebx
    28388     56/push-esi
    28389     57/push-edi
    28390     # ecx = v
    28391     8b/-> *(ebp+8) 1/r32/ecx
    28392     # var reg/edx: (addr array byte) = lookup(v->register)
    28393     (lookup *(ecx+0x18) *(ecx+0x1c))  # Var-register Var-register => eax
    28394     89/<- %edx 0/r32/eax
    28395     # var depth/ebx: int = v->block-depth
    28396     8b/-> *(ecx+0x10) 3/r32/ebx  # Var-block-depth
    28397     # var min/ecx: (addr handle var) = vars->data
    28398     8b/-> *(ebp+0xc) 1/r32/ecx
    28399     81 0/subop/add %ecx 8/imm32
    28400     # TODO: check that start >= min and start < &vars->data[top]
    28401     # TODO: check that *start == v
    28402     # var curr/esi: (addr handle var) = start
    28403     8b/-> *(ebp+0x10) 6/r32/esi
    28404     # curr -= 8
    28405     81 5/subop/subtract %esi 8/imm32
    28406     {
    28407 $same-register-spilled-before?:loop:
    28408       # if (curr < min) break
    28409       39/compare %esi 1/r32/ecx
    28410       0f 82/jump-if-addr< break/disp32
    28411       # var x/eax: (addr var) = lookup(*curr)
    28412       (lookup *esi *(esi+4))  # => eax
    28413       # if (x->block-depth < depth) break
    28414       39/compare *(eax+0x10) 3/r32/ebx  # Var-block-depth
    28415       0f 8c/jump-if-< break/disp32
    28416       # if (x->register == 0) continue
    28417       81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
    28418       74/jump-if-= $same-register-spilled-before?:continue/disp8
    28419       # if (x->register == reg) return true
    28420       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    28421       (string-equal? %eax %edx)  # => eax
    28422       3d/compare-eax-and 0/imm32/false
    28423       b8/copy-to-eax 1/imm32/true
    28424       75/jump-if-!= $same-register-spilled-before?:end/disp8
    28425 $same-register-spilled-before?:continue:
    28426       # curr -= 8
    28427       81 5/subop/subtract %esi 8/imm32
    28428       e9/jump loop/disp32
    28429     }
    28430 $same-register-spilled-before?:false:
    28431     b8/copy-to-eax 0/imm32/false
    28432 $same-register-spilled-before?:end:
    28433     # . restore registers
    28434     5f/pop-to-edi
    28435     5e/pop-to-esi
    28436     5b/pop-to-ebx
    28437     5a/pop-to-edx
    28438     59/pop-to-ecx
    28439     # . epilogue
    28440     89/<- %esp 5/r32/ebp
    28441     5d/pop-to-ebp
    28442     c3/return
    28443
    28444 # clean up global state for 'vars' until some block depth (inclusive)
    28445 clean-up-blocks:  # vars: (addr stack live-var), until-block-depth: int, fn: (addr function)
    28446     # . prologue
    28447     55/push-ebp
    28448     89/<- %ebp 4/r32/esp
    28449     # . save registers
    28450     50/push-eax
    28451     51/push-ecx
    28452     56/push-esi
    28453     # esi = vars
    28454     8b/-> *(ebp+8) 6/r32/esi
    28455     # ecx = until-block-depth
    28456     8b/-> *(ebp+0xc) 1/r32/ecx
    28457     {
    28458 $clean-up-blocks:reclaim-loop:
    28459       # if (vars->top <= 0) break
    28460       8b/-> *esi 0/r32/eax  # Stack-top
    28461       3d/compare-eax-and 0/imm32
    28462       0f 8e/jump-if-<= break/disp32
    28463       # var v/eax: (addr var) = lookup(vars[vars->top-12])
    28464       (lookup *(esi+eax-4) *(esi+eax))  # vars + 8 + vars->top - 12 => eax
    28465       # if (v->block-depth < until-block-depth) break
    28466       39/compare *(eax+0x10) 1/r32/ecx  # Var-block-depth
    28467       0f 8c/jump-if-< break/disp32
    28468       (pop %esi)  # => eax
    28469       (pop %esi)  # => eax
    28470       (pop %esi)  # => eax
    28471       e9/jump loop/disp32
    28472     }
    28473 $clean-up-blocks:end:
    28474     # . restore registers
    28475     5e/pop-to-esi
    28476     59/pop-to-ecx
    28477     58/pop-to-eax
    28478     # . epilogue
    28479     89/<- %esp 5/r32/ebp
    28480     5d/pop-to-ebp
    28481     c3/return
    28482
    28483 reg-in-function-outputs?:  # fn: (addr function), target: (addr array byte) -> result/eax: boolean
    28484     # . prologue
    28485     55/push-ebp
    28486     89/<- %ebp 4/r32/esp
    28487     # . save registers
    28488     51/push-ecx
    28489     # var curr/ecx: (addr list var) = lookup(fn->outputs)
    28490     8b/-> *(ebp+8) 0/r32/eax
    28491     (lookup *(eax+0x10) *(eax+0x14))  # Function-outputs Function-outputs => eax
    28492     89/<- %ecx 0/r32/eax
    28493     # while curr != null
    28494     {
    28495       81 7/subop/compare %ecx 0/imm32
    28496       74/jump-if-= break/disp8
    28497       # var v/eax: (addr var) = lookup(curr->value)
    28498       (lookup *ecx *(ecx+4))  # List-value List-value => eax
    28499       # var reg/eax: (addr array byte) = lookup(v->register)
    28500       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    28501       # if (reg == target) return true
    28502       (string-equal? %eax *(ebp+0xc))  # => eax
    28503       3d/compare-eax-and 0/imm32/false
    28504       75/jump-if-!= $reg-in-function-outputs?:end/disp8
    28505       # curr = curr->next
    28506       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
    28507       89/<- %ecx 0/r32/eax
    28508       #
    28509       eb/jump loop/disp8
    28510     }
    28511     # return false
    28512     b8/copy-to-eax 0/imm32
    28513 $reg-in-function-outputs?:end:
    28514     # . restore registers
    28515     59/pop-to-ecx
    28516     # . epilogue
    28517     89/<- %esp 5/r32/ebp
    28518     5d/pop-to-ebp
    28519     c3/return
    28520
    28521 emit-subx-var-def:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
    28522     # . prologue
    28523     55/push-ebp
    28524     89/<- %ebp 4/r32/esp
    28525     # . save registers
    28526     50/push-eax
    28527     51/push-ecx
    28528     52/push-edx
    28529     # eax = stmt
    28530     8b/-> *(ebp+0xc) 0/r32/eax
    28531     # var v/ecx: (addr var)
    28532     (lookup *(eax+4) *(eax+8))  # Vardef-var Vardef-var => eax
    28533     89/<- %ecx 0/r32/eax
    28534     # v->block-depth = *Curr-block-depth
    28535     8b/-> *Curr-block-depth 0/r32/eax
    28536     89/<- *(ecx+0x10) 0/r32/eax  # Var-block-depth
    28537     # var n/edx: int = size-of(stmt->var)
    28538     (size-of %ecx)  # => eax
    28539     89/<- %edx 0/r32/eax
    28540     # *Curr-local-stack-offset -= n
    28541     29/subtract-from *Curr-local-stack-offset 2/r32/edx
    28542     # v->offset = *Curr-local-stack-offset
    28543     8b/-> *Curr-local-stack-offset 0/r32/eax
    28544     89/<- *(ecx+0x14) 0/r32/eax  # Var-offset
    28545     # if v is an array, do something special to initialize it
    28546     {
    28547       (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
    28548       (mu-array? %eax)  # => eax
    28549       3d/compare-eax-and 0/imm32/false
    28550       0f 84/jump-if-= break/disp32
    28551       # var array-size-without-size/edx: int = n-4
    28552       81 5/subop/subtract %edx 4/imm32
    28553       #
    28554       (emit-array-data-initialization *(ebp+8) %edx)
    28555       e9/jump $emit-subx-var-def:end/disp32
    28556     }
    28557     # another special-case for initializing streams
    28558     # a stream is an array with 2 extra pointers
    28559     {
    28560       (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
    28561       (mu-stream? %eax)  # => eax
    28562       3d/compare-eax-and 0/imm32/false
    28563       0f 84/jump-if-= break/disp32
    28564       # var array-size-without-size/edx: int = n-12
    28565       81 5/subop/subtract %edx 0xc/imm32
    28566       (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
    28567       (emit-stream-data-initialization *(ebp+8) %edx %eax *(ebp+0x10) *(ebp+0x14))
    28568       # emit read and write pointers
    28569       (emit-indent *(ebp+8) *Curr-block-depth)
    28570       (write-buffered *(ebp+8) "68/push 0/imm32\n")
    28571       (emit-indent *(ebp+8) *Curr-block-depth)
    28572       (write-buffered *(ebp+8) "68/push 0/imm32\n")
    28573       #
    28574       eb/jump $emit-subx-var-def:end/disp8
    28575     }
    28576     # while n > 0
    28577     {
    28578       81 7/subop/compare %edx 0/imm32
    28579       7e/jump-if-<= break/disp8
    28580       (emit-indent *(ebp+8) *Curr-block-depth)
    28581       (write-buffered *(ebp+8) "68/push 0/imm32\n")
    28582       # n -= 4
    28583       81 5/subop/subtract %edx 4/imm32
    28584       #
    28585       eb/jump loop/disp8
    28586     }
    28587 $emit-subx-var-def:end:
    28588     # . restore registers
    28589     5a/pop-to-edx
    28590     59/pop-to-ecx
    28591     58/pop-to-eax
    28592     # . epilogue
    28593     89/<- %esp 5/r32/ebp
    28594     5d/pop-to-ebp
    28595     c3/return
    28596
    28597 emit-array-data-initialization:  # out: (addr buffered-file), n: int
    28598     # . prologue
    28599     55/push-ebp
    28600     89/<- %ebp 4/r32/esp
    28601     #
    28602     (emit-indent *(ebp+8) *Curr-block-depth)
    28603     (write-buffered *(ebp+8) "(push-n-zero-bytes ")
    28604     (write-int32-hex-buffered *(ebp+8) *(ebp+0xc))
    28605     (write-buffered *(ebp+8) ")\n")
    28606     (emit-indent *(ebp+8) *Curr-block-depth)
    28607     (write-buffered *(ebp+8) "68/push ")
    28608     (write-int32-hex-buffered *(ebp+8) *(ebp+0xc))
    28609     (write-buffered *(ebp+8) "/imm32\n")
    28610 $emit-array-data-initialization:end:
    28611     # . epilogue
    28612     89/<- %esp 5/r32/ebp
    28613     5d/pop-to-ebp
    28614     c3/return
    28615
    28616 emit-stream-data-initialization:  # out: (addr buffered-file), n: int, type: (addr type-tree), err: (addr buffered-file), ed: (addr exit-descriptor)
    28617     # . prologue
    28618     55/push-ebp
    28619     89/<- %ebp 4/r32/esp
    28620     # . save registers
    28621     50/push-eax
    28622     # Optimization: if it's a stream of bytes, don't initialize.
    28623     #
    28624     # We often construct large temporary streams on the stack for 'trace'
    28625     # statements. Initializing such streams can significantly slow programs
    28626     # down.
    28627     #
    28628     # Mu doesn't really depend on initializing stream contents for type- or
    28629     # memory-safety; we're mostly doing so to make it easy to debug unsafe
    28630     # SubX code that misuses stream objects by manipulating read/write
    28631     # pointers. But you can't _really_ protect from unsafe SubX, so I think we
    28632     # don't give up much safety or security here.
    28633     {
    28634       (stream-element-type-id *(ebp+0x10) *(ebp+0x14) *(ebp+0x18))  # => eax
    28635       3d/compare-eax-and 8/imm32/byte
    28636       75/jump-if-!= break/disp8
    28637       (emit-indent *(ebp+8) *Curr-block-depth)
    28638       (write-buffered *(ebp+8) "81 5/subop/subtract %esp ")
    28639       (write-int32-hex-buffered *(ebp+8) *(ebp+0xc))
    28640       (write-buffered *(ebp+8) "/imm32\n")
    28641       eb/jump $emit-stream-data-initialization:emit-length/disp8
    28642     }
    28643     (emit-indent *(ebp+8) *Curr-block-depth)
    28644     (write-buffered *(ebp+8) "(push-n-zero-bytes ")
    28645     (write-int32-hex-buffered *(ebp+8) *(ebp+0xc))
    28646     (write-buffered *(ebp+8) ")\n")
    28647 $emit-stream-data-initialization:emit-length:
    28648     (emit-indent *(ebp+8) *Curr-block-depth)
    28649     (write-buffered *(ebp+8) "68/push ")
    28650     (write-int32-hex-buffered *(ebp+8) *(ebp+0xc))
    28651     (write-buffered *(ebp+8) "/imm32\n")
    28652 $emit-stream-data-initialization:end:
    28653     # . restore registers
    28654     58/pop-to-eax
    28655     # . epilogue
    28656     89/<- %esp 5/r32/ebp
    28657     5d/pop-to-ebp
    28658     c3/return
    28659
    28660 emit-subx-stmt:  # out: (addr buffered-file), stmt: (addr stmt), primitives: (addr primitive), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    28661     # . prologue
    28662     55/push-ebp
    28663     89/<- %ebp 4/r32/esp
    28664     # . save registers
    28665     50/push-eax
    28666     51/push-ecx
    28667     # - some special-case primitives that don't actually use the 'primitives' data structure
    28668     # var op/ecx: (addr array byte) = lookup(stmt->operation)
    28669     8b/-> *(ebp+0xc) 1/r32/ecx
    28670     (lookup *(ecx+4) *(ecx+8))  # Stmt1-operation Stmt1-operation => eax
    28671     89/<- %ecx 0/r32/eax
    28672     # copy byte (can be a primitive except we need to emit a second instruction)
    28673     {
    28674       # if (!string-equal?(stmt->operation, "copy-byte")) break
    28675       (string-equal? %ecx "copy-byte")  # => eax
    28676       3d/compare-eax-and 0/imm32/false
    28677       0f 84/jump-if-= break/disp32
    28678       (translate-mu-copy-byte-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
    28679       e9/jump $emit-subx-stmt:end/disp32
    28680     }
    28681     # copy-byte-to can be a primitive; writes to memory don't need to clear surrounding bytes
    28682     # array size
    28683     {
    28684       # if (!string-equal?(stmt->operation, "length")) break
    28685       (string-equal? %ecx "length")  # => eax
    28686       3d/compare-eax-and 0/imm32/false
    28687       0f 84/jump-if-= break/disp32
    28688       (translate-mu-length-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
    28689       e9/jump $emit-subx-stmt:end/disp32
    28690     }
    28691     # index into array
    28692     {
    28693       # if (!string-equal?(stmt->operation, "index")) break
    28694       (string-equal? %ecx "index")  # => eax
    28695       3d/compare-eax-and 0/imm32/false
    28696       0f 84/jump-if-= break/disp32
    28697       (translate-mu-index-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
    28698       e9/jump $emit-subx-stmt:end/disp32
    28699     }
    28700     # compute-offset for index into array
    28701     {
    28702       # if (!string-equal?(stmt->operation, "compute-offset")) break
    28703       (string-equal? %ecx "compute-offset")  # => eax
    28704       3d/compare-eax-and 0/imm32/false
    28705       0f 84/jump-if-= break/disp32
    28706       (translate-mu-compute-index-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
    28707       e9/jump $emit-subx-stmt:end/disp32
    28708     }
    28709     # get field from record
    28710     {
    28711       # if (!string-equal?(stmt->operation, "get")) break
    28712       (string-equal? %ecx "get")  # => eax
    28713       3d/compare-eax-and 0/imm32/false
    28714       0f 84/jump-if-= break/disp32
    28715       (translate-mu-get-stmt *(ebp+8) *(ebp+0xc))
    28716       e9/jump $emit-subx-stmt:end/disp32
    28717     }
    28718     # allocate scalar
    28719     {
    28720       # if (!string-equal?(stmt->operation, "allocate")) break
    28721       (string-equal? %ecx "allocate")  # => eax
    28722       3d/compare-eax-and 0/imm32/false
    28723       0f 84/jump-if-= break/disp32
    28724       (translate-mu-allocate-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
    28725       e9/jump $emit-subx-stmt:end/disp32
    28726     }
    28727     # copy-object
    28728     {
    28729       # if (!string-equal?(stmt->operation, "copy-object")) break
    28730       (string-equal? %ecx "copy-object")  # => eax
    28731       3d/compare-eax-and 0/imm32/false
    28732       0f 84/jump-if-= break/disp32
    28733       (translate-mu-copy-object-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
    28734       e9/jump $emit-subx-stmt:end/disp32
    28735     }
    28736     # clear-object
    28737     {
    28738       # if (!string-equal?(stmt->operation, "clear-object")) break
    28739       (string-equal? %ecx "clear-object")  # => eax
    28740       3d/compare-eax-and 0/imm32/false
    28741       0f 84/jump-if-= break/disp32
    28742       (translate-mu-clear-object-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
    28743       e9/jump $emit-subx-stmt:end/disp32
    28744     }
    28745     # allocate array
    28746     {
    28747       # if (!string-equal?(stmt->operation, "populate")) break
    28748       (string-equal? %ecx "populate")  # => eax
    28749       3d/compare-eax-and 0/imm32/false
    28750       0f 84/jump-if-= break/disp32
    28751       (translate-mu-populate-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
    28752       e9/jump $emit-subx-stmt:end/disp32
    28753     }
    28754     # allocate stream
    28755     {
    28756       # if (!string-equal?(stmt->operation, "populate-stream")) break
    28757       (string-equal? %ecx "populate-stream")  # => eax
    28758       3d/compare-eax-and 0/imm32/false
    28759       0f 84/jump-if-= break/disp32
    28760       (translate-mu-populate-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
    28761       e9/jump $emit-subx-stmt:end/disp32
    28762     }
    28763     # read from stream
    28764     {
    28765       # if (!string-equal?(stmt->operation, "read-from-stream")) break
    28766       (string-equal? %ecx "read-from-stream")  # => eax
    28767       3d/compare-eax-and 0/imm32/false
    28768       0f 84/jump-if-= break/disp32
    28769       (translate-mu-read-from-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
    28770       e9/jump $emit-subx-stmt:end/disp32
    28771     }
    28772     # write to stream
    28773     {
    28774       # if (!string-equal?(stmt->operation, "write-to-stream")) break
    28775       (string-equal? %ecx "write-to-stream")  # => eax
    28776       3d/compare-eax-and 0/imm32/false
    28777       0f 84/jump-if-= break/disp32
    28778       (translate-mu-write-to-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
    28779       e9/jump $emit-subx-stmt:end/disp32
    28780     }
    28781     # - optimizations
    28782     # if copy instruction has same register in source and destination, emit nothing
    28783     (redundant-copy? *(ebp+0xc))  # => eax
    28784     3d/compare-eax-and 0/imm32/false
    28785     75/jump-if-!= $emit-subx-stmt:end/disp8
    28786     # - if stmt matches a primitive, emit it
    28787     {
    28788 $emit-subx-stmt:check-for-primitive:
    28789       # var curr/eax: (addr primitive)
    28790       (find-matching-primitive *(ebp+0x10) *(ebp+0xc))  # primitives, stmt => eax
    28791       3d/compare-eax-and 0/imm32
    28792       74/jump-if-= break/disp8
    28793 $emit-subx-stmt:primitive:
    28794       (emit-subx-primitive *(ebp+8) *(ebp+0xc) %eax)  # out, stmt, curr
    28795       e9/jump $emit-subx-stmt:end/disp32
    28796     }
    28797     # - otherwise emit a call
    28798     # TODO: type-checking
    28799 $emit-subx-stmt:call:
    28800     (emit-call *(ebp+8) *(ebp+0xc))
    28801 $emit-subx-stmt:end:
    28802     # . restore registers
    28803     59/pop-to-ecx
    28804     58/pop-to-eax
    28805     # . epilogue
    28806     89/<- %esp 5/r32/ebp
    28807     5d/pop-to-ebp
    28808     c3/return
    28809
    28810 redundant-copy?:  # stmt: (addr stmt) -> result/eax: boolean
    28811     # . prologue
    28812     55/push-ebp
    28813     89/<- %ebp 4/r32/esp
    28814     # . save registers
    28815     56/push-esi
    28816     57/push-edi
    28817     # esi = stmt
    28818     8b/-> *(ebp+8) 6/r32/esi
    28819     # if stmt->operation != "copy" return false
    28820     (lookup *(esi+4) *(esi+8))  # Stmt1-operation Stmt1-operation => eax
    28821     (string-equal? %eax "copy")  # => eax
    28822     3d/compare-eax-and 0/imm32/false
    28823     0f 84/jump-if-= $redundant-copy?:end/disp32
    28824     # var output-reg/edi: (addr stmt-var) = stmt->outputs->value->register
    28825     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    28826     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    28827     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    28828     # . if output-reg == null, return false
    28829     3d/compare-eax-and 0/imm32
    28830     74/jump-if-= $redundant-copy?:end/disp8
    28831     89/<- %edi 0/r32/eax
    28832     # return (inout->value->register == output->value->register)
    28833     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    28834     # . if inout->is-deref return false
    28835     81 7/subop/compare *(eax+0x10) 0/imm32/false  # Stmt-var-is-deref
    28836     {
    28837       74/jump-if-= break/disp8
    28838       b8/copy-to-eax 0/imm32/false
    28839       e9/jump $redundant-copy?:end/disp32
    28840     }
    28841     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    28842     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    28843     # . if inout-reg == null, return false
    28844     3d/compare-eax-and 0/imm32
    28845     74/jump-if-= $redundant-copy?:end/disp8
    28846     (string-equal? %eax %edi)  # => eax
    28847 $redundant-copy?:end:
    28848     # . restore registers
    28849     5f/pop-to-edi
    28850     5e/pop-to-esi
    28851     # . epilogue
    28852     89/<- %esp 5/r32/ebp
    28853     5d/pop-to-ebp
    28854     c3/return
    28855
    28856 translate-mu-length-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
    28857     # . prologue
    28858     55/push-ebp
    28859     89/<- %ebp 4/r32/esp
    28860     # . save registers
    28861     50/push-eax
    28862     51/push-ecx
    28863     52/push-edx
    28864     53/push-ebx
    28865     56/push-esi
    28866     # esi = stmt
    28867     8b/-> *(ebp+0xc) 6/r32/esi
    28868     # var base/ebx: (addr var) = stmt->inouts[0]->value
    28869     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    28870     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    28871     89/<- %ebx 0/r32/eax
    28872     # var elemsize/ecx: int = array-element-size(base)
    28873     (array-element-size %ebx *(ebp+0x10) *(ebp+0x14))  # => eax
    28874     89/<- %ecx 0/r32/eax
    28875     # var outreg/edx: (addr array byte) = stmt->outputs[0]->value->register
    28876     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    28877     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    28878     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    28879     89/<- %edx 0/r32/eax
    28880     # if elemsize == 1
    28881     {
    28882       81 7/subop/compare %ecx 1/imm32
    28883       75/jump-if-!= break/disp8
    28884 $translate-mu-length-stmt:size-1:
    28885       (emit-save-size-to *(ebp+8) %ebx %edx)
    28886       e9/jump $translate-mu-length-stmt:end/disp32
    28887     }
    28888     # if elemsize is a power of 2 less than 256
    28889     {
    28890       (power-of-2? %ecx *(ebp+0x10) *(ebp+0x14))  # => eax
    28891       3d/compare-eax-and 0/imm32/false
    28892       74/jump-if-= break/disp8
    28893       81 7/subop/compare %ecx 0xff/imm32
    28894       7f/jump-if-> break/disp8
    28895 $translate-mu-length-stmt:size-power-of-2:
    28896       (emit-save-size-to *(ebp+8) %ebx %edx)
    28897       (emit-divide-by-shift-right *(ebp+8) %edx %ecx)
    28898       e9/jump $translate-mu-length-stmt:end/disp32
    28899     }
    28900     # otherwise, the complex case
    28901     # . emit register spills
    28902     {
    28903 $translate-mu-length-stmt:complex:
    28904       (string-equal? %edx "eax")  # => eax
    28905       3d/compare-eax-and 0/imm32/false
    28906       75/break-if-!= break/disp8
    28907       (emit-indent *(ebp+8) *Curr-block-depth)
    28908       (write-buffered *(ebp+8) "50/push-eax\n")
    28909     }
    28910     {
    28911       (string-equal? %edx "ecx")  # => eax
    28912       3d/compare-eax-and 0/imm32/false
    28913       75/break-if-!= break/disp8
    28914       (emit-indent *(ebp+8) *Curr-block-depth)
    28915       (write-buffered *(ebp+8) "51/push-ecx\n")
    28916     }
    28917     {
    28918       (string-equal? %edx "edx")  # => eax
    28919       3d/compare-eax-and 0/imm32/false
    28920       75/break-if-!= break/disp8
    28921       (emit-indent *(ebp+8) *Curr-block-depth)
    28922       (write-buffered *(ebp+8) "52/push-edx\n")
    28923     }
    28924     # .
    28925     (emit-save-size-to *(ebp+8) %ebx "eax")
    28926     (emit-indent *(ebp+8) *Curr-block-depth)
    28927     (write-buffered *(ebp+8) "31/xor %edx 2/r32/edx\n")
    28928     (emit-indent *(ebp+8) *Curr-block-depth)
    28929     (write-buffered *(ebp+8) "b9/copy-to-ecx ")
    28930     (write-int32-hex-buffered *(ebp+8) %ecx)
    28931     (write-buffered *(ebp+8) "/imm32\n")
    28932     (emit-indent *(ebp+8) *Curr-block-depth)
    28933     (write-buffered *(ebp+8) "f7 7/subop/idiv-eax-edx-by %ecx\n")
    28934     {
    28935       (string-equal? %edx "eax")  # => eax
    28936       3d/compare-eax-and 0/imm32/false
    28937       75/break-if-!= break/disp8
    28938       (emit-indent *(ebp+8) *Curr-block-depth)
    28939       (write-buffered *(ebp+8) "89/<- %")
    28940       (write-buffered *(ebp+8) %edx)
    28941       (write-buffered *(ebp+8) " 0/r32/eax\n")
    28942     }
    28943     # . emit register restores
    28944     {
    28945       (string-equal? %edx "edx")  # => eax
    28946       3d/compare-eax-and 0/imm32/false
    28947       75/break-if-!= break/disp8
    28948       (emit-indent *(ebp+8) *Curr-block-depth)
    28949       (write-buffered *(ebp+8) "5a/pop-to-edx\n")
    28950     }
    28951     {
    28952       (string-equal? %edx "ecx")  # => eax
    28953       3d/compare-eax-and 0/imm32/false
    28954       75/break-if-!= break/disp8
    28955       (emit-indent *(ebp+8) *Curr-block-depth)
    28956       (write-buffered *(ebp+8) "59/pop-to-ecx\n")
    28957     }
    28958     {
    28959       (string-equal? %edx "eax")  # => eax
    28960       3d/compare-eax-and 0/imm32/false
    28961       75/break-if-!= break/disp8
    28962       (emit-indent *(ebp+8) *Curr-block-depth)
    28963       (write-buffered *(ebp+8) "58/pop-to-eax\n")
    28964     }
    28965 $translate-mu-length-stmt:end:
    28966     # . restore registers
    28967     5e/pop-to-esi
    28968     5b/pop-to-ebx
    28969     5a/pop-to-edx
    28970     59/pop-to-ecx
    28971     58/pop-to-eax
    28972     # . epilogue
    28973     89/<- %esp 5/r32/ebp
    28974     5d/pop-to-ebp
    28975     c3/return
    28976
    28977 array-element-size:  # arr: (addr var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
    28978     # . prologue
    28979     55/push-ebp
    28980     89/<- %ebp 4/r32/esp
    28981     #
    28982     (array-element-type-id *(ebp+8) *(ebp+0xc) *(ebp+0x10))  # => eax
    28983     (size-of-type-id-as-array-element %eax)  # => eax
    28984 $array-element-size:end:
    28985     # . epilogue
    28986     89/<- %esp 5/r32/ebp
    28987     5d/pop-to-ebp
    28988     c3/return
    28989
    28990 array-element-type-id:  # v: (addr var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: type-id
    28991     # precondition: n is positive
    28992     # . prologue
    28993     55/push-ebp
    28994     89/<- %ebp 4/r32/esp
    28995     #
    28996     8b/-> *(ebp+8) 0/r32/eax
    28997     # var t/eax: (addr type-tree)
    28998     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    28999     # if t == 0 abort
    29000     3d/compare-eax-with 0/imm32
    29001     0f 84/jump-if-== $array-element-type-id:error0/disp32
    29002     # if t->is-atom? abort
    29003     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
    29004     0f 85/jump-if-!= $array-element-type-id:error1/disp32
    29005     # if (t->left == addr) t = t->right
    29006     {
    29007       50/push-eax
    29008       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    29009       (simple-mu-type? %eax 2)  # addr => eax
    29010       3d/compare-eax-with 0/imm32/false
    29011       58/pop-to-eax
    29012       74/jump-if-= break/disp8
    29013 $array-element-type-id:skip-addr:
    29014       (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
    29015     }
    29016     # if t == 0 abort
    29017     3d/compare-eax-with 0/imm32
    29018     0f 84/jump-if-= $array-element-type-id:error2/disp32
    29019     # if t->is-atom? abort
    29020     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
    29021     0f 85/jump-if-!= $array-element-type-id:error2/disp32
    29022     # if t->left != array abort
    29023     {
    29024       50/push-eax
    29025       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    29026       (simple-mu-type? %eax 3)  # array => eax
    29027       3d/compare-eax-with 0/imm32/false
    29028       58/pop-to-eax
    29029 $array-element-type-id:no-array:
    29030       0f 84/jump-if-= $array-element-type-id:error2/disp32
    29031     }
    29032 $array-element-type-id:skip-array:
    29033     # t = t->right
    29034     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
    29035     # if t == 0 abort
    29036     3d/compare-eax-with 0/imm32
    29037     0f 84/jump-if-= $array-element-type-id:error2/disp32
    29038     # if t->is-atom? abort
    29039     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
    29040     0f 85/jump-if-!= $array-element-type-id:error2/disp32
    29041     # t = t->left
    29042     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    29043     # if (!t->is-atom?) t = t->left     # TODO: assumes array element size can be determined from just first word of array element type
    29044     # if (t->is-atom == false) t = lookup(t->left)
    29045     {
    29046       81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
    29047       75/jump-if-!= break/disp8
    29048       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    29049     }
    29050     # return t->value
    29051     8b/-> *(eax+4) 0/r32/eax  # Type-tree-value
    29052 $array-element-type-id:end:
    29053     # . epilogue
    29054     89/<- %esp 5/r32/ebp
    29055     5d/pop-to-ebp
    29056     c3/return
    29057
    29058 $array-element-type-id:error0:
    29059     (write-buffered *(ebp+0xc) "array-element-type-id: var '")
    29060     50/push-eax
    29061     8b/-> *(ebp+8) 0/r32/eax
    29062     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    29063     (write-buffered *(ebp+0xc) %eax)
    29064     58/pop-to-eax
    29065     (write-buffered *(ebp+0xc) "' has no type\n")
    29066     (flush *(ebp+0xc))
    29067     (stop *(ebp+0x10) 1)
    29068     # never gets here
    29069
    29070 $array-element-type-id:error1:
    29071     (write-buffered *(ebp+0xc) "array-element-type-id: var '")
    29072     50/push-eax
    29073     8b/-> *(ebp+8) 0/r32/eax
    29074     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    29075     (write-buffered *(ebp+0xc) %eax)
    29076     58/pop-to-eax
    29077     (write-buffered *(ebp+0xc) "' has atomic type ")
    29078     (write-int32-hex-buffered *(ebp+0xc) *(eax+4))  # Type-tree-value
    29079     (write-buffered *(ebp+0xc) Newline)
    29080     (flush *(ebp+0xc))
    29081     (stop *(ebp+0x10) 1)
    29082     # never gets here
    29083
    29084 $array-element-type-id:error2:
    29085     (write-buffered *(ebp+0xc) "array-element-type-id: var '")
    29086     50/push-eax
    29087     8b/-> *(ebp+8) 0/r32/eax
    29088     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    29089     (write-buffered *(ebp+0xc) %eax)
    29090     58/pop-to-eax
    29091     (write-buffered *(ebp+0xc) "' has non-array type\n")
    29092     (flush *(ebp+0xc))
    29093     (stop *(ebp+0x10) 1)
    29094     # never gets here
    29095
    29096 size-of-type-id-as-array-element:  # t: type-id -> result/eax: int
    29097     # . prologue
    29098     55/push-ebp
    29099     89/<- %ebp 4/r32/esp
    29100     # eax = t
    29101     8b/-> *(ebp+8) 0/r32/eax
    29102     # if t is 'byte', size is 1
    29103     3d/compare-eax-and 8/imm32/byte
    29104     {
    29105       75/jump-if-!= break/disp8
    29106       b8/copy-to-eax 1/imm32
    29107       eb/jump $size-of-type-id-as-array-element:end/disp8
    29108     }
    29109     # otherwise proceed as usual
    29110     (size-of-type-id %eax)  # => eax
    29111 $size-of-type-id-as-array-element:end:
    29112     # . epilogue
    29113     89/<- %esp 5/r32/ebp
    29114     5d/pop-to-ebp
    29115     c3/return
    29116
    29117 stream-element-type-id:  # type: (addr type-tree), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: type-id
    29118     # precondition: n is positive
    29119     # . prologue
    29120     55/push-ebp
    29121     89/<- %ebp 4/r32/esp
    29122     # eax = type
    29123     8b/-> *(ebp+8) 0/r32/eax
    29124     # if type == 0 abort
    29125     3d/compare-eax-with 0/imm32
    29126     0f 84/jump-if-== $stream-element-type-id:error0/disp32
    29127     # if type->is-atom? abort
    29128     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
    29129     0f 85/jump-if-!= $stream-element-type-id:error1/disp32
    29130     # if (type->left == addr) type = type->right
    29131     {
    29132       50/push-eax
    29133       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    29134       (simple-mu-type? %eax 2)  # addr => eax
    29135       3d/compare-eax-with 0/imm32/false
    29136       58/pop-to-eax
    29137       74/jump-if-= break/disp8
    29138 $stream-element-type-id:skip-addr:
    29139       (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
    29140     }
    29141     # if type == 0 abort
    29142     3d/compare-eax-with 0/imm32
    29143     0f 84/jump-if-= $stream-element-type-id:error2/disp32
    29144     # if type->is-atom? abort
    29145     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
    29146     0f 85/jump-if-!= $stream-element-type-id:error2/disp32
    29147     # if type->left != stream abort
    29148     {
    29149       50/push-eax
    29150       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    29151       (simple-mu-type? %eax 0xb)  # stream => eax
    29152       3d/compare-eax-with 0/imm32/false
    29153       58/pop-to-eax
    29154 $stream-element-type-id:no-stream:
    29155       0f 84/jump-if-= $stream-element-type-id:error2/disp32
    29156     }
    29157 $stream-element-type-id:skip-stream:
    29158     # type = type->right
    29159     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
    29160     # if type == 0 abort
    29161     3d/compare-eax-with 0/imm32
    29162     0f 84/jump-if-= $stream-element-type-id:error2/disp32
    29163     # if type->is-atom? abort
    29164     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
    29165     0f 85/jump-if-!= $stream-element-type-id:error2/disp32
    29166     # t = type->left
    29167     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    29168     # if (!type->is-atom?) type = type->left     # TODO: assumes stream element size can be determined from just first word of stream element type
    29169     {
    29170       81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
    29171       75/jump-if-!= break/disp8
    29172       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    29173     }
    29174     # return type->value
    29175     8b/-> *(eax+4) 0/r32/eax  # Type-tree-value
    29176 $stream-element-type-id:end:
    29177     # . epilogue
    29178     89/<- %esp 5/r32/ebp
    29179     5d/pop-to-ebp
    29180     c3/return
    29181
    29182 $stream-element-type-id:error0:
    29183     (write-buffered *(ebp+0xc) "stream-element-type-id: var '")
    29184     50/push-eax
    29185     8b/-> *(ebp+8) 0/r32/eax
    29186     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    29187     (write-buffered *(ebp+0xc) %eax)
    29188     58/pop-to-eax
    29189     (write-buffered *(ebp+0xc) "' has no type\n")
    29190     (flush *(ebp+0xc))
    29191     (stop *(ebp+0x10) 1)
    29192     # never gets here
    29193
    29194 $stream-element-type-id:error1:
    29195     (write-buffered *(ebp+0xc) "stream-element-type-id: var '")
    29196     50/push-eax
    29197     8b/-> *(ebp+8) 0/r32/eax
    29198     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    29199     (write-buffered *(ebp+0xc) %eax)
    29200     58/pop-to-eax
    29201     (write-buffered *(ebp+0xc) "' has atomic type ")
    29202     (write-int32-hex-buffered *(ebp+0xc) *(eax+4))  # Type-tree-value
    29203     (write-buffered *(ebp+0xc) Newline)
    29204     (flush *(ebp+0xc))
    29205     (stop *(ebp+0x10) 1)
    29206     # never gets here
    29207
    29208 $stream-element-type-id:error2:
    29209     (write-buffered *(ebp+0xc) "stream-element-type-id: var '")
    29210     50/push-eax
    29211     8b/-> *(ebp+8) 0/r32/eax
    29212     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    29213     (write-buffered *(ebp+0xc) %eax)
    29214     58/pop-to-eax
    29215     (write-buffered *(ebp+0xc) "' has non-stream type\n")
    29216     (flush *(ebp+0xc))
    29217     (stop *(ebp+0x10) 1)
    29218     # never gets here
    29219
    29220 emit-save-size-to:  # out: (addr buffered-file), base: (addr var), outreg: (addr array byte)
    29221     # . prologue
    29222     55/push-ebp
    29223     89/<- %ebp 4/r32/esp
    29224     # . save registers
    29225     50/push-eax
    29226     53/push-ebx
    29227     # ebx = base
    29228     8b/-> *(ebp+0xc) 3/r32/ebx
    29229     (emit-indent *(ebp+8) *Curr-block-depth)
    29230     (write-buffered *(ebp+8) "8b/-> *")
    29231     # if base is an (addr array ...) in a register
    29232     {
    29233       81 7/subop/compare *(ebx+0x18)) 0/imm32  # Var-register
    29234       74/jump-if-= break/disp8
    29235 $emit-save-size-to:emit-base-from-register:
    29236       (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
    29237       (write-buffered *(ebp+8) %eax)
    29238       eb/jump $emit-save-size-to:emit-output/disp8
    29239     }
    29240     # otherwise if base is an (array ...) on the stack
    29241     {
    29242       81 7/subop/compare *(ebx+0x14)) 0/imm32  # Var-offset
    29243       74/jump-if-= break/disp8
    29244 $emit-save-size-to:emit-base-from-stack:
    29245       (write-buffered *(ebp+8) "(ebp+")
    29246       (write-int32-hex-buffered *(ebp+8) *(ebx+0x14))  # Var-offset
    29247       (write-buffered *(ebp+8) ")")
    29248     }
    29249 $emit-save-size-to:emit-output:
    29250     (write-buffered *(ebp+8) " ")
    29251     (get Mu-registers *(ebp+0x10) 0xc "Mu-registers")  # => eax
    29252     (write-int32-hex-buffered *(ebp+8) *eax)
    29253     (write-buffered *(ebp+8) "/r32\n")
    29254 $emit-save-size-to:end:
    29255     # . restore registers
    29256     5b/pop-to-ebx
    29257     58/pop-to-eax
    29258     # . epilogue
    29259     89/<- %esp 5/r32/ebp
    29260     5d/pop-to-ebp
    29261     c3/return
    29262
    29263 emit-divide-by-shift-right:  # out: (addr buffered-file), reg: (addr array byte), size: int
    29264     # . prologue
    29265     55/push-ebp
    29266     89/<- %ebp 4/r32/esp
    29267     # . save registers
    29268     50/push-eax
    29269     #
    29270     (emit-indent *(ebp+8) *Curr-block-depth)
    29271     (write-buffered *(ebp+8) "c1/shift 5/subop/>> %")
    29272     (write-buffered *(ebp+8) *(ebp+0xc))
    29273     (write-buffered *(ebp+8) Space)
    29274     (num-shift-rights *(ebp+0x10))  # => eax
    29275     (write-int32-hex-buffered *(ebp+8) %eax)
    29276     (write-buffered *(ebp+8) "/imm8\n")
    29277 $emit-divide-by-shift-right:end:
    29278     # . restore registers
    29279     58/pop-to-eax
    29280     # . epilogue
    29281     89/<- %esp 5/r32/ebp
    29282     5d/pop-to-ebp
    29283     c3/return
    29284
    29285 translate-mu-copy-byte-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
    29286     # . prologue
    29287     55/push-ebp
    29288     89/<- %ebp 4/r32/esp
    29289     # . save registers
    29290     50/push-eax
    29291     56/push-esi
    29292     # esi = stmt
    29293     8b/-> *(ebp+0xc) 6/r32/esi
    29294     #
    29295     (emit-indent *(ebp+8) *Curr-block-depth)
    29296     (write-buffered *(ebp+8) "8a/byte->")
    29297     # emit stmt->inouts[0]
    29298     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    29299     (emit-subx-var-as-rm32 *(ebp+8) %eax)
    29300     # emit /r32 for stmt->outputs[0]->register
    29301     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    29302     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    29303     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    29304     (maybe-get Mu-registers %eax 0xc)  # => eax: (addr register-index)
    29305     (write-buffered *(ebp+8) Space)
    29306     (write-int32-hex-buffered *(ebp+8) *eax)
    29307     (write-buffered *(ebp+8) "/r32\n")
    29308     # clear rest of register
    29309     (emit-indent *(ebp+8) *Curr-block-depth)
    29310     (write-buffered *(ebp+8) "81 4/subop/and %")
    29311     8b/-> *(ebp+0xc) 0/r32/eax
    29312     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    29313     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    29314     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    29315     (write-buffered *(ebp+8) %eax)
    29316     (write-buffered *(ebp+8) " 0xff/imm32\n")
    29317 $translate-mu-copy-byte-stmt:end:
    29318     # . restore registers
    29319     5e/pop-to-esi
    29320     58/pop-to-eax
    29321     # . epilogue
    29322     89/<- %esp 5/r32/ebp
    29323     5d/pop-to-ebp
    29324     c3/return
    29325
    29326 # a little different from other translate- functions; notice the extra 'fn' argument
    29327 translate-mu-index-stmt:  # out: (addr buffered-file), stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    29328     # . prologue
    29329     55/push-ebp
    29330     89/<- %ebp 4/r32/esp
    29331     # . save registers
    29332     53/push-ebx
    29333     # ebx = stmt
    29334     8b/-> *(ebp+0xc) 3/r32/ebx
    29335     # var base/ebx: (addr var) = stmt->inouts[0]
    29336     (lookup *(ebx+0xc) *(ebx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    29337     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    29338     89/<- %ebx 0/r32/eax
    29339     # emit bounds-check
    29340     (emit-mu-index-bounds-check *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14) *(ebp+0x18))
    29341     # if (var->register) do one thing
    29342     {
    29343       81 7/subop/compare *(ebx+0x18) 0/imm32  # Var-register
    29344       74/jump-if-= break/disp8
    29345       # TODO: ensure there's no dereference
    29346       (translate-mu-index-stmt-with-array-in-register *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))
    29347       eb/jump $translate-mu-index-stmt:end/disp8
    29348     }
    29349     # if (var->offset) do a different thing
    29350     {
    29351       81 7/subop/compare *(ebx+0x14) 0/imm32  # Var-offset
    29352       74/jump-if-= break/disp8
    29353       # TODO: ensure there's no dereference
    29354       (translate-mu-index-stmt-with-array-on-stack *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))
    29355       eb/jump $translate-mu-index-stmt:end/disp8
    29356     }
    29357 $translate-mu-index-stmt:end:
    29358     # . restore registers
    29359     5b/pop-to-ebx
    29360     # . epilogue
    29361     89/<- %esp 5/r32/ebp
    29362     5d/pop-to-ebp
    29363     c3/return
    29364
    29365 $translate-mu-index-stmt:error1:
    29366     (write-buffered *(ebp+0x14) "couldn't translate an index instruction. second (index) input must either lie in a register or be a literal\n")
    29367     (flush *(ebp+0x14))
    29368     (stop *(ebp+0x18) 1)
    29369     # never gets here
    29370
    29371 $translate-mu-index-stmt:error2:
    29372     (write-buffered *(ebp+0x14) "couldn't translate an index instruction. second (index) input when in a register must be an int or offset\n")
    29373     (flush *(ebp+0x14))
    29374     (stop *(ebp+0x18) 1)
    29375     # never gets here
    29376
    29377 emit-mu-index-bounds-check:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
    29378     # . prologue
    29379     55/push-ebp
    29380     89/<- %ebp 4/r32/esp
    29381     # . save registers
    29382     50/push-eax
    29383     51/push-ecx
    29384     52/push-edx
    29385     53/push-ebx
    29386     # ecx = stmt
    29387     8b/-> *(ebp+0xc) 1/r32/ecx
    29388     #
    29389     (emit-indent *(ebp+8) *Curr-block-depth)
    29390     (write-buffered *(ebp+8) "(__check-mu-array-bounds ")
    29391 $emit-mu-index-bounds-check:compute-base:
    29392     # var base/ebx: (addr var) = inouts[0]
    29393     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    29394     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    29395     89/<- %ebx 0/r32/eax
    29396 $emit-mu-index-bounds-check:emit-index:
    29397     # var index/edx: (addr var) = inouts[1]
    29398     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    29399     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    29400     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    29401     89/<- %edx 0/r32/eax
    29402     # if index->register, print its code
    29403     81 7/subop/compare *(edx+0x18) 0/imm32  # Var-register
    29404     {
    29405       0f 84/jump-if-= break/disp32
    29406 $emit-mu-index-bounds-check:emit-register-index:
    29407       (write-buffered *(ebp+8) "%")
    29408       (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
    29409       (write-buffered *(ebp+8) %eax)
    29410       eb/jump $emit-mu-index-bounds-check:index-done/disp8
    29411     }
    29412     # otherwise if index is a literal, print it
    29413 $emit-mu-index-bounds-check:emit-literal-index:
    29414     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
    29415     (simple-mu-type? %eax 0)  # => eax
    29416     3d/compare-eax-and 0/imm32/false
    29417     {
    29418       0f 84/jump-if-= break/disp32
    29419       (lookup *edx *(edx+4))  # Var-name Var-name => eax
    29420       (write-buffered *(ebp+8) %eax)
    29421     }
    29422 $emit-mu-index-bounds-check:index-done:
    29423     (write-buffered *(ebp+8) " ")
    29424 $emit-mu-index-bounds-check:emit-element-size:
    29425     # if index is a literal or int, print size of array element
    29426     {
    29427       {
    29428         (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
    29429         (simple-mu-type? %eax 0)  # literal => eax
    29430         3d/compare-eax-and 0/imm32/false
    29431         75/jump-if-!= break/disp8
    29432         (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
    29433         (simple-mu-type? %eax 1)  # int => eax
    29434         3d/compare-eax-and 0/imm32/false
    29435         75/jump-if-!= break/disp8
    29436         eb/jump $emit-mu-index-bounds-check:emit-element-size-offset/disp8
    29437       }
    29438 $emit-mu-index-bounds-check:emit-int-register-index:
    29439       (array-element-size %ebx *(ebp+0x14) *(ebp+0x18))  # => eax
    29440       (write-int32-hex-buffered *(ebp+8) %eax)
    29441       e9/jump $emit-mu-index-bounds-check:emit-base/disp32
    29442     }
    29443 $emit-mu-index-bounds-check:emit-element-size-offset:
    29444     # if index has type (offset ...), print "1"
    29445     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
    29446     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
    29447     {
    29448       75/jump-if-!= break/disp8
    29449       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    29450       (simple-mu-type? %eax 7)  # => eax
    29451       3d/compare-eax-and 0/imm32/false
    29452       {
    29453         0f 84/jump-if-= break/disp32
    29454 $emit-mu-index-bounds-check:emit-offset-register-index:
    29455         (write-buffered *(ebp+8) "1")
    29456       }
    29457     }
    29458 $emit-mu-index-bounds-check:emit-base:
    29459     # if base is in a register, print " *" base->register
    29460     81 7/subop/compare *(ebx+0x18) 0/imm32  # Var-register
    29461     {
    29462       74/jump-if-= break/disp8
    29463       (write-buffered *(ebp+8) " *")
    29464       (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
    29465       (write-buffered *(ebp+8) %eax)
    29466       e9/jump $emit-mu-index-bounds-check:emit-function-name/disp32
    29467     }
    29468     # otherwise print " *(ebp+" base->offset ")"
    29469     (write-buffered *(ebp+8) " *(ebp+")
    29470     (write-int32-hex-buffered *(ebp+8) *(ebx+0x14))  # Var-offset
    29471     (write-buffered *(ebp+8) ")")
    29472 $emit-mu-index-bounds-check:emit-function-name:
    29473     # " \"" function-name "\""
    29474     (write-buffered *(ebp+8) " \"")
    29475     8b/-> *(ebp+0x10) 1/r32/ecx
    29476     (lookup *ecx *(ecx+4))  # Function-name Function-name => eax
    29477     (write-buffered *(ebp+8) %eax)
    29478     (write-buffered *(ebp+8) "\"")
    29479 $emit-mu-index-bounds-check:emit-array-name:
    29480     # " \"" base->name "\""
    29481     (write-buffered *(ebp+8) " \"")
    29482     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
    29483     (write-buffered *(ebp+8) %eax)
    29484     (write-buffered *(ebp+8) "\")\n")
    29485 $emit-mu-index-bounds-check:end:
    29486     # . restore registers
    29487     5b/pop-to-ebx
    29488     5a/pop-to-edx
    29489     59/pop-to-ecx
    29490     58/pop-to-eax
    29491     # . epilogue
    29492     89/<- %esp 5/r32/ebp
    29493     5d/pop-to-ebp
    29494     c3/return
    29495
    29496 translate-mu-index-stmt-with-array-in-register:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
    29497     # . prologue
    29498     55/push-ebp
    29499     89/<- %ebp 4/r32/esp
    29500     # . save registers
    29501     50/push-eax
    29502     51/push-ecx
    29503     52/push-edx
    29504     53/push-ebx
    29505     # ecx = stmt
    29506     8b/-> *(ebp+0xc) 1/r32/ecx
    29507     # var base/ebx: (addr var) = inouts[0]
    29508     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    29509     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    29510     89/<- %ebx 0/r32/eax
    29511     # emit null check
    29512     (emit-indent *(ebp+8) *Curr-block-depth)
    29513     (write-buffered *(ebp+8) "81 7/subop/compare %")
    29514     (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
    29515     (write-buffered *(ebp+8) %eax)
    29516     (write-buffered *(ebp+8) " 0/imm32\n")
    29517     (emit-indent *(ebp+8) *Curr-block-depth)
    29518     (write-buffered *(ebp+8) "0f 84/jump-if-= __mu-abort-null-index-base-address/disp32\n")
    29519     #
    29520     (emit-indent *(ebp+8) *Curr-block-depth)
    29521     (write-buffered *(ebp+8) "8d/copy-address *(")
    29522     # TODO: ensure inouts[0] is in a register and not dereferenced
    29523 $translate-mu-index-stmt-with-array-in-register:emit-base:
    29524     # print base->register " + "
    29525     (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
    29526     (write-buffered *(ebp+8) %eax)
    29527     (write-buffered *(ebp+8) " + ")
    29528     # var index/edx: (addr var) = inouts[1]
    29529     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    29530     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    29531     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    29532     89/<- %edx 0/r32/eax
    29533     # if index->register
    29534     81 7/subop/compare *(edx+0x18) 0/imm32  # Var-register
    29535     {
    29536       0f 84/jump-if-= break/disp32
    29537 $translate-mu-index-stmt-with-array-in-register:emit-register-index:
    29538       # if index is an int
    29539       (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
    29540       (simple-mu-type? %eax 1)  # int => 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-int-register-index:
    29545         # print index->register "<<" log2(array-element-size(base)) " + 4) "
    29546         # . index->register "<<"
    29547         (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
    29548         (write-buffered *(ebp+8) %eax)
    29549         (write-buffered *(ebp+8) "<<")
    29550         # . log2(array-element-size(base->type))
    29551         # we know size is a power of 2
    29552         (array-element-size %ebx *(ebp+0x10) *(ebp+0x14))  # => eax
    29553         (num-shift-rights %eax)  # => eax
    29554         (write-int32-hex-buffered *(ebp+8) %eax)
    29555         e9/jump $translate-mu-index-stmt-with-array-in-register:emit-register-index-done/disp32
    29556       }
    29557       # if index->type is any other atom, abort
    29558       (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
    29559       81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
    29560       0f 85/jump-if-!= $translate-mu-index-stmt:error2/disp32
    29561       # if index has type (offset ...)
    29562       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    29563       (simple-mu-type? %eax 7)  # => eax
    29564       3d/compare-eax-and 0/imm32/false
    29565       {
    29566         0f 84/jump-if-= break/disp32
    29567         # print index->register
    29568 $translate-mu-index-stmt-with-array-in-register:emit-offset-register-index:
    29569         (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
    29570         (write-buffered *(ebp+8) %eax)
    29571       }
    29572 $translate-mu-index-stmt-with-array-in-register:emit-register-index-done:
    29573       (write-buffered *(ebp+8) " + 4) ")
    29574       e9/jump $translate-mu-index-stmt-with-array-in-register:emit-output/disp32
    29575     }
    29576     # otherwise if index is a literal
    29577     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
    29578     (simple-mu-type? %eax 0)  # => eax
    29579     3d/compare-eax-and 0/imm32/false
    29580     {
    29581       0f 84/jump-if-= break/disp32
    29582 $translate-mu-index-stmt-with-array-in-register:emit-literal-index:
    29583       # var index-value/edx: int = parse-hex-int(index->name)
    29584       (lookup *edx *(edx+4))  # Var-name Var-name => eax
    29585       (parse-hex-int %eax)  # => eax
    29586       89/<- %edx 0/r32/eax
    29587       # offset = idx-value * array-element-size(base->type)
    29588       (array-element-size %ebx *(ebp+0x10) *(ebp+0x14))  # => eax
    29589       f7 4/subop/multiply-into-edx-eax %edx  # clobbers edx
    29590       # offset += 4 for array size
    29591       05/add-to-eax 4/imm32
    29592       # TODO: check edx for overflow
    29593       # print offset
    29594       (write-int32-hex-buffered *(ebp+8) %eax)
    29595       (write-buffered *(ebp+8) ") ")
    29596       e9/jump $translate-mu-index-stmt-with-array-in-register:emit-output/disp32
    29597     }
    29598     # otherwise abort
    29599     e9/jump $translate-mu-index-stmt:error1/disp32
    29600 $translate-mu-index-stmt-with-array-in-register:emit-output:
    29601     # outputs[0] "/r32"
    29602     8b/-> *(ebp+0xc) 1/r32/ecx
    29603     (lookup *(ecx+0x14) *(ecx+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    29604     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    29605     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    29606     (get Mu-registers %eax 0xc "Mu-registers")  # => eax: (addr int)
    29607     (write-int32-hex-buffered *(ebp+8) *eax)
    29608     (write-buffered *(ebp+8) "/r32\n")
    29609 $translate-mu-index-stmt-with-array-in-register:end:
    29610     # . restore registers
    29611     5b/pop-to-ebx
    29612     5a/pop-to-edx
    29613     59/pop-to-ecx
    29614     58/pop-to-eax
    29615     # . epilogue
    29616     89/<- %esp 5/r32/ebp
    29617     5d/pop-to-ebp
    29618     c3/return
    29619
    29620 translate-mu-index-stmt-with-array-on-stack:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
    29621     # . prologue
    29622     55/push-ebp
    29623     89/<- %ebp 4/r32/esp
    29624     # . save registers
    29625     50/push-eax
    29626     51/push-ecx
    29627     52/push-edx
    29628     53/push-ebx
    29629     #
    29630     (emit-indent *(ebp+8) *Curr-block-depth)
    29631     (write-buffered *(ebp+8) "8d/copy-address *(ebp + ")
    29632     # var curr/edx: (addr stmt-var) = lookup(stmt->inouts)
    29633     8b/-> *(ebp+0xc) 0/r32/eax
    29634     (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    29635     89/<- %edx 0/r32/eax
    29636     # var base/ecx: (addr var) = lookup(curr->value)
    29637     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    29638     89/<- %ecx 0/r32/eax
    29639     # var curr2/eax: (addr stmt-var) = lookup(curr->next)
    29640     (lookup *(edx+8) *(edx+0xc))  # Stmt-var-next Stmt-var-next => eax
    29641     # var index/edx: (handle var) = curr2->value
    29642     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    29643     89/<- %edx 0/r32/eax
    29644     # if index->register
    29645     81 7/subop/compare *(edx+0x18) 0/imm32  # Var-register
    29646     {
    29647       0f 84/jump-if-= break/disp32
    29648 $translate-mu-index-stmt-with-array-on-stack:emit-register-index:
    29649       # if index is an int
    29650       (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
    29651       (simple-mu-type? %eax 1)  # int => eax
    29652       3d/compare-eax-and 0/imm32/false
    29653       {
    29654         0f 84/jump-if-= break/disp32
    29655 $translate-mu-index-stmt-with-array-on-stack:emit-int-register-index:
    29656         # print index->register "<<" log2(array-element-size(base)) " + " base->offset+4
    29657         # . inouts[1]->register "<<"
    29658         (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
    29659         (write-buffered *(ebp+8) %eax)
    29660         (write-buffered *(ebp+8) "<<")
    29661         # . log2(array-element-size(base))
    29662         # TODO: ensure size is a power of 2
    29663         (array-element-size %ecx *(ebp+0x10) *(ebp+0x14))  # => eax
    29664         (num-shift-rights %eax)  # => eax
    29665         (write-int32-hex-buffered *(ebp+8) %eax)
    29666         #
    29667         (write-buffered *(ebp+8) " + ")
    29668         #
    29669         8b/-> *(ecx+0x14) 0/r32/eax  # Var-offset
    29670         05/add-to-eax 4/imm32  # for array length
    29671         (write-int32-hex-buffered *(ebp+8) %eax)
    29672         e9/jump $translate-mu-index-stmt-with-array-on-stack:emit-register-index-done/disp32
    29673       }
    29674       # if index->type is any other atom, abort
    29675       (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
    29676       81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
    29677       0f 85/jump-if-!= $translate-mu-index-stmt:error2/disp32
    29678       # if index has type (offset ...)
    29679       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    29680       (simple-mu-type? %eax 7)  # => eax
    29681       3d/compare-eax-and 0/imm32/false
    29682       {
    29683         0f 84/jump-if-= break/disp32
    29684         # print index->register
    29685 $translate-mu-index-stmt-with-array-on-stack:emit-offset-register-index:
    29686         (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
    29687         (write-buffered *(ebp+8) %eax)
    29688       }
    29689 $translate-mu-index-stmt-with-array-on-stack:emit-register-index-done:
    29690       (write-buffered *(ebp+8) ") ")
    29691       e9/jump $translate-mu-index-stmt-with-array-on-stack:emit-output/disp32
    29692     }
    29693     # otherwise if index is a literal
    29694     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
    29695     (simple-mu-type? %eax 0)  # => eax
    29696     3d/compare-eax-and 0/imm32/false
    29697     {
    29698       0f 84/jump-if-= break/disp32
    29699 $translate-mu-index-stmt-with-array-on-stack:emit-literal-index:
    29700       # var idx-value/edx: int = parse-hex-int(index->name)
    29701       (lookup *edx *(edx+4))  # Var-name Var-name => eax
    29702       (parse-hex-int %eax)  # Var-name => eax
    29703       89/<- %edx 0/r32/eax
    29704       # offset = idx-value * array-element-size(base)
    29705       (array-element-size %ecx *(ebp+0x10) *(ebp+0x14))  # => eax
    29706       f7 4/subop/multiply-into-edx-eax %edx  # clobbers edx
    29707       # offset += base->offset
    29708       03/add *(ecx+0x14) 0/r32/eax  # Var-offset
    29709       # offset += 4 for array size
    29710       05/add-to-eax 4/imm32
    29711       # TODO: check edx for overflow
    29712       # print offset
    29713       (write-int32-hex-buffered *(ebp+8) %eax)
    29714       (write-buffered *(ebp+8) ") ")
    29715       e9/jump $translate-mu-index-stmt-with-array-on-stack:emit-output/disp32
    29716     }
    29717     # otherwise abort
    29718     e9/jump $translate-mu-index-stmt:error1/disp32
    29719 $translate-mu-index-stmt-with-array-on-stack:emit-output:
    29720     # outputs[0] "/r32"
    29721     8b/-> *(ebp+0xc) 0/r32/eax
    29722     (lookup *(eax+0x14) *(eax+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    29723     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    29724     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    29725     (get Mu-registers %eax 0xc "Mu-registers")  # => eax: (addr int)
    29726     (write-int32-hex-buffered *(ebp+8) *eax)
    29727     (write-buffered *(ebp+8) "/r32\n")
    29728 $translate-mu-index-stmt-with-array-on-stack:end:
    29729     # . restore registers
    29730     5b/pop-to-ebx
    29731     5a/pop-to-edx
    29732     59/pop-to-ecx
    29733     58/pop-to-eax
    29734     # . epilogue
    29735     89/<- %esp 5/r32/ebp
    29736     5d/pop-to-ebp
    29737     c3/return
    29738
    29739 translate-mu-compute-index-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
    29740     # . prologue
    29741     55/push-ebp
    29742     89/<- %ebp 4/r32/esp
    29743     # . save registers
    29744     50/push-eax
    29745     51/push-ecx
    29746     52/push-edx
    29747     53/push-ebx
    29748     #
    29749     (emit-indent *(ebp+8) *Curr-block-depth)
    29750     (write-buffered *(ebp+8) "69/multiply")
    29751     # ecx = stmt
    29752     8b/-> *(ebp+0xc) 1/r32/ecx
    29753     # var first-inout/ebx: (addr stmt-var) = stmt->inouts[0]
    29754     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    29755     89/<- %ebx 0/r32/eax
    29756 $translate-mu-compute-index-stmt:emit-index:
    29757     (lookup *(ebx+8) *(ebx+0xc))  # Stmt-var-next Stmt-var-next => eax
    29758     (emit-subx-var-as-rm32 *(ebp+8) %eax)
    29759     (write-buffered *(ebp+8) Space)
    29760 $translate-mu-compute-index-stmt:emit-elem-size:
    29761     # var base/ebx: (addr var)
    29762     (lookup *ebx *(ebx+4))  # Stmt-var-value Stmt-var-value => eax
    29763     89/<- %ebx 0/r32/eax
    29764     # print array-element-size(base)
    29765     (array-element-size %ebx *(ebp+0x10) *(ebp+0x14))  # => eax
    29766     (write-int32-hex-buffered *(ebp+8) %eax)
    29767     (write-buffered *(ebp+8) "/imm32 ")
    29768 $translate-mu-compute-index-stmt:emit-output:
    29769     # outputs[0] "/r32"
    29770     (lookup *(ecx+0x14) *(ecx+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    29771     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    29772     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    29773     (get Mu-registers %eax 0xc "Mu-registers")  # => eax: (addr int)
    29774     (write-int32-hex-buffered *(ebp+8) *eax)
    29775     (write-buffered *(ebp+8) "/r32\n")
    29776 $translate-mu-compute-index-stmt:end:
    29777     # . restore registers
    29778     5b/pop-to-ebx
    29779     5a/pop-to-edx
    29780     59/pop-to-ecx
    29781     58/pop-to-eax
    29782     # . epilogue
    29783     89/<- %esp 5/r32/ebp
    29784     5d/pop-to-ebp
    29785     c3/return
    29786
    29787 translate-mu-get-stmt:  # out: (addr buffered-file), stmt: (addr stmt)
    29788     # . prologue
    29789     55/push-ebp
    29790     89/<- %ebp 4/r32/esp
    29791     # . save registers
    29792     50/push-eax
    29793     51/push-ecx
    29794     52/push-edx
    29795     # ecx = stmt
    29796     8b/-> *(ebp+0xc) 1/r32/ecx
    29797     # var base/eax: (addr var) = stmt->inouts->value
    29798     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    29799     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    29800     # if base is in a register, insert a null check
    29801     81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
    29802     {
    29803       0f 84/jump-if-= break/disp32
    29804 $translate-mu-get-stmt:emit-null-check-for-register-input:
    29805       # emit "81 7/subop/compare %" base->register " 0/imm32\n"
    29806       (emit-indent *(ebp+8) *Curr-block-depth)
    29807       (write-buffered *(ebp+8) "81 7/subop/compare %")
    29808       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    29809       (write-buffered *(ebp+8) %eax)
    29810       (write-buffered *(ebp+8) " 0/imm32\n")
    29811       #
    29812       (emit-indent *(ebp+8) *Curr-block-depth)
    29813       (write-buffered *(ebp+8) "0f 84/jump-if-= __mu-abort-null-get-base-address/disp32\n")
    29814     }
    29815     # var offset/edx: int = get offset of stmt
    29816     (mu-get-offset %ecx)  # => eax
    29817     89/<- %edx 0/r32/eax
    29818     # var base/eax: (addr var) = stmt->inouts->value
    29819     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    29820     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    29821     #
    29822     (emit-indent *(ebp+8) *Curr-block-depth)
    29823     (write-buffered *(ebp+8) "8d/copy-address ")
    29824     # if base is in a register
    29825     81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
    29826     {
    29827       0f 84/jump-if-= break/disp32
    29828 $translate-mu-get-stmt:emit-register-input:
    29829       # emit "*(" base->register " + " offset ") "
    29830       (write-buffered *(ebp+8) "*(")
    29831       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    29832       (write-buffered *(ebp+8) %eax)
    29833       (write-buffered *(ebp+8) " + ")
    29834       (write-int32-hex-buffered *(ebp+8) %edx)
    29835       (write-buffered *(ebp+8) ") ")
    29836       e9/jump $translate-mu-get-stmt:emit-output/disp32
    29837     }
    29838     # otherwise base is on the stack
    29839     {
    29840 $translate-mu-get-stmt:emit-stack-input:
    29841       # emit "*(ebp + " inouts[0]->stack-offset + offset ") "
    29842       (write-buffered *(ebp+8) "*(ebp+")
    29843       03/add *(eax+0x14) 2/r32/edx  # Var-offset
    29844       (write-int32-hex-buffered *(ebp+8) %edx)
    29845       (write-buffered *(ebp+8) ") ")
    29846       eb/jump $translate-mu-get-stmt:emit-output/disp8
    29847     }
    29848 $translate-mu-get-stmt:emit-output:
    29849     # var output/eax: (addr var) = stmt->outputs->value
    29850     (lookup *(ecx+0x14) *(ecx+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    29851     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    29852     # emit offset->register "/r32"
    29853     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    29854     (get Mu-registers %eax 0xc "Mu-registers")  # => eax: (addr int)
    29855     (write-int32-hex-buffered *(ebp+8) *eax)
    29856     (write-buffered *(ebp+8) "/r32\n")
    29857 $translate-mu-get-stmt:end:
    29858     # . restore registers
    29859     5a/pop-to-edx
    29860     59/pop-to-ecx
    29861     58/pop-to-eax
    29862     # . epilogue
    29863     89/<- %esp 5/r32/ebp
    29864     5d/pop-to-ebp
    29865     c3/return
    29866
    29867 translate-mu-copy-object-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
    29868     # . prologue
    29869     55/push-ebp
    29870     89/<- %ebp 4/r32/esp
    29871     # . save registers
    29872     50/push-eax
    29873     #
    29874     (emit-indent *(ebp+8) *Curr-block-depth)
    29875     (write-buffered *(ebp+8) "(copy-bytes")
    29876     # eax = stmt
    29877     8b/-> *(ebp+0xc) 0/r32/eax
    29878     # var first-inout/eax: (addr stmt-var) = stmt->inouts[0]
    29879     (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    29880     (emit-subx-call-operand *(ebp+8) %eax)
    29881     # var second-inout/eax: (addr stmt-var) = stmt->inouts[1]
    29882     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    29883     (emit-subx-call-operand *(ebp+8) %eax)
    29884     # emit size of inouts
    29885     (write-buffered *(ebp+8) Space)
    29886     (addr-payload-size %eax *(ebp+0x10) *(ebp+0x14))  # => eax
    29887     (write-int32-hex-buffered *(ebp+8) %eax)
    29888     (write-buffered *(ebp+8) ")\n")
    29889 $translate-mu-copy-object-stmt:end:
    29890     # . restore registers
    29891     58/pop-to-eax
    29892     # . epilogue
    29893     89/<- %esp 5/r32/ebp
    29894     5d/pop-to-ebp
    29895     c3/return
    29896
    29897 translate-mu-clear-object-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
    29898     # . prologue
    29899     55/push-ebp
    29900     89/<- %ebp 4/r32/esp
    29901     # . save registers
    29902     50/push-eax
    29903     #
    29904     (emit-indent *(ebp+8) *Curr-block-depth)
    29905     (write-buffered *(ebp+8) "(zero-out")
    29906     # eax = stmt
    29907     8b/-> *(ebp+0xc) 0/r32/eax
    29908     # var dest/eax: (addr stmt-var) = stmt->inouts[0]
    29909     (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    29910     #
    29911     (emit-subx-call-operand *(ebp+8) %eax)
    29912     (write-buffered *(ebp+8) Space)
    29913     (addr-payload-size %eax *(ebp+0x10) *(ebp+0x14))  # => eax
    29914     (write-int32-hex-buffered *(ebp+8) %eax)
    29915     (write-buffered *(ebp+8) ")\n")
    29916 $translate-mu-clear-object-stmt:end:
    29917     # . restore registers
    29918     58/pop-to-eax
    29919     # . epilogue
    29920     89/<- %esp 5/r32/ebp
    29921     5d/pop-to-ebp
    29922     c3/return
    29923
    29924 translate-mu-allocate-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
    29925     # . prologue
    29926     55/push-ebp
    29927     89/<- %ebp 4/r32/esp
    29928     # . save registers
    29929     50/push-eax
    29930     56/push-esi
    29931     57/push-edi
    29932     # esi = stmt
    29933     8b/-> *(ebp+0xc) 6/r32/esi
    29934     # var target/edi: (addr stmt-var) = stmt->inouts[0]
    29935     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    29936     89/<- %edi 0/r32/eax
    29937     #
    29938     (emit-indent *(ebp+8) *Curr-block-depth)
    29939     (write-buffered *(ebp+8) "(allocate Heap ")
    29940     (addr-handle-payload-size %edi *(ebp+0x10) *(ebp+0x14))  # => eax
    29941     (write-int32-hex-buffered *(ebp+8) %eax)
    29942     (emit-subx-call-operand *(ebp+8) %edi)
    29943     (write-buffered *(ebp+8) ")\n")
    29944 $translate-mu-allocate-stmt:end:
    29945     # . restore registers
    29946     5f/pop-to-edi
    29947     5e/pop-to-esi
    29948     58/pop-to-eax
    29949     # . epilogue
    29950     89/<- %esp 5/r32/ebp
    29951     5d/pop-to-ebp
    29952     c3/return
    29953
    29954 addr-handle-payload-size:  # s: (addr stmt-var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
    29955     # . prologue
    29956     55/push-ebp
    29957     89/<- %ebp 4/r32/esp
    29958     # var t/eax: (addr type-tree) = s->value->type
    29959     8b/-> *(ebp+8) 0/r32/eax
    29960     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    29961     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    29962     # TODO: check eax != 0
    29963     # TODO: check !t->is-atom?
    29964     # TODO: check t->left == addr
    29965     # t = t->right
    29966 $addr-handle-payload-size:skip-addr:
    29967     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
    29968     # TODO: check eax != 0
    29969     # TODO: check !t->is-atom?
    29970     # TODO: check t->left == handle
    29971     # t = t->right
    29972 $addr-handle-payload-size:skip-handle:
    29973     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
    29974     # TODO: check eax != 0
    29975     # if !t->is-atom? t = t->left
    29976     81 7/subop/compare *eax 0/imm32/false
    29977     {
    29978       75/jump-if-!= break/disp8
    29979       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    29980     }
    29981     # TODO: check t->is-atom?
    29982     # return size(t->value)
    29983     (size-of-type-id *(eax+4))  # Type-tree-value => eax
    29984 $addr-handle-payload-size:end:
    29985     # . epilogue
    29986     89/<- %esp 5/r32/ebp
    29987     5d/pop-to-ebp
    29988     c3/return
    29989
    29990 addr-payload-size:  # s: (addr stmt-var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
    29991     # . prologue
    29992     55/push-ebp
    29993     89/<- %ebp 4/r32/esp
    29994     # var t/eax: (addr type-tree) = s->value->type
    29995     8b/-> *(ebp+8) 0/r32/eax
    29996     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    29997     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    29998     # TODO: check eax != 0
    29999     # TODO: check !t->is-atom?
    30000     # TODO: check t->left == addr
    30001     # t = t->right
    30002 $addr-payload-size:skip-addr:
    30003     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
    30004     # TODO: check eax != 0
    30005     # if !t->is-atom? t = t->left
    30006     81 7/subop/compare *eax 0/imm32/false
    30007     {
    30008       75/jump-if-!= break/disp8
    30009       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    30010     }
    30011     # TODO: check t->is-atom?
    30012     # return size(t->value)
    30013     (size-of-type-id *(eax+4))  # Type-tree-value => eax
    30014 $addr-payload-size:end:
    30015     # . epilogue
    30016     89/<- %esp 5/r32/ebp
    30017     5d/pop-to-ebp
    30018     c3/return
    30019
    30020 translate-mu-populate-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
    30021     # . prologue
    30022     55/push-ebp
    30023     89/<- %ebp 4/r32/esp
    30024     # . save registers
    30025     50/push-eax
    30026     51/push-ecx
    30027     56/push-esi
    30028     57/push-edi
    30029     # esi = stmt
    30030     8b/-> *(ebp+0xc) 6/r32/esi
    30031     # var target/edi: (addr stmt-var) = stmt->inouts[0]
    30032     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    30033     89/<- %edi 0/r32/eax
    30034     # var len/ecx: (addr stmt-var) = stmt->inouts[1]
    30035     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
    30036     89/<- %ecx 0/r32/eax
    30037     #
    30038     (emit-indent *(ebp+8) *Curr-block-depth)
    30039     (write-buffered *(ebp+8) "(allocate-array2 Heap ")
    30040     (addr-handle-array-payload-size %edi *(ebp+0x10) *(ebp+0x14))  # => eax
    30041     (write-int32-hex-buffered *(ebp+8) %eax)
    30042     (emit-subx-call-operand *(ebp+8) %ecx)
    30043     (emit-subx-call-operand *(ebp+8) %edi)
    30044     (write-buffered *(ebp+8) ")\n")
    30045 $translate-mu-populate-stmt:end:
    30046     # . restore registers
    30047     5f/pop-to-edi
    30048     5e/pop-to-esi
    30049     59/pop-to-ecx
    30050     58/pop-to-eax
    30051     # . epilogue
    30052     89/<- %esp 5/r32/ebp
    30053     5d/pop-to-ebp
    30054     c3/return
    30055
    30056 translate-mu-populate-stream-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
    30057     # . prologue
    30058     55/push-ebp
    30059     89/<- %ebp 4/r32/esp
    30060     # . save registers
    30061     50/push-eax
    30062     51/push-ecx
    30063     56/push-esi
    30064     57/push-edi
    30065     # esi = stmt
    30066     8b/-> *(ebp+0xc) 6/r32/esi
    30067     # var target/edi: (addr stmt-var) = stmt->inouts[0]
    30068     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    30069     89/<- %edi 0/r32/eax
    30070     # var len/ecx: (addr stmt-var) = stmt->inouts[1]
    30071     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
    30072     89/<- %ecx 0/r32/eax
    30073     #
    30074     (emit-indent *(ebp+8) *Curr-block-depth)
    30075     (write-buffered *(ebp+8) "(new-stream Heap ")
    30076     (addr-handle-stream-payload-size %edi *(ebp+0x10) *(ebp+0x14))  # => eax
    30077     (write-int32-hex-buffered *(ebp+8) %eax)
    30078     (emit-subx-call-operand *(ebp+8) %ecx)
    30079     (emit-subx-call-operand *(ebp+8) %edi)
    30080     (write-buffered *(ebp+8) ")\n")
    30081 $translate-mu-populate-stream-stmt:end:
    30082     # . restore registers
    30083     5f/pop-to-edi
    30084     5e/pop-to-esi
    30085     59/pop-to-ecx
    30086     58/pop-to-eax
    30087     # . epilogue
    30088     89/<- %esp 5/r32/ebp
    30089     5d/pop-to-ebp
    30090     c3/return
    30091
    30092 translate-mu-read-from-stream-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
    30093     # . prologue
    30094     55/push-ebp
    30095     89/<- %ebp 4/r32/esp
    30096     # . save registers
    30097     50/push-eax
    30098     51/push-ecx
    30099     56/push-esi
    30100     57/push-edi
    30101     # esi = stmt
    30102     8b/-> *(ebp+0xc) 6/r32/esi
    30103     # var stream/ecx: (addr stmt-var) = stmt->inouts[0]
    30104     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    30105     89/<- %ecx 0/r32/eax
    30106     # var target/edi: (addr stmt-var) = stmt->inouts[1]
    30107     (lookup *(ecx+8) *(ecx+0xc))  # Stmt-var-next Stmt-var-next => eax
    30108     89/<- %edi 0/r32/eax
    30109     #
    30110     (emit-indent *(ebp+8) *Curr-block-depth)
    30111     (write-buffered *(ebp+8) "(read-from-stream")
    30112     (emit-subx-call-operand *(ebp+8) %ecx)
    30113     (emit-subx-call-operand *(ebp+8) %edi)
    30114     (write-buffered *(ebp+8) Space)
    30115     (addr-payload-size %edi *(ebp+0x10) *(ebp+0x14))  # => eax
    30116     (write-int32-hex-buffered *(ebp+8) %eax)
    30117     (write-buffered *(ebp+8) ")\n")
    30118 $translate-mu-read-from-stream-stmt:end:
    30119     # . restore registers
    30120     5f/pop-to-edi
    30121     5e/pop-to-esi
    30122     59/pop-to-ecx
    30123     58/pop-to-eax
    30124     # . epilogue
    30125     89/<- %esp 5/r32/ebp
    30126     5d/pop-to-ebp
    30127     c3/return
    30128
    30129 translate-mu-write-to-stream-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
    30130     # . prologue
    30131     55/push-ebp
    30132     89/<- %ebp 4/r32/esp
    30133     # . save registers
    30134     50/push-eax
    30135     51/push-ecx
    30136     56/push-esi
    30137     57/push-edi
    30138     # esi = stmt
    30139     8b/-> *(ebp+0xc) 6/r32/esi
    30140     # var stream/ecx: (addr stmt-var) = stmt->inouts[0]
    30141     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    30142     89/<- %ecx 0/r32/eax
    30143     # var target/edi: (addr stmt-var) = stmt->inouts[1]
    30144     (lookup *(ecx+8) *(ecx+0xc))  # Stmt-var-next Stmt-var-next => eax
    30145     89/<- %edi 0/r32/eax
    30146     #
    30147     (emit-indent *(ebp+8) *Curr-block-depth)
    30148     (write-buffered *(ebp+8) "(write-to-stream")
    30149     (emit-subx-call-operand *(ebp+8) %ecx)
    30150     (flush *(ebp+8))
    30151     (emit-subx-call-operand *(ebp+8) %edi)
    30152     (flush *(ebp+8))
    30153     (write-buffered *(ebp+8) Space)
    30154     (flush *(ebp+8))
    30155     (addr-payload-size %edi *(ebp+0x10) *(ebp+0x14))  # => eax
    30156     (write-int32-hex-buffered *(ebp+8) %eax)
    30157     (write-buffered *(ebp+8) ")\n")
    30158 $translate-mu-write-to-stream-stmt:end:
    30159     # . restore registers
    30160     5f/pop-to-edi
    30161     5e/pop-to-esi
    30162     59/pop-to-ecx
    30163     58/pop-to-eax
    30164     # . epilogue
    30165     89/<- %esp 5/r32/ebp
    30166     5d/pop-to-ebp
    30167     c3/return
    30168
    30169 addr-handle-array-payload-size:  # s: (addr stmt-var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
    30170     # . prologue
    30171     55/push-ebp
    30172     89/<- %ebp 4/r32/esp
    30173     # var t/eax: (addr type-tree) = s->value->type
    30174     8b/-> *(ebp+8) 0/r32/eax
    30175     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    30176     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    30177     # TODO: check eax != 0
    30178     # TODO: check !t->is-atom?
    30179     # TODO: check t->left == addr
    30180     # t = t->right
    30181 $addr-handle-array-payload-size:skip-addr:
    30182     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
    30183     # TODO: check eax != 0
    30184     # TODO: check !t->is-atom?
    30185     # TODO: check t->left == handle
    30186     # t = t->right
    30187 $addr-handle-array-payload-size:skip-handle:
    30188     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
    30189     # TODO: check eax != 0
    30190     # TODO: check !t->is-atom?
    30191     # TODO: check t->left == array
    30192     # t = t->right
    30193 $addr-handle-array-payload-size:skip-array:
    30194     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
    30195     # TODO: check eax != 0
    30196     # if !t->is-atom? t = t->left
    30197     81 7/subop/compare *eax 0/imm32/false
    30198     {
    30199       75/jump-if-!= break/disp8
    30200       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    30201     }
    30202 $addr-handle-array-payload-size:compute-size:
    30203     # TODO: check t->is-atom?
    30204     # return size(t->value)
    30205     (size-of-type-id-as-array-element *(eax+4))  # Type-tree-value => eax
    30206 $addr-handle-array-payload-size:end:
    30207     # . epilogue
    30208     89/<- %esp 5/r32/ebp
    30209     5d/pop-to-ebp
    30210     c3/return
    30211
    30212 addr-handle-stream-payload-size:  # s: (addr stmt-var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
    30213     # . prologue
    30214     55/push-ebp
    30215     89/<- %ebp 4/r32/esp
    30216     # var t/eax: (addr type-tree) = s->value->type
    30217     8b/-> *(ebp+8) 0/r32/eax
    30218     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    30219     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    30220     # TODO: check eax != 0
    30221     # TODO: check !t->is-atom?
    30222     # TODO: check t->left == addr
    30223     # t = t->right
    30224 $addr-handle-stream-payload-size:skip-addr:
    30225     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
    30226     # TODO: check eax != 0
    30227     # TODO: check !t->is-atom?
    30228     # TODO: check t->left == handle
    30229     # t = t->right
    30230 $addr-handle-stream-payload-size:skip-handle:
    30231     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
    30232     # TODO: check eax != 0
    30233     # TODO: check !t->is-atom?
    30234     # TODO: check t->left == stream
    30235     # t = t->right
    30236 $addr-handle-stream-payload-size:skip-stream:
    30237     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
    30238     # TODO: check eax != 0
    30239     # if !t->is-atom? t = t->left
    30240     81 7/subop/compare *eax 0/imm32/false
    30241     {
    30242       75/jump-if-!= break/disp8
    30243       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    30244     }
    30245 $addr-handle-stream-payload-size:compute-size:
    30246     # TODO: check t->is-atom?
    30247     # return size(t->value)
    30248     (size-of-type-id-as-array-element *(eax+4))  # Type-tree-value => eax
    30249 $addr-handle-stream-payload-size:end:
    30250     # . epilogue
    30251     89/<- %esp 5/r32/ebp
    30252     5d/pop-to-ebp
    30253     c3/return
    30254
    30255 power-of-2?:  # n: int, err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: boolean
    30256     # precondition: n is positive
    30257     # . prologue
    30258     55/push-ebp
    30259     89/<- %ebp 4/r32/esp
    30260     # eax = n
    30261     8b/-> *(ebp+8) 0/r32/eax
    30262     # if (n < 0) abort
    30263     3d/compare-eax-with 0/imm32
    30264     0f 8c/jump-if-< $power-of-2?:abort/disp32
    30265     # var tmp/eax: int = n-1
    30266     48/decrement-eax
    30267     # var tmp2/eax: int = n & tmp
    30268     23/and-> *(ebp+8) 0/r32/eax
    30269     # return (tmp2 == 0)
    30270     3d/compare-eax-and 0/imm32
    30271     0f 94/set-byte-if-= %al
    30272     25/and-eax-with 0xff/imm32
    30273 $power-of-2?:end:
    30274     # . epilogue
    30275     89/<- %esp 5/r32/ebp
    30276     5d/pop-to-ebp
    30277     c3/return
    30278
    30279 $power-of-2?:abort:
    30280     (write-buffered *(ebp+0xc) "power-of-2?: negative number\n")
    30281     (flush *(ebp+0xc))
    30282     (stop *(ebp+0x10) 1)
    30283     # never gets here
    30284
    30285 num-shift-rights:  # n: int -> result/eax: int
    30286     # precondition: n is a positive power of 2
    30287     # . prologue
    30288     55/push-ebp
    30289     89/<- %ebp 4/r32/esp
    30290     # . save registers
    30291     51/push-ecx
    30292     # var curr/ecx: int = n
    30293     8b/-> *(ebp+8) 1/r32/ecx
    30294     # result = 0
    30295     b8/copy-to-eax 0/imm32
    30296     {
    30297       # if (curr <= 1) break
    30298       81 7/subop/compare %ecx 1/imm32
    30299       7e/jump-if-<= break/disp8
    30300       40/increment-eax
    30301       c1/shift 5/subop/arithmetic-right %ecx 1/imm8
    30302       eb/jump loop/disp8
    30303     }
    30304 $num-shift-rights:end:
    30305     # . restore registers
    30306     59/pop-to-ecx
    30307     # . epilogue
    30308     89/<- %esp 5/r32/ebp
    30309     5d/pop-to-ebp
    30310     c3/return
    30311
    30312 mu-get-offset:  # stmt: (addr stmt) -> result/eax: int
    30313     # . prologue
    30314     55/push-ebp
    30315     89/<- %ebp 4/r32/esp
    30316     # var second-inout/eax: (addr stmt-var) = stmt->inouts->next
    30317     8b/-> *(ebp+8) 0/r32/eax
    30318     (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    30319     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    30320     # var output-var/eax: (addr var) = second-inout->value
    30321     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    30322 #?     (write-buffered Stderr "mu-get-offset: ")
    30323 #?     (write-int32-hex-buffered Stderr %eax)
    30324 #?     (write-buffered Stderr " name: ")
    30325 #?     50/push-eax
    30326 #?     (lookup *eax *(eax+4))  # Var-name
    30327 #?     (write-buffered Stderr %eax)
    30328 #?     58/pop-to-eax
    30329 #?     (write-buffered Stderr Newline)
    30330 #?     (flush Stderr)
    30331     # return output-var->stack-offset
    30332     8b/-> *(eax+0x14) 0/r32/eax  # Var-offset
    30333 #?     (write-buffered Stderr "=> ")
    30334 #?     (write-int32-hex-buffered Stderr %eax)
    30335 #?     (write-buffered Stderr Newline)
    30336 #?     (flush Stderr)
    30337 $emit-get-offset:end:
    30338     # . epilogue
    30339     89/<- %esp 5/r32/ebp
    30340     5d/pop-to-ebp
    30341     c3/return
    30342
    30343 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)
    30344     # . prologue
    30345     55/push-ebp
    30346     89/<- %ebp 4/r32/esp
    30347     # . save registers
    30348     50/push-eax
    30349     51/push-ecx
    30350     56/push-esi
    30351     # esi = block
    30352     8b/-> *(ebp+0xc) 6/r32/esi
    30353     # block->var->block-depth = *Curr-block-depth
    30354     (lookup *(esi+0xc) *(esi+0x10))  # Block-var Block-var => eax
    30355     8b/-> *Curr-block-depth 1/r32/ecx
    30356     89/<- *(eax+0x10) 1/r32/ecx  # Var-block-depth
    30357     # var stmts/eax: (addr list stmt) = lookup(block->statements)
    30358     (lookup *(esi+4) *(esi+8))  # Block-stmts Block-stmts => eax
    30359     #
    30360     {
    30361 $emit-subx-block:check-empty:
    30362       3d/compare-eax-and 0/imm32
    30363       0f 84/jump-if-= break/disp32
    30364       (emit-indent *(ebp+8) *Curr-block-depth)
    30365       (write-buffered *(ebp+8) "{\n")
    30366       # var v/ecx: (addr var) = lookup(block->var)
    30367       (lookup *(esi+0xc) *(esi+0x10))  # Block-var Block-var => eax
    30368       89/<- %ecx 0/r32/eax
    30369       #
    30370       (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    30371       (write-buffered *(ebp+8) %eax)
    30372       (write-buffered *(ebp+8) ":loop:\n")
    30373       ff 0/subop/increment *Curr-block-depth
    30374       (push *(ebp+0x10) *(esi+0xc))  # Block-var
    30375       (push *(ebp+0x10) *(esi+0x10))  # Block-var
    30376       (push *(ebp+0x10) 0)  # false
    30377       # emit block->statements
    30378       (lookup *(esi+4) *(esi+8))  # Block-stmts Block-stmts => eax
    30379       (emit-subx-stmt-list *(ebp+8) %eax *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
    30380       (pop *(ebp+0x10))  # => eax
    30381       (pop *(ebp+0x10))  # => eax
    30382       (pop *(ebp+0x10))  # => eax
    30383       ff 1/subop/decrement *Curr-block-depth
    30384       (emit-indent *(ebp+8) *Curr-block-depth)
    30385       (write-buffered *(ebp+8) "}\n")
    30386       (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    30387       (write-buffered *(ebp+8) %eax)
    30388       (write-buffered *(ebp+8) ":break:\n")
    30389     }
    30390 $emit-subx-block:end:
    30391     # . restore registers
    30392     5e/pop-to-esi
    30393     59/pop-to-ecx
    30394     58/pop-to-eax
    30395     # . epilogue
    30396     89/<- %esp 5/r32/ebp
    30397     5d/pop-to-ebp
    30398     c3/return
    30399
    30400 # Primitives supported
    30401 # See mu_instructions for a summary of this linked-list data structure.
    30402 #
    30403 # For each operation, put variants with hard-coded registers before flexible ones.
    30404 #
    30405 # Unfortunately, our restrictions on addresses require that various fields in
    30406 # primitives be handles, which complicates these definitions.
    30407 #   - we need to insert dummy fields all over the place for fake alloc-ids
    30408 #   - we can't use our syntax sugar of quoted literals for string fields
    30409 #
    30410 # Fake alloc-ids are needed because our type definitions up top require
    30411 # handles but it's clearer to statically allocate these long-lived objects.
    30412 # Fake alloc-ids are perfectly safe, but they can't be reclaimed.
    30413 #
    30414 # Every 'object' below starts with a fake alloc-id. It may also contain other
    30415 # fake alloc-ids for various handle fields.
    30416 #
    30417 # I think of objects starting with a fake alloc-id as having type 'payload'.
    30418 # It's not really intended to be created dynamically; for that use `allocate`
    30419 # as usual.
    30420 #
    30421 # Idea for a notation to simplify such definitions:
    30422 #   _Primitive-increment-eax:  # (payload primitive)
    30423 #     0x11/alloc-id:fake:payload
    30424 #     0x11 @(0x11 "increment")  # name
    30425 #     0 0                       # inouts
    30426 #     0x11 @(0x11/payload
    30427 #            0x11 @(0x11/payload  # List-value
    30428 #                   0 0             # Var-name
    30429 #                   0x11 @(0x11     # Var-type
    30430 #                          1/is-atom
    30431 #                          1/value 0/unused   # Type-tree-left
    30432 #                          0 0                # Type-tree-right
    30433 #                         )
    30434 #                   1               # block-depth
    30435 #                   0               # stack-offset
    30436 #                   0x11 @(0x11 "eax")  # Var-register
    30437 #                  )
    30438 #            0 0)                 # List-next
    30439 #     ...
    30440 #     _Primitive-increment-ecx/imm32/next
    30441 #   ...
    30442 # Awfully complex and non-obvious. But also clearly signals there's something
    30443 # to learn here, so may be worth trying.
    30444 #
    30445 # '@' is just an initial thought. Punctuation used so far in Mu: () * % # / "
    30446 #
    30447 # For now we'll continue to just use comments and manually ensure they stay up
    30448 # to date.
    30449 == data
    30450 Primitives:  # (addr primitive)
    30451 # - increment/decrement
    30452 _Primitive-increment-eax:  # (addr primitive)
    30453     # var/eax <- increment => 40/increment-eax
    30454     0x11/imm32/alloc-id:fake
    30455     _string-increment/imm32/name
    30456     0/imm32/no-inouts
    30457     0/imm32/no-inouts
    30458     0x11/imm32/alloc-id:fake
    30459     Single-int-var-in-eax/imm32/outputs
    30460     0x11/imm32/alloc-id:fake
    30461     _string_40_increment_eax/imm32/subx-name
    30462     0/imm32/no-rm32
    30463     0/imm32/no-r32
    30464     0/imm32/no-imm32
    30465     0/imm32/no-imm8
    30466     0/imm32/no-disp32
    30467     0/imm32/no-xm32
    30468     0/imm32/no-x32
    30469     0x11/imm32/alloc-id:fake
    30470     _Primitive-increment-ecx/imm32/next
    30471 _Primitive-increment-ecx:  # (payload primitive)
    30472     0x11/imm32/alloc-id:fake:payload
    30473     # var/ecx <- increment => 41/increment-ecx
    30474     0x11/imm32/alloc-id:fake
    30475     _string-increment/imm32/name
    30476     0/imm32/no-inouts
    30477     0/imm32/no-inouts
    30478     0x11/imm32/alloc-id:fake
    30479     Single-int-var-in-ecx/imm32/outputs
    30480     0x11/imm32/alloc-id:fake
    30481     _string_41_increment_ecx/imm32/subx-name
    30482     0/imm32/no-rm32
    30483     0/imm32/no-r32
    30484     0/imm32/no-imm32
    30485     0/imm32/no-imm8
    30486     0/imm32/no-disp32
    30487     0/imm32/no-xm32
    30488     0/imm32/no-x32
    30489     0x11/imm32/alloc-id:fake
    30490     _Primitive-increment-edx/imm32/next
    30491 _Primitive-increment-edx:  # (payload primitive)
    30492     0x11/imm32/alloc-id:fake:payload
    30493     # var/edx <- increment => 42/increment-edx
    30494     0x11/imm32/alloc-id:fake
    30495     _string-increment/imm32/name
    30496     0/imm32/no-inouts
    30497     0/imm32/no-inouts
    30498     0x11/imm32/alloc-id:fake
    30499     Single-int-var-in-edx/imm32/outputs
    30500     0x11/imm32/alloc-id:fake
    30501     _string_42_increment_edx/imm32/subx-name
    30502     0/imm32/no-rm32
    30503     0/imm32/no-r32
    30504     0/imm32/no-imm32
    30505     0/imm32/no-imm8
    30506     0/imm32/no-disp32
    30507     0/imm32/no-xm32
    30508     0/imm32/no-x32
    30509     0x11/imm32/alloc-id:fake
    30510     _Primitive-increment-ebx/imm32/next
    30511 _Primitive-increment-ebx:  # (payload primitive)
    30512     0x11/imm32/alloc-id:fake:payload
    30513     # var/ebx <- increment => 43/increment-ebx
    30514     0x11/imm32/alloc-id:fake
    30515     _string-increment/imm32/name
    30516     0/imm32/no-inouts
    30517     0/imm32/no-inouts
    30518     0x11/imm32/alloc-id:fake
    30519     Single-int-var-in-ebx/imm32/outputs
    30520     0x11/imm32/alloc-id:fake
    30521     _string_43_increment_ebx/imm32/subx-name
    30522     0/imm32/no-rm32
    30523     0/imm32/no-r32
    30524     0/imm32/no-imm32
    30525     0/imm32/no-imm8
    30526     0/imm32/no-disp32
    30527     0/imm32/no-xm32
    30528     0/imm32/no-x32
    30529     0x11/imm32/alloc-id:fake
    30530     _Primitive-increment-esi/imm32/next
    30531 _Primitive-increment-esi:  # (payload primitive)
    30532     0x11/imm32/alloc-id:fake:payload
    30533     # var/esi <- increment => 46/increment-esi
    30534     0x11/imm32/alloc-id:fake
    30535     _string-increment/imm32/name
    30536     0/imm32/no-inouts
    30537     0/imm32/no-inouts
    30538     0x11/imm32/alloc-id:fake
    30539     Single-int-var-in-esi/imm32/outputs
    30540     0x11/imm32/alloc-id:fake
    30541     _string_46_increment_esi/imm32/subx-name
    30542     0/imm32/no-rm32
    30543     0/imm32/no-r32
    30544     0/imm32/no-imm32
    30545     0/imm32/no-imm8
    30546     0/imm32/no-disp32
    30547     0/imm32/no-xm32
    30548     0/imm32/no-x32
    30549     0x11/imm32/alloc-id:fake
    30550     _Primitive-increment-edi/imm32/next
    30551 _Primitive-increment-edi:  # (payload primitive)
    30552     0x11/imm32/alloc-id:fake:payload
    30553     # var/edi <- increment => 47/increment-edi
    30554     0x11/imm32/alloc-id:fake
    30555     _string-increment/imm32/name
    30556     0/imm32/no-inouts
    30557     0/imm32/no-inouts
    30558     0x11/imm32/alloc-id:fake
    30559     Single-int-var-in-edi/imm32/outputs
    30560     0x11/imm32/alloc-id:fake
    30561     _string_47_increment_edi/imm32/subx-name
    30562     0/imm32/no-rm32
    30563     0/imm32/no-r32
    30564     0/imm32/no-imm32
    30565     0/imm32/no-imm8
    30566     0/imm32/no-disp32
    30567     0/imm32/no-xm32
    30568     0/imm32/no-x32
    30569     0x11/imm32/alloc-id:fake
    30570     _Primitive-decrement-eax/imm32/next
    30571 _Primitive-decrement-eax:  # (payload primitive)
    30572     0x11/imm32/alloc-id:fake:payload
    30573     # var/eax <- decrement => 48/decrement-eax
    30574     0x11/imm32/alloc-id:fake
    30575     _string-decrement/imm32/name
    30576     0/imm32/no-inouts
    30577     0/imm32/no-inouts
    30578     0x11/imm32/alloc-id:fake
    30579     Single-int-var-in-eax/imm32/outputs
    30580     0x11/imm32/alloc-id:fake
    30581     _string_48_decrement_eax/imm32/subx-name
    30582     0/imm32/no-rm32
    30583     0/imm32/no-r32
    30584     0/imm32/no-imm32
    30585     0/imm32/no-imm8
    30586     0/imm32/no-disp32
    30587     0/imm32/no-xm32
    30588     0/imm32/no-x32
    30589     0x11/imm32/alloc-id:fake
    30590     _Primitive-decrement-ecx/imm32/next
    30591 _Primitive-decrement-ecx:  # (payload primitive)
    30592     0x11/imm32/alloc-id:fake:payload
    30593     # var/ecx <- decrement => 49/decrement-ecx
    30594     0x11/imm32/alloc-id:fake
    30595     _string-decrement/imm32/name
    30596     0/imm32/no-inouts
    30597     0/imm32/no-inouts
    30598     0x11/imm32/alloc-id:fake
    30599     Single-int-var-in-ecx/imm32/outputs
    30600     0x11/imm32/alloc-id:fake
    30601     _string_49_decrement_ecx/imm32/subx-name
    30602     0/imm32/no-rm32
    30603     0/imm32/no-r32
    30604     0/imm32/no-imm32
    30605     0/imm32/no-imm8
    30606     0/imm32/no-disp32
    30607     0/imm32/no-xm32
    30608     0/imm32/no-x32
    30609     0x11/imm32/alloc-id:fake
    30610     _Primitive-decrement-edx/imm32/next
    30611 _Primitive-decrement-edx:  # (payload primitive)
    30612     0x11/imm32/alloc-id:fake:payload
    30613     # var/edx <- decrement => 4a/decrement-edx
    30614     0x11/imm32/alloc-id:fake
    30615     _string-decrement/imm32/name
    30616     0/imm32/no-inouts
    30617     0/imm32/no-inouts
    30618     0x11/imm32/alloc-id:fake
    30619     Single-int-var-in-edx/imm32/outputs
    30620     0x11/imm32/alloc-id:fake
    30621     _string_4a_decrement_edx/imm32/subx-name
    30622     0/imm32/no-rm32
    30623     0/imm32/no-r32
    30624     0/imm32/no-imm32
    30625     0/imm32/no-imm8
    30626     0/imm32/no-disp32
    30627     0/imm32/no-xm32
    30628     0/imm32/no-x32
    30629     0x11/imm32/alloc-id:fake
    30630     _Primitive-decrement-ebx/imm32/next
    30631 _Primitive-decrement-ebx:  # (payload primitive)
    30632     0x11/imm32/alloc-id:fake:payload
    30633     # var/ebx <- decrement => 4b/decrement-ebx
    30634     0x11/imm32/alloc-id:fake
    30635     _string-decrement/imm32/name
    30636     0/imm32/no-inouts
    30637     0/imm32/no-inouts
    30638     0x11/imm32/alloc-id:fake
    30639     Single-int-var-in-ebx/imm32/outputs
    30640     0x11/imm32/alloc-id:fake
    30641     _string_4b_decrement_ebx/imm32/subx-name
    30642     0/imm32/no-rm32
    30643     0/imm32/no-r32
    30644     0/imm32/no-imm32
    30645     0/imm32/no-imm8
    30646     0/imm32/no-disp32
    30647     0/imm32/no-xm32
    30648     0/imm32/no-x32
    30649     0x11/imm32/alloc-id:fake
    30650     _Primitive-decrement-esi/imm32/next
    30651 _Primitive-decrement-esi:  # (payload primitive)
    30652     0x11/imm32/alloc-id:fake:payload
    30653     # var/esi <- decrement => 4e/decrement-esi
    30654     0x11/imm32/alloc-id:fake
    30655     _string-decrement/imm32/name
    30656     0/imm32/no-inouts
    30657     0/imm32/no-inouts
    30658     0x11/imm32/alloc-id:fake
    30659     Single-int-var-in-esi/imm32/outputs
    30660     0x11/imm32/alloc-id:fake
    30661     _string_4e_decrement_esi/imm32/subx-name
    30662     0/imm32/no-rm32
    30663     0/imm32/no-r32
    30664     0/imm32/no-imm32
    30665     0/imm32/no-imm8
    30666     0/imm32/no-disp32
    30667     0/imm32/no-xm32
    30668     0/imm32/no-x32
    30669     0x11/imm32/alloc-id:fake
    30670     _Primitive-decrement-edi/imm32/next
    30671 _Primitive-decrement-edi:  # (payload primitive)
    30672     0x11/imm32/alloc-id:fake:payload
    30673     # var/edi <- decrement => 4f/decrement-edi
    30674     0x11/imm32/alloc-id:fake
    30675     _string-decrement/imm32/name
    30676     0/imm32/no-inouts
    30677     0/imm32/no-inouts
    30678     0x11/imm32/alloc-id:fake
    30679     Single-int-var-in-edi/imm32/outputs
    30680     0x11/imm32/alloc-id:fake
    30681     _string_4f_decrement_edi/imm32/subx-name
    30682     0/imm32/no-rm32
    30683     0/imm32/no-r32
    30684     0/imm32/no-imm32
    30685     0/imm32/no-imm8
    30686     0/imm32/no-disp32
    30687     0/imm32/no-xm32
    30688     0/imm32/no-x32
    30689     0x11/imm32/alloc-id:fake
    30690     _Primitive-increment-mem/imm32/next
    30691 _Primitive-increment-mem:  # (payload primitive)
    30692     0x11/imm32/alloc-id:fake:payload
    30693     # increment var => ff 0/subop/increment *(ebp+__)
    30694     0x11/imm32/alloc-id:fake
    30695     _string-increment/imm32/name
    30696     0x11/imm32/alloc-id:fake
    30697     Single-int-var-in-mem/imm32/inouts
    30698     0/imm32/no-outputs
    30699     0/imm32/no-outputs
    30700     0x11/imm32/alloc-id:fake
    30701     _string_ff_subop_increment/imm32/subx-name
    30702     1/imm32/rm32-is-first-inout
    30703     0/imm32/no-r32
    30704     0/imm32/no-imm32
    30705     0/imm32/no-imm8
    30706     0/imm32/no-disp32
    30707     0/imm32/no-xm32
    30708     0/imm32/no-x32
    30709     0x11/imm32/alloc-id:fake
    30710     _Primitive-increment-reg/imm32/next
    30711 _Primitive-increment-reg:  # (payload primitive)
    30712     0x11/imm32/alloc-id:fake:payload
    30713     # var/reg <- increment => ff 0/subop/increment %__
    30714     0x11/imm32/alloc-id:fake
    30715     _string-increment/imm32/name
    30716     0/imm32/no-inouts
    30717     0/imm32/no-inouts
    30718     0x11/imm32/alloc-id:fake
    30719     Single-int-var-in-some-register/imm32/outputs
    30720     0x11/imm32/alloc-id:fake
    30721     _string_ff_subop_increment/imm32/subx-name
    30722     3/imm32/rm32-is-first-output
    30723     0/imm32/no-r32
    30724     0/imm32/no-imm32
    30725     0/imm32/no-imm8
    30726     0/imm32/no-disp32
    30727     0/imm32/no-xm32
    30728     0/imm32/no-x32
    30729     0x11/imm32/alloc-id:fake
    30730     _Primitive-decrement-mem/imm32/next
    30731 _Primitive-decrement-mem:  # (payload primitive)
    30732     0x11/imm32/alloc-id:fake:payload
    30733     # decrement var => ff 1/subop/decrement *(ebp+__)
    30734     0x11/imm32/alloc-id:fake
    30735     _string-decrement/imm32/name
    30736     0x11/imm32/alloc-id:fake
    30737     Single-int-var-in-mem/imm32/inouts
    30738     0/imm32/no-outputs
    30739     0/imm32/no-outputs
    30740     0x11/imm32/alloc-id:fake
    30741     _string_ff_subop_decrement/imm32/subx-name
    30742     1/imm32/rm32-is-first-inout
    30743     0/imm32/no-r32
    30744     0/imm32/no-imm32
    30745     0/imm32/no-imm8
    30746     0/imm32/no-disp32
    30747     0/imm32/no-xm32
    30748     0/imm32/no-x32
    30749     0x11/imm32/alloc-id:fake
    30750     _Primitive-decrement-reg/imm32/next
    30751 _Primitive-decrement-reg:  # (payload primitive)
    30752     0x11/imm32/alloc-id:fake:payload
    30753     # var/reg <- decrement => ff 1/subop/decrement %__
    30754     0x11/imm32/alloc-id:fake
    30755     _string-decrement/imm32/name
    30756     0/imm32/no-inouts
    30757     0/imm32/no-inouts
    30758     0x11/imm32/alloc-id:fake
    30759     Single-int-var-in-some-register/imm32/outputs
    30760     0x11/imm32/alloc-id:fake
    30761     _string_ff_subop_decrement/imm32/subx-name
    30762     3/imm32/rm32-is-first-output
    30763     0/imm32/no-r32
    30764     0/imm32/no-imm32
    30765     0/imm32/no-imm8
    30766     0/imm32/no-disp32
    30767     0/imm32/no-xm32
    30768     0/imm32/no-x32
    30769     0x11/imm32/alloc-id:fake
    30770     _Primitive-add-to-eax/imm32/next
    30771 # - add
    30772 _Primitive-add-to-eax:  # (payload primitive)
    30773     0x11/imm32/alloc-id:fake:payload
    30774     # var/eax <- add lit => 05/add-to-eax lit/imm32
    30775     0x11/imm32/alloc-id:fake
    30776     _string-add/imm32/name
    30777     0x11/imm32/alloc-id:fake
    30778     Single-lit-var/imm32/inouts
    30779     0x11/imm32/alloc-id:fake
    30780     Single-int-var-in-eax/imm32/outputs
    30781     0x11/imm32/alloc-id:fake
    30782     _string_05_add_to_eax/imm32/subx-name
    30783     0/imm32/no-rm32
    30784     0/imm32/no-r32
    30785     1/imm32/imm32-is-first-inout
    30786     0/imm32/no-imm8
    30787     0/imm32/no-disp32
    30788     0/imm32/no-xm32
    30789     0/imm32/no-x32
    30790     0x11/imm32/alloc-id:fake
    30791     _Primitive-add-reg-to-reg/imm32/next
    30792 _Primitive-add-reg-to-reg:  # (payload primitive)
    30793     0x11/imm32/alloc-id:fake:payload
    30794     # var1/reg <- add var2/reg => 01/add-to var1/rm32 var2/r32
    30795     0x11/imm32/alloc-id:fake
    30796     _string-add/imm32/name
    30797     0x11/imm32/alloc-id:fake
    30798     Single-int-var-in-some-register/imm32/inouts
    30799     0x11/imm32/alloc-id:fake
    30800     Single-int-var-in-some-register/imm32/outputs
    30801     0x11/imm32/alloc-id:fake
    30802     _string_01_add_to/imm32/subx-name
    30803     3/imm32/rm32-is-first-output
    30804     1/imm32/r32-is-first-inout
    30805     0/imm32/no-imm32
    30806     0/imm32/no-imm8
    30807     0/imm32/no-disp32
    30808     0/imm32/no-xm32
    30809     0/imm32/no-x32
    30810     0x11/imm32/alloc-id:fake
    30811     _Primitive-add-reg-to-mem/imm32/next
    30812 _Primitive-add-reg-to-mem:  # (payload primitive)
    30813     0x11/imm32/alloc-id:fake:payload
    30814     # add-to var1 var2/reg => 01/add-to var1 var2/r32
    30815     0x11/imm32/alloc-id:fake
    30816     _string-add-to/imm32/name
    30817     0x11/imm32/alloc-id:fake
    30818     Two-args-int-stack-int-reg/imm32/inouts
    30819     0/imm32/no-outputs
    30820     0/imm32/no-outputs
    30821     0x11/imm32/alloc-id:fake
    30822     _string_01_add_to/imm32/subx-name
    30823     1/imm32/rm32-is-first-inout
    30824     2/imm32/r32-is-second-inout
    30825     0/imm32/no-imm32
    30826     0/imm32/no-imm8
    30827     0/imm32/no-disp32
    30828     0/imm32/no-xm32
    30829     0/imm32/no-x32
    30830     0x11/imm32/alloc-id:fake
    30831     _Primitive-add-mem-to-reg/imm32/next
    30832 _Primitive-add-mem-to-reg:  # (payload primitive)
    30833     0x11/imm32/alloc-id:fake:payload
    30834     # var1/reg <- add var2 => 03/add var2/rm32 var1/r32
    30835     0x11/imm32/alloc-id:fake
    30836     _string-add/imm32/name
    30837     0x11/imm32/alloc-id:fake
    30838     Single-int-var-in-mem/imm32/inouts
    30839     0x11/imm32/alloc-id:fake
    30840     Single-int-var-in-some-register/imm32/outputs
    30841     0x11/imm32/alloc-id:fake
    30842     _string_03_add/imm32/subx-name
    30843     1/imm32/rm32-is-first-inout
    30844     3/imm32/r32-is-first-output
    30845     0/imm32/no-imm32
    30846     0/imm32/no-imm8
    30847     0/imm32/no-disp32
    30848     0/imm32/no-xm32
    30849     0/imm32/no-x32
    30850     0x11/imm32/alloc-id:fake
    30851     _Primitive-add-lit-to-reg/imm32/next
    30852 _Primitive-add-lit-to-reg:  # (payload primitive)
    30853     0x11/imm32/alloc-id:fake:payload
    30854     # var1/reg <- add lit => 81 0/subop/add var1/rm32 lit/imm32
    30855     0x11/imm32/alloc-id:fake
    30856     _string-add/imm32/name
    30857     0x11/imm32/alloc-id:fake
    30858     Single-lit-var/imm32/inouts
    30859     0x11/imm32/alloc-id:fake
    30860     Single-int-var-in-some-register/imm32/outputs
    30861     0x11/imm32/alloc-id:fake
    30862     _string_81_subop_add/imm32/subx-name
    30863     3/imm32/rm32-is-first-output
    30864     0/imm32/no-r32
    30865     1/imm32/imm32-is-first-inout
    30866     0/imm32/no-imm8
    30867     0/imm32/no-disp32
    30868     0/imm32/no-xm32
    30869     0/imm32/no-x32
    30870     0x11/imm32/alloc-id:fake
    30871     _Primitive-add-lit-to-mem/imm32/next
    30872 _Primitive-add-lit-to-mem:  # (payload primitive)
    30873     0x11/imm32/alloc-id:fake:payload
    30874     # add-to var1, lit => 81 0/subop/add var1/rm32 lit/imm32
    30875     0x11/imm32/alloc-id:fake
    30876     _string-add-to/imm32/name
    30877     0x11/imm32/alloc-id:fake
    30878     Int-var-and-literal/imm32/inouts
    30879     0/imm32/no-outputs
    30880     0/imm32/no-outputs
    30881     0x11/imm32/alloc-id:fake
    30882     _string_81_subop_add/imm32/subx-name
    30883     1/imm32/rm32-is-first-inout
    30884     0/imm32/no-r32
    30885     2/imm32/imm32-is-second-inout
    30886     0/imm32/no-imm8
    30887     0/imm32/no-disp32
    30888     0/imm32/no-xm32
    30889     0/imm32/no-x32
    30890     0x11/imm32/alloc-id:fake
    30891     _Primitive-subtract-from-eax/imm32/next
    30892 # - subtract
    30893 _Primitive-subtract-from-eax:  # (payload primitive)
    30894     0x11/imm32/alloc-id:fake:payload
    30895     # var/eax <- subtract lit => 2d/subtract-from-eax lit/imm32
    30896     0x11/imm32/alloc-id:fake
    30897     _string-subtract/imm32/name
    30898     0x11/imm32/alloc-id:fake
    30899     Single-lit-var/imm32/inouts
    30900     0x11/imm32/alloc-id:fake
    30901     Single-int-var-in-eax/imm32/outputs
    30902     0x11/imm32/alloc-id:fake
    30903     _string_2d_subtract_from_eax/imm32/subx-name
    30904     0/imm32/no-rm32
    30905     0/imm32/no-r32
    30906     1/imm32/imm32-is-first-inout
    30907     0/imm32/no-imm8
    30908     0/imm32/no-disp32
    30909     0/imm32/no-xm32
    30910     0/imm32/no-x32
    30911     0x11/imm32/alloc-id:fake
    30912     _Primitive-subtract-reg-from-reg/imm32/next
    30913 _Primitive-subtract-reg-from-reg:  # (payload primitive)
    30914     0x11/imm32/alloc-id:fake:payload
    30915     # var1/reg <- subtract var2/reg => 29/subtract-from var1/rm32 var2/r32
    30916     0x11/imm32/alloc-id:fake
    30917     _string-subtract/imm32/name
    30918     0x11/imm32/alloc-id:fake
    30919     Single-int-var-in-some-register/imm32/inouts
    30920     0x11/imm32/alloc-id:fake
    30921     Single-int-var-in-some-register/imm32/outputs
    30922     0x11/imm32/alloc-id:fake
    30923     _string_29_subtract_from/imm32/subx-name
    30924     3/imm32/rm32-is-first-output
    30925     1/imm32/r32-is-first-inout
    30926     0/imm32/no-imm32
    30927     0/imm32/no-imm8
    30928     0/imm32/no-disp32
    30929     0/imm32/no-xm32
    30930     0/imm32/no-x32
    30931     0x11/imm32/alloc-id:fake
    30932     _Primitive-subtract-reg-from-mem/imm32/next
    30933 _Primitive-subtract-reg-from-mem:  # (payload primitive)
    30934     0x11/imm32/alloc-id:fake:payload
    30935     # subtract-from var1 var2/reg => 29/subtract-from var1 var2/r32
    30936     0x11/imm32/alloc-id:fake
    30937     _string-subtract-from/imm32/name
    30938     0x11/imm32/alloc-id:fake
    30939     Two-args-int-stack-int-reg/imm32/inouts
    30940     0/imm32/no-outputs
    30941     0/imm32/no-outputs
    30942     0x11/imm32/alloc-id:fake
    30943     _string_29_subtract_from/imm32/subx-name
    30944     1/imm32/rm32-is-first-inout
    30945     2/imm32/r32-is-second-inout
    30946     0/imm32/no-imm32
    30947     0/imm32/no-imm8
    30948     0/imm32/no-disp32
    30949     0/imm32/no-xm32
    30950     0/imm32/no-x32
    30951     0x11/imm32/alloc-id:fake
    30952     _Primitive-subtract-mem-from-reg/imm32/next
    30953 _Primitive-subtract-mem-from-reg:  # (payload primitive)
    30954     0x11/imm32/alloc-id:fake:payload
    30955     # var1/reg <- subtract var2 => 2b/subtract var2/rm32 var1/r32
    30956     0x11/imm32/alloc-id:fake
    30957     _string-subtract/imm32/name
    30958     0x11/imm32/alloc-id:fake
    30959     Single-int-var-in-mem/imm32/inouts
    30960     0x11/imm32/alloc-id:fake
    30961     Single-int-var-in-some-register/imm32/outputs
    30962     0x11/imm32/alloc-id:fake
    30963     _string_2b_subtract/imm32/subx-name
    30964     1/imm32/rm32-is-first-inout
    30965     3/imm32/r32-is-first-output
    30966     0/imm32/no-imm32
    30967     0/imm32/no-imm8
    30968     0/imm32/no-disp32
    30969     0/imm32/no-xm32
    30970     0/imm32/no-x32
    30971     0x11/imm32/alloc-id:fake
    30972     _Primitive-subtract-lit-from-reg/imm32/next
    30973 _Primitive-subtract-lit-from-reg:  # (payload primitive)
    30974     0x11/imm32/alloc-id:fake:payload
    30975     # var1/reg <- subtract lit => 81 5/subop/subtract var1/rm32 lit/imm32
    30976     0x11/imm32/alloc-id:fake
    30977     _string-subtract/imm32/name
    30978     0x11/imm32/alloc-id:fake
    30979     Single-lit-var/imm32/inouts
    30980     0x11/imm32/alloc-id:fake
    30981     Single-int-var-in-some-register/imm32/outputs
    30982     0x11/imm32/alloc-id:fake
    30983     _string_81_subop_subtract/imm32/subx-name
    30984     3/imm32/rm32-is-first-output
    30985     0/imm32/no-r32
    30986     1/imm32/imm32-is-first-inout
    30987     0/imm32/no-imm8
    30988     0/imm32/no-disp32
    30989     0/imm32/no-xm32
    30990     0/imm32/no-x32
    30991     0x11/imm32/alloc-id:fake
    30992     _Primitive-subtract-lit-from-mem/imm32/next
    30993 _Primitive-subtract-lit-from-mem:  # (payload primitive)
    30994     0x11/imm32/alloc-id:fake:payload
    30995     # subtract-from var1, lit => 81 5/subop/subtract var1/rm32 lit/imm32
    30996     0x11/imm32/alloc-id:fake
    30997     _string-subtract-from/imm32/name
    30998     0x11/imm32/alloc-id:fake
    30999     Int-var-and-literal/imm32/inouts
    31000     0/imm32/no-outputs
    31001     0/imm32/no-outputs
    31002     0x11/imm32/alloc-id:fake
    31003     _string_81_subop_subtract/imm32/subx-name
    31004     1/imm32/rm32-is-first-inout
    31005     0/imm32/no-r32
    31006     2/imm32/imm32-is-second-inout
    31007     0/imm32/no-imm8
    31008     0/imm32/no-disp32
    31009     0/imm32/no-xm32
    31010     0/imm32/no-x32
    31011     0x11/imm32/alloc-id:fake
    31012     _Primitive-and-with-eax/imm32/next
    31013 # - and
    31014 _Primitive-and-with-eax:  # (payload primitive)
    31015     0x11/imm32/alloc-id:fake:payload
    31016     # var/eax <- and lit => 25/and-with-eax lit/imm32
    31017     0x11/imm32/alloc-id:fake
    31018     _string-and/imm32/name
    31019     0x11/imm32/alloc-id:fake
    31020     Single-lit-var/imm32/inouts
    31021     0x11/imm32/alloc-id:fake
    31022     Single-int-var-in-eax/imm32/outputs
    31023     0x11/imm32/alloc-id:fake
    31024     _string_25_and_with_eax/imm32/subx-name
    31025     0/imm32/no-rm32
    31026     0/imm32/no-r32
    31027     1/imm32/imm32-is-first-inout
    31028     0/imm32/no-imm8
    31029     0/imm32/no-disp32
    31030     0/imm32/no-xm32
    31031     0/imm32/no-x32
    31032     0x11/imm32/alloc-id:fake
    31033     _Primitive-and-reg-with-reg/imm32/next
    31034 _Primitive-and-reg-with-reg:  # (payload primitive)
    31035     0x11/imm32/alloc-id:fake:payload
    31036     # var1/reg <- and var2/reg => 21/and-with var1/rm32 var2/r32
    31037     0x11/imm32/alloc-id:fake
    31038     _string-and/imm32/name
    31039     0x11/imm32/alloc-id:fake
    31040     Single-int-var-in-some-register/imm32/inouts
    31041     0x11/imm32/alloc-id:fake
    31042     Single-int-var-in-some-register/imm32/outputs
    31043     0x11/imm32/alloc-id:fake
    31044     _string_21_and_with/imm32/subx-name
    31045     3/imm32/rm32-is-first-output
    31046     1/imm32/r32-is-first-inout
    31047     0/imm32/no-imm32
    31048     0/imm32/no-imm8
    31049     0/imm32/no-disp32
    31050     0/imm32/no-xm32
    31051     0/imm32/no-x32
    31052     0x11/imm32/alloc-id:fake
    31053     _Primitive-and-reg-with-mem/imm32/next
    31054 _Primitive-and-reg-with-mem:  # (payload primitive)
    31055     0x11/imm32/alloc-id:fake:payload
    31056     # and-with var1 var2/reg => 21/and-with var1 var2/r32
    31057     0x11/imm32/alloc-id:fake
    31058     _string-and-with/imm32/name
    31059     0x11/imm32/alloc-id:fake
    31060     Two-args-int-stack-int-reg/imm32/inouts
    31061     0/imm32/no-outputs
    31062     0/imm32/no-outputs
    31063     0x11/imm32/alloc-id:fake
    31064     _string_21_and_with/imm32/subx-name
    31065     1/imm32/rm32-is-first-inout
    31066     2/imm32/r32-is-second-inout
    31067     0/imm32/no-imm32
    31068     0/imm32/no-imm8
    31069     0/imm32/no-disp32
    31070     0/imm32/no-xm32
    31071     0/imm32/no-x32
    31072     0x11/imm32/alloc-id:fake
    31073     _Primitive-and-mem-with-reg/imm32/next
    31074 _Primitive-and-mem-with-reg:  # (payload primitive)
    31075     0x11/imm32/alloc-id:fake:payload
    31076     # var1/reg <- and var2 => 23/and var2/rm32 var1/r32
    31077     0x11/imm32/alloc-id:fake
    31078     _string-and/imm32/name
    31079     0x11/imm32/alloc-id:fake
    31080     Single-int-var-in-mem/imm32/inouts
    31081     0x11/imm32/alloc-id:fake
    31082     Single-int-var-in-some-register/imm32/outputs
    31083     0x11/imm32/alloc-id:fake
    31084     _string_23_and/imm32/subx-name
    31085     1/imm32/rm32-is-first-inout
    31086     3/imm32/r32-is-first-output
    31087     0/imm32/no-imm32
    31088     0/imm32/no-imm8
    31089     0/imm32/no-disp32
    31090     0/imm32/no-xm32
    31091     0/imm32/no-x32
    31092     0x11/imm32/alloc-id:fake
    31093     _Primitive-and-lit-with-reg/imm32/next
    31094 _Primitive-and-lit-with-reg:  # (payload primitive)
    31095     0x11/imm32/alloc-id:fake:payload
    31096     # var1/reg <- and lit => 81 4/subop/and var1/rm32 lit/imm32
    31097     0x11/imm32/alloc-id:fake
    31098     _string-and/imm32/name
    31099     0x11/imm32/alloc-id:fake
    31100     Single-lit-var/imm32/inouts
    31101     0x11/imm32/alloc-id:fake
    31102     Single-int-var-in-some-register/imm32/outputs
    31103     0x11/imm32/alloc-id:fake
    31104     _string_81_subop_and/imm32/subx-name
    31105     3/imm32/rm32-is-first-output
    31106     0/imm32/no-r32
    31107     1/imm32/imm32-is-first-inout
    31108     0/imm32/no-imm8
    31109     0/imm32/no-disp32
    31110     0/imm32/no-xm32
    31111     0/imm32/no-x32
    31112     0x11/imm32/alloc-id:fake
    31113     _Primitive-and-lit-with-mem/imm32/next
    31114 _Primitive-and-lit-with-mem:  # (payload primitive)
    31115     0x11/imm32/alloc-id:fake:payload
    31116     # and-with var1, lit => 81 4/subop/and var1/rm32 lit/imm32
    31117     0x11/imm32/alloc-id:fake
    31118     _string-and-with/imm32/name
    31119     0x11/imm32/alloc-id:fake
    31120     Int-var-and-literal/imm32/inouts
    31121     0/imm32/no-outputs
    31122     0/imm32/no-outputs
    31123     0x11/imm32/alloc-id:fake
    31124     _string_81_subop_and/imm32/subx-name
    31125     1/imm32/rm32-is-first-inout
    31126     0/imm32/no-r32
    31127     2/imm32/imm32-is-second-inout
    31128     0/imm32/no-imm8
    31129     0/imm32/no-disp32
    31130     0/imm32/no-xm32
    31131     0/imm32/no-x32
    31132     0x11/imm32/alloc-id:fake
    31133     _Primitive-or-with-eax/imm32/next
    31134 # - or
    31135 _Primitive-or-with-eax:  # (payload primitive)
    31136     0x11/imm32/alloc-id:fake:payload
    31137     # var/eax <- or lit => 0d/or-with-eax lit/imm32
    31138     0x11/imm32/alloc-id:fake
    31139     _string-or/imm32/name
    31140     0x11/imm32/alloc-id:fake
    31141     Single-lit-var/imm32/inouts
    31142     0x11/imm32/alloc-id:fake
    31143     Single-int-var-in-eax/imm32/outputs
    31144     0x11/imm32/alloc-id:fake
    31145     _string_0d_or_with_eax/imm32/subx-name
    31146     0/imm32/no-rm32
    31147     0/imm32/no-r32
    31148     1/imm32/imm32-is-first-inout
    31149     0/imm32/no-imm8
    31150     0/imm32/no-disp32
    31151     0/imm32/no-xm32
    31152     0/imm32/no-x32
    31153     0x11/imm32/alloc-id:fake
    31154     _Primitive-or-reg-with-reg/imm32/next
    31155 _Primitive-or-reg-with-reg:  # (payload primitive)
    31156     0x11/imm32/alloc-id:fake:payload
    31157     # var1/reg <- or var2/reg => 09/or-with var1/rm32 var2/r32
    31158     0x11/imm32/alloc-id:fake
    31159     _string-or/imm32/name
    31160     0x11/imm32/alloc-id:fake
    31161     Single-int-var-in-some-register/imm32/inouts
    31162     0x11/imm32/alloc-id:fake
    31163     Single-int-var-in-some-register/imm32/outputs
    31164     0x11/imm32/alloc-id:fake
    31165     _string_09_or_with/imm32/subx-name
    31166     3/imm32/rm32-is-first-output
    31167     1/imm32/r32-is-first-inout
    31168     0/imm32/no-imm32
    31169     0/imm32/no-imm8
    31170     0/imm32/no-disp32
    31171     0/imm32/no-xm32
    31172     0/imm32/no-x32
    31173     0x11/imm32/alloc-id:fake
    31174     _Primitive-or-reg-with-mem/imm32/next
    31175 _Primitive-or-reg-with-mem:  # (payload primitive)
    31176     0x11/imm32/alloc-id:fake:payload
    31177     # or-with var1 var2/reg => 09/or-with var1 var2/r32
    31178     0x11/imm32/alloc-id:fake
    31179     _string-or-with/imm32/name
    31180     0x11/imm32/alloc-id:fake
    31181     Two-args-int-stack-int-reg/imm32/inouts
    31182     0/imm32/no-outputs
    31183     0/imm32/no-outputs
    31184     0x11/imm32/alloc-id:fake
    31185     _string_09_or_with/imm32/subx-name
    31186     1/imm32/rm32-is-first-inout
    31187     2/imm32/r32-is-second-inout
    31188     0/imm32/no-imm32
    31189     0/imm32/no-imm8
    31190     0/imm32/no-disp32
    31191     0/imm32/no-xm32
    31192     0/imm32/no-x32
    31193     0x11/imm32/alloc-id:fake
    31194     _Primitive-or-mem-with-reg/imm32/next
    31195 _Primitive-or-mem-with-reg:  # (payload primitive)
    31196     0x11/imm32/alloc-id:fake:payload
    31197     # var1/reg <- or var2 => 0b/or var2/rm32 var1/r32
    31198     0x11/imm32/alloc-id:fake
    31199     _string-or/imm32/name
    31200     0x11/imm32/alloc-id:fake
    31201     Single-int-var-in-mem/imm32/inouts
    31202     0x11/imm32/alloc-id:fake
    31203     Single-int-var-in-some-register/imm32/outputs
    31204     0x11/imm32/alloc-id:fake
    31205     _string_0b_or/imm32/subx-name
    31206     1/imm32/rm32-is-first-inout
    31207     3/imm32/r32-is-first-output
    31208     0/imm32/no-imm32
    31209     0/imm32/no-imm8
    31210     0/imm32/no-disp32
    31211     0/imm32/no-xm32
    31212     0/imm32/no-x32
    31213     0x11/imm32/alloc-id:fake
    31214     _Primitive-or-lit-with-reg/imm32/next
    31215 _Primitive-or-lit-with-reg:  # (payload primitive)
    31216     0x11/imm32/alloc-id:fake:payload
    31217     # var1/reg <- or lit => 81 1/subop/or var1/rm32 lit/imm32
    31218     0x11/imm32/alloc-id:fake
    31219     _string-or/imm32/name
    31220     0x11/imm32/alloc-id:fake
    31221     Single-lit-var/imm32/inouts
    31222     0x11/imm32/alloc-id:fake
    31223     Single-int-var-in-some-register/imm32/outputs
    31224     0x11/imm32/alloc-id:fake
    31225     _string_81_subop_or/imm32/subx-name
    31226     3/imm32/rm32-is-first-output
    31227     0/imm32/no-r32
    31228     1/imm32/imm32-is-first-inout
    31229     0/imm32/no-imm8
    31230     0/imm32/no-disp32
    31231     0/imm32/no-xm32
    31232     0/imm32/no-x32
    31233     0x11/imm32/alloc-id:fake
    31234     _Primitive-or-lit-with-mem/imm32/next
    31235 _Primitive-or-lit-with-mem:  # (payload primitive)
    31236     0x11/imm32/alloc-id:fake:payload
    31237     # or-with var1, lit => 81 1/subop/or var1/rm32 lit/imm32
    31238     0x11/imm32/alloc-id:fake
    31239     _string-or-with/imm32/name
    31240     0x11/imm32/alloc-id:fake
    31241     Int-var-and-literal/imm32/inouts
    31242     0/imm32/no-outputs
    31243     0/imm32/no-outputs
    31244     0x11/imm32/alloc-id:fake
    31245     _string_81_subop_or/imm32/subx-name
    31246     1/imm32/rm32-is-first-inout
    31247     0/imm32/no-r32
    31248     2/imm32/imm32-is-second-inout
    31249     0/imm32/no-imm8
    31250     0/imm32/no-disp32
    31251     0/imm32/no-xm32
    31252     0/imm32/no-x32
    31253     0x11/imm32/alloc-id:fake
    31254     _Primitive-not-reg/imm32/next
    31255 # - not
    31256 _Primitive-not-reg:  # (payload primitive)
    31257     0x11/imm32/alloc-id:fake:payload
    31258     # var1/reg <- not => f7 2/subop/not var1/rm32
    31259     0x11/imm32/alloc-id:fake
    31260     _string-not/imm32/name
    31261     0/imm32/no-inouts
    31262     0/imm32/no-inouts
    31263     0x11/imm32/alloc-id:fake
    31264     Single-int-var-in-some-register/imm32/outputs
    31265     0x11/imm32/alloc-id:fake
    31266     _string_f7_subop_not/imm32/subx-name
    31267     3/imm32/rm32-is-first-output
    31268     0/imm32/no-r32
    31269     0/imm32/no-imm32
    31270     0/imm32/no-imm8
    31271     0/imm32/no-disp32
    31272     0/imm32/no-xm32
    31273     0/imm32/no-x32
    31274     0x11/imm32/alloc-id:fake
    31275     _Primitive-not-mem/imm32/next
    31276 _Primitive-not-mem:  # (payload primitive)
    31277     0x11/imm32/alloc-id:fake:payload
    31278     # not var1 => f7 2/subop/not var1/rm32
    31279     0x11/imm32/alloc-id:fake
    31280     _string-not/imm32/name
    31281     0x11/imm32/alloc-id:fake
    31282     Single-int-var-in-mem/imm32/inouts
    31283     0/imm32/no-outputs
    31284     0/imm32/no-outputs
    31285     0x11/imm32/alloc-id:fake
    31286     _string_f7_subop_not/imm32/subx-name
    31287     1/imm32/rm32-is-first-inout
    31288     0/imm32/no-r32
    31289     0/imm32/no-imm32
    31290     0/imm32/no-imm8
    31291     0/imm32/no-disp32
    31292     0/imm32/no-xm32
    31293     0/imm32/no-x32
    31294     0x11/imm32/alloc-id:fake
    31295     _Primitive-xor-with-eax/imm32/next
    31296 # - xor
    31297 _Primitive-xor-with-eax:  # (payload primitive)
    31298     0x11/imm32/alloc-id:fake:payload
    31299     # var/eax <- xor lit => 35/xor-with-eax lit/imm32
    31300     0x11/imm32/alloc-id:fake
    31301     _string-xor/imm32/name
    31302     0x11/imm32/alloc-id:fake
    31303     Single-lit-var/imm32/inouts
    31304     0x11/imm32/alloc-id:fake
    31305     Single-int-var-in-eax/imm32/outputs
    31306     0x11/imm32/alloc-id:fake
    31307     _string_35_xor_with_eax/imm32/subx-name
    31308     0/imm32/no-rm32
    31309     0/imm32/no-r32
    31310     1/imm32/imm32-is-first-inout
    31311     0/imm32/no-imm8
    31312     0/imm32/no-disp32
    31313     0/imm32/no-xm32
    31314     0/imm32/no-x32
    31315     0x11/imm32/alloc-id:fake
    31316     _Primitive-xor-reg-with-reg/imm32/next
    31317 _Primitive-xor-reg-with-reg:  # (payload primitive)
    31318     0x11/imm32/alloc-id:fake:payload
    31319     # var1/reg <- xor var2/reg => 31/xor-with var1/rm32 var2/r32
    31320     0x11/imm32/alloc-id:fake
    31321     _string-xor/imm32/name
    31322     0x11/imm32/alloc-id:fake
    31323     Single-int-var-in-some-register/imm32/inouts
    31324     0x11/imm32/alloc-id:fake
    31325     Single-int-var-in-some-register/imm32/outputs
    31326     0x11/imm32/alloc-id:fake
    31327     _string_31_xor_with/imm32/subx-name
    31328     3/imm32/rm32-is-first-output
    31329     1/imm32/r32-is-first-inout
    31330     0/imm32/no-imm32
    31331     0/imm32/no-imm8
    31332     0/imm32/no-disp32
    31333     0/imm32/no-xm32
    31334     0/imm32/no-x32
    31335     0x11/imm32/alloc-id:fake
    31336     _Primitive-xor-reg-with-mem/imm32/next
    31337 _Primitive-xor-reg-with-mem:  # (payload primitive)
    31338     0x11/imm32/alloc-id:fake:payload
    31339     # xor-with var1 var2/reg => 31/xor-with var1 var2/r32
    31340     0x11/imm32/alloc-id:fake
    31341     _string-xor-with/imm32/name
    31342     0x11/imm32/alloc-id:fake
    31343     Two-args-int-stack-int-reg/imm32/inouts
    31344     0/imm32/no-outputs
    31345     0/imm32/no-outputs
    31346     0x11/imm32/alloc-id:fake
    31347     _string_31_xor_with/imm32/subx-name
    31348     1/imm32/rm32-is-first-inout
    31349     2/imm32/r32-is-second-inout
    31350     0/imm32/no-imm32
    31351     0/imm32/no-imm8
    31352     0/imm32/no-disp32
    31353     0/imm32/no-xm32
    31354     0/imm32/no-x32
    31355     0x11/imm32/alloc-id:fake
    31356     _Primitive-xor-mem-with-reg/imm32/next
    31357 _Primitive-xor-mem-with-reg:  # (payload primitive)
    31358     0x11/imm32/alloc-id:fake:payload
    31359     # var1/reg <- xor var2 => 33/xor var2/rm32 var1/r32
    31360     0x11/imm32/alloc-id:fake
    31361     _string-xor/imm32/name
    31362     0x11/imm32/alloc-id:fake
    31363     Single-int-var-in-mem/imm32/inouts
    31364     0x11/imm32/alloc-id:fake
    31365     Single-int-var-in-some-register/imm32/outputs
    31366     0x11/imm32/alloc-id:fake
    31367     _string_33_xor/imm32/subx-name
    31368     1/imm32/rm32-is-first-inout
    31369     3/imm32/r32-is-first-output
    31370     0/imm32/no-imm32
    31371     0/imm32/no-imm8
    31372     0/imm32/no-disp32
    31373     0/imm32/no-xm32
    31374     0/imm32/no-x32
    31375     0x11/imm32/alloc-id:fake
    31376     _Primitive-xor-lit-with-reg/imm32/next
    31377 _Primitive-xor-lit-with-reg:  # (payload primitive)
    31378     0x11/imm32/alloc-id:fake:payload
    31379     # var1/reg <- xor lit => 81 6/subop/xor var1/rm32 lit/imm32
    31380     0x11/imm32/alloc-id:fake
    31381     _string-xor/imm32/name
    31382     0x11/imm32/alloc-id:fake
    31383     Single-lit-var/imm32/inouts
    31384     0x11/imm32/alloc-id:fake
    31385     Single-int-var-in-some-register/imm32/outputs
    31386     0x11/imm32/alloc-id:fake
    31387     _string_81_subop_xor/imm32/subx-name
    31388     3/imm32/rm32-is-first-output
    31389     0/imm32/no-r32
    31390     1/imm32/imm32-is-first-inout
    31391     0/imm32/no-imm8
    31392     0/imm32/no-disp32
    31393     0/imm32/no-xm32
    31394     0/imm32/no-x32
    31395     0x11/imm32/alloc-id:fake
    31396     _Primitive-xor-lit-with-mem/imm32/next
    31397 _Primitive-xor-lit-with-mem:  # (payload primitive)
    31398     0x11/imm32/alloc-id:fake:payload
    31399     # xor-with var1, lit => 81 6/subop/xor var1/rm32 lit/imm32
    31400     0x11/imm32/alloc-id:fake
    31401     _string-xor-with/imm32/name
    31402     0x11/imm32/alloc-id:fake
    31403     Int-var-and-literal/imm32/inouts
    31404     0/imm32/no-outputs
    31405     0/imm32/no-outputs
    31406     0x11/imm32/alloc-id:fake
    31407     _string_81_subop_xor/imm32/subx-name
    31408     1/imm32/rm32-is-first-inout
    31409     0/imm32/no-r32
    31410     2/imm32/imm32-is-second-inout
    31411     0/imm32/no-imm8
    31412     0/imm32/no-disp32
    31413     0/imm32/no-xm32
    31414     0/imm32/no-x32
    31415     0x11/imm32/alloc-id:fake
    31416     _Primitive-shift-reg-left-by-lit/imm32/next
    31417 _Primitive-shift-reg-left-by-lit:  # (payload primitive)
    31418     0x11/imm32/alloc-id:fake:payload
    31419     # var1/reg <- shift-left lit => c1/shift 4/subop/left var1/rm32 lit/imm32
    31420     0x11/imm32/alloc-id:fake
    31421     _string-shift-left/imm32/name
    31422     0x11/imm32/alloc-id:fake
    31423     Single-lit-var/imm32/inouts
    31424     0x11/imm32/alloc-id:fake
    31425     Single-int-var-in-some-register/imm32/outputs
    31426     0x11/imm32/alloc-id:fake
    31427     _string_c1_subop_shift_left/imm32/subx-name
    31428     3/imm32/rm32-is-first-output
    31429     0/imm32/no-r32
    31430     0/imm32/no-imm32
    31431     1/imm32/imm8-is-first-inout
    31432     0/imm32/no-disp32
    31433     0/imm32/no-xm32
    31434     0/imm32/no-x32
    31435     0x11/imm32/alloc-id:fake
    31436     _Primitive-shift-reg-right-by-lit/imm32/next
    31437 _Primitive-shift-reg-right-by-lit:  # (payload primitive)
    31438     0x11/imm32/alloc-id:fake:payload
    31439     # var1/reg <- shift-right lit => c1/shift 5/subop/right var1/rm32 lit/imm32
    31440     0x11/imm32/alloc-id:fake
    31441     _string-shift-right/imm32/name
    31442     0x11/imm32/alloc-id:fake
    31443     Single-lit-var/imm32/inouts
    31444     0x11/imm32/alloc-id:fake
    31445     Single-int-var-in-some-register/imm32/outputs
    31446     0x11/imm32/alloc-id:fake
    31447     _string_c1_subop_shift_right_padding_zeroes/imm32/subx-name
    31448     3/imm32/rm32-is-first-output
    31449     0/imm32/no-r32
    31450     0/imm32/no-imm32
    31451     1/imm32/imm8-is-first-inout
    31452     0/imm32/no-disp32
    31453     0/imm32/no-xm32
    31454     0/imm32/no-x32
    31455     0x11/imm32/alloc-id:fake
    31456     _Primitive-shift-reg-right-signed-by-lit/imm32/next
    31457 _Primitive-shift-reg-right-signed-by-lit:  # (payload primitive)
    31458     0x11/imm32/alloc-id:fake:payload
    31459     # var1/reg <- shift-right-signed lit => c1/shift 7/subop/right-preserving-sign var1/rm32 lit/imm32
    31460     0x11/imm32/alloc-id:fake
    31461     _string-shift-right-signed/imm32/name
    31462     0x11/imm32/alloc-id:fake
    31463     Single-lit-var/imm32/inouts
    31464     0x11/imm32/alloc-id:fake
    31465     Single-int-var-in-some-register/imm32/outputs
    31466     0x11/imm32/alloc-id:fake
    31467     _string_c1_subop_shift_right_preserving_sign/imm32/subx-name
    31468     3/imm32/rm32-is-first-output
    31469     0/imm32/no-r32
    31470     0/imm32/no-imm32
    31471     1/imm32/imm8-is-first-inout
    31472     0/imm32/no-disp32
    31473     0/imm32/no-xm32
    31474     0/imm32/no-x32
    31475     0x11/imm32/alloc-id:fake
    31476     _Primitive-shift-mem-left-by-lit/imm32/next
    31477 _Primitive-shift-mem-left-by-lit:  # (payload primitive)
    31478     0x11/imm32/alloc-id:fake:payload
    31479     # shift-left var1, lit => c1/shift 4/subop/left var1/rm32 lit/imm32
    31480     0x11/imm32/alloc-id:fake
    31481     _string-shift-left/imm32/name
    31482     0x11/imm32/alloc-id:fake
    31483     Int-var-and-literal/imm32/inouts
    31484     0/imm32/no-outputs
    31485     0/imm32/no-outputs
    31486     0x11/imm32/alloc-id:fake
    31487     _string_c1_subop_shift_left/imm32/subx-name
    31488     1/imm32/rm32-is-first-inout
    31489     0/imm32/no-r32
    31490     0/imm32/no-imm32
    31491     2/imm32/imm8-is-second-inout
    31492     0/imm32/no-disp32
    31493     0/imm32/no-xm32
    31494     0/imm32/no-x32
    31495     0x11/imm32/alloc-id:fake
    31496     _Primitive-shift-mem-right-by-lit/imm32/next
    31497 _Primitive-shift-mem-right-by-lit:  # (payload primitive)
    31498     0x11/imm32/alloc-id:fake:payload
    31499     # shift-right var1, lit => c1/shift 5/subop/right var1/rm32 lit/imm32
    31500     0x11/imm32/alloc-id:fake
    31501     _string-shift-right/imm32/name
    31502     0x11/imm32/alloc-id:fake
    31503     Int-var-and-literal/imm32/inouts
    31504     0/imm32/no-outputs
    31505     0/imm32/no-outputs
    31506     0x11/imm32/alloc-id:fake
    31507     _string_c1_subop_shift_right_padding_zeroes/imm32/subx-name
    31508     1/imm32/rm32-is-first-inout
    31509     0/imm32/no-r32
    31510     0/imm32/no-imm32
    31511     2/imm32/imm8-is-second-inout
    31512     0/imm32/no-disp32
    31513     0/imm32/no-xm32
    31514     0/imm32/no-x32
    31515     0x11/imm32/alloc-id:fake
    31516     _Primitive-shift-mem-right-signed-by-lit/imm32/next
    31517 _Primitive-shift-mem-right-signed-by-lit:  # (payload primitive)
    31518     0x11/imm32/alloc-id:fake:payload
    31519     # shift-right-signed var1, lit => c1/shift 7/subop/right-preserving-sign var1/rm32 lit/imm32
    31520     0x11/imm32/alloc-id:fake
    31521     _string-shift-right-signed/imm32/name
    31522     0x11/imm32/alloc-id:fake
    31523     Int-var-and-literal/imm32/inouts
    31524     0/imm32/no-outputs
    31525     0/imm32/no-outputs
    31526     0x11/imm32/alloc-id:fake
    31527     _string_c1_subop_shift_right_preserving_sign/imm32/subx-name
    31528     1/imm32/rm32-is-first-inout
    31529     0/imm32/no-r32
    31530     0/imm32/no-imm32
    31531     2/imm32/imm8-is-second-inout
    31532     0/imm32/no-disp32
    31533     0/imm32/no-xm32
    31534     0/imm32/no-x32
    31535     0x11/imm32/alloc-id:fake
    31536     _Primitive-copy-to-eax/imm32/next
    31537 # - copy
    31538 _Primitive-copy-to-eax:  # (payload primitive)
    31539     0x11/imm32/alloc-id:fake:payload
    31540     # var/eax <- copy lit => b8/copy-to-eax lit/imm32
    31541     0x11/imm32/alloc-id:fake
    31542     _string-copy/imm32/name
    31543     0x11/imm32/alloc-id:fake
    31544     Single-lit-var/imm32/inouts
    31545     0x11/imm32/alloc-id:fake
    31546     Single-int-var-in-eax/imm32/outputs
    31547     0x11/imm32/alloc-id:fake
    31548     _string_b8_copy_to_eax/imm32/subx-name
    31549     0/imm32/no-rm32
    31550     0/imm32/no-r32
    31551     1/imm32/imm32-is-first-inout
    31552     0/imm32/no-imm8
    31553     0/imm32/no-disp32
    31554     0/imm32/no-xm32
    31555     0/imm32/no-x32
    31556     0x11/imm32/alloc-id:fake
    31557     _Primitive-copy-to-ecx/imm32/next
    31558 _Primitive-copy-to-ecx:  # (payload primitive)
    31559     0x11/imm32/alloc-id:fake:payload
    31560     # var/ecx <- copy lit => b9/copy-to-ecx lit/imm32
    31561     0x11/imm32/alloc-id:fake
    31562     _string-copy/imm32/name
    31563     0x11/imm32/alloc-id:fake
    31564     Single-lit-var/imm32/inouts
    31565     0x11/imm32/alloc-id:fake
    31566     Single-int-var-in-ecx/imm32/outputs
    31567     0x11/imm32/alloc-id:fake
    31568     _string_b9_copy_to_ecx/imm32/subx-name
    31569     0/imm32/no-rm32
    31570     0/imm32/no-r32
    31571     1/imm32/imm32-is-first-inout
    31572     0/imm32/no-imm8
    31573     0/imm32/no-disp32
    31574     0/imm32/no-xm32
    31575     0/imm32/no-x32
    31576     0x11/imm32/alloc-id:fake
    31577     _Primitive-copy-to-edx/imm32/next
    31578 _Primitive-copy-to-edx:  # (payload primitive)
    31579     0x11/imm32/alloc-id:fake:payload
    31580     # var/edx <- copy lit => ba/copy-to-edx lit/imm32
    31581     0x11/imm32/alloc-id:fake
    31582     _string-copy/imm32/name
    31583     0x11/imm32/alloc-id:fake
    31584     Single-lit-var/imm32/inouts
    31585     0x11/imm32/alloc-id:fake
    31586     Single-int-var-in-edx/imm32/outputs
    31587     0x11/imm32/alloc-id:fake
    31588     _string_ba_copy_to_edx/imm32/subx-name
    31589     0/imm32/no-rm32
    31590     0/imm32/no-r32
    31591     1/imm32/imm32-is-first-inout
    31592     0/imm32/no-imm8
    31593     0/imm32/no-disp32
    31594     0/imm32/no-xm32
    31595     0/imm32/no-x32
    31596     0x11/imm32/alloc-id:fake
    31597     _Primitive-copy-to-ebx/imm32/next
    31598 _Primitive-copy-to-ebx:  # (payload primitive)
    31599     0x11/imm32/alloc-id:fake:payload
    31600     # var/ebx <- copy lit => bb/copy-to-ebx lit/imm32
    31601     0x11/imm32/alloc-id:fake
    31602     _string-copy/imm32/name
    31603     0x11/imm32/alloc-id:fake
    31604     Single-lit-var/imm32/inouts
    31605     0x11/imm32/alloc-id:fake
    31606     Single-int-var-in-ebx/imm32/outputs
    31607     0x11/imm32/alloc-id:fake
    31608     _string_bb_copy_to_ebx/imm32/subx-name
    31609     0/imm32/no-rm32
    31610     0/imm32/no-r32
    31611     1/imm32/imm32-is-first-inout
    31612     0/imm32/no-imm8
    31613     0/imm32/no-disp32
    31614     0/imm32/no-xm32
    31615     0/imm32/no-x32
    31616     0x11/imm32/alloc-id:fake
    31617     _Primitive-copy-to-esi/imm32/next
    31618 _Primitive-copy-to-esi:  # (payload primitive)
    31619     0x11/imm32/alloc-id:fake:payload
    31620     # var/esi <- copy lit => be/copy-to-esi lit/imm32
    31621     0x11/imm32/alloc-id:fake
    31622     _string-copy/imm32/name
    31623     0x11/imm32/alloc-id:fake
    31624     Single-lit-var/imm32/inouts
    31625     0x11/imm32/alloc-id:fake
    31626     Single-int-var-in-esi/imm32/outputs
    31627     0x11/imm32/alloc-id:fake
    31628     _string_be_copy_to_esi/imm32/subx-name
    31629     0/imm32/no-rm32
    31630     0/imm32/no-r32
    31631     1/imm32/imm32-is-first-inout
    31632     0/imm32/no-imm8
    31633     0/imm32/no-disp32
    31634     0/imm32/no-xm32
    31635     0/imm32/no-x32
    31636     0x11/imm32/alloc-id:fake
    31637     _Primitive-copy-to-edi/imm32/next
    31638 _Primitive-copy-to-edi:  # (payload primitive)
    31639     0x11/imm32/alloc-id:fake:payload
    31640     # var/edi <- copy lit => bf/copy-to-edi lit/imm32
    31641     0x11/imm32/alloc-id:fake
    31642     _string-copy/imm32/name
    31643     0x11/imm32/alloc-id:fake
    31644     Single-lit-var/imm32/inouts
    31645     0x11/imm32/alloc-id:fake
    31646     Single-int-var-in-edi/imm32/outputs
    31647     0x11/imm32/alloc-id:fake
    31648     _string_bf_copy_to_edi/imm32/subx-name
    31649     0/imm32/no-rm32
    31650     0/imm32/no-r32
    31651     1/imm32/imm32-is-first-inout
    31652     0/imm32/no-imm8
    31653     0/imm32/no-disp32
    31654     0/imm32/no-xm32
    31655     0/imm32/no-x32
    31656     0x11/imm32/alloc-id:fake
    31657     _Primitive-copy-reg-to-reg/imm32/next
    31658 _Primitive-copy-reg-to-reg:  # (payload primitive)
    31659     0x11/imm32/alloc-id:fake:payload
    31660     # var1/reg <- copy var2/reg => 89/<- var1/rm32 var2/r32
    31661     0x11/imm32/alloc-id:fake
    31662     _string-copy/imm32/name
    31663     0x11/imm32/alloc-id:fake
    31664     Single-int-var-in-some-register/imm32/inouts
    31665     0x11/imm32/alloc-id:fake
    31666     Single-int-var-in-some-register/imm32/outputs
    31667     0x11/imm32/alloc-id:fake
    31668     _string_89_<-/imm32/subx-name
    31669     3/imm32/rm32-is-first-output
    31670     1/imm32/r32-is-first-inout
    31671     0/imm32/no-imm32
    31672     0/imm32/no-imm8
    31673     0/imm32/no-disp32
    31674     0/imm32/no-xm32
    31675     0/imm32/no-x32
    31676     0x11/imm32/alloc-id:fake
    31677     _Primitive-copy-reg-to-mem/imm32/next
    31678 _Primitive-copy-reg-to-mem:  # (payload primitive)
    31679     0x11/imm32/alloc-id:fake:payload
    31680     # copy-to var1 var2/reg => 89/<- var1 var2/r32
    31681     0x11/imm32/alloc-id:fake
    31682     _string-copy-to/imm32/name
    31683     0x11/imm32/alloc-id:fake
    31684     Two-args-int-stack-int-reg/imm32/inouts
    31685     0/imm32/no-outputs
    31686     0/imm32/no-outputs
    31687     0x11/imm32/alloc-id:fake
    31688     _string_89_<-/imm32/subx-name
    31689     1/imm32/rm32-is-first-inout
    31690     2/imm32/r32-is-second-inout
    31691     0/imm32/no-imm32
    31692     0/imm32/no-imm8
    31693     0/imm32/no-disp32
    31694     0/imm32/no-xm32
    31695     0/imm32/no-x32
    31696     0x11/imm32/alloc-id:fake
    31697     _Primitive-copy-mem-to-reg/imm32/next
    31698 _Primitive-copy-mem-to-reg:  # (payload primitive)
    31699     0x11/imm32/alloc-id:fake:payload
    31700     # var1/reg <- copy var2 => 8b/-> var2/rm32 var1/r32
    31701     0x11/imm32/alloc-id:fake
    31702     _string-copy/imm32/name
    31703     0x11/imm32/alloc-id:fake
    31704     Single-int-var-in-mem/imm32/inouts
    31705     0x11/imm32/alloc-id:fake
    31706     Single-int-var-in-some-register/imm32/outputs
    31707     0x11/imm32/alloc-id:fake
    31708     _string_8b_->/imm32/subx-name
    31709     1/imm32/rm32-is-first-inout
    31710     3/imm32/r32-is-first-output
    31711     0/imm32/no-imm32
    31712     0/imm32/no-imm8
    31713     0/imm32/no-disp32
    31714     0/imm32/no-xm32
    31715     0/imm32/no-x32
    31716     0x11/imm32/alloc-id:fake
    31717     _Primitive-copy-lit-to-reg/imm32/next
    31718 _Primitive-copy-lit-to-reg:  # (payload primitive)
    31719     0x11/imm32/alloc-id:fake:payload
    31720     # var1/reg <- copy lit => c7 0/subop/copy var1/rm32 lit/imm32
    31721     0x11/imm32/alloc-id:fake
    31722     _string-copy/imm32/name
    31723     0x11/imm32/alloc-id:fake
    31724     Single-lit-var/imm32/inouts
    31725     0x11/imm32/alloc-id:fake
    31726     Single-int-var-in-some-register/imm32/outputs
    31727     0x11/imm32/alloc-id:fake
    31728     _string_c7_subop_copy/imm32/subx-name
    31729     3/imm32/rm32-is-first-output
    31730     0/imm32/no-r32
    31731     1/imm32/imm32-is-first-inout
    31732     0/imm32/no-imm8
    31733     0/imm32/no-disp32
    31734     0/imm32/no-xm32
    31735     0/imm32/no-x32
    31736     0x11/imm32/alloc-id:fake
    31737     _Primitive-copy-lit-to-mem/imm32/next
    31738 _Primitive-copy-lit-to-mem:  # (payload primitive)
    31739     0x11/imm32/alloc-id:fake:payload
    31740     # copy-to var1, lit => c7 0/subop/copy var1/rm32 lit/imm32
    31741     0x11/imm32/alloc-id:fake
    31742     _string-copy-to/imm32/name
    31743     0x11/imm32/alloc-id:fake
    31744     Int-var-and-literal/imm32/inouts
    31745     0/imm32/no-outputs
    31746     0/imm32/no-outputs
    31747     0x11/imm32/alloc-id:fake
    31748     _string_c7_subop_copy/imm32/subx-name
    31749     1/imm32/rm32-is-first-inout
    31750     0/imm32/no-r32
    31751     2/imm32/imm32-is-second-inout
    31752     0/imm32/no-imm8
    31753     0/imm32/no-disp32
    31754     0/imm32/no-xm32
    31755     0/imm32/no-x32
    31756     0x11/imm32/alloc-id:fake
    31757     _Primitive-copy-byte-from-reg/imm32/next
    31758 # - copy byte
    31759 _Primitive-copy-byte-from-reg:
    31760     0x11/imm32/alloc-id:fake:payload
    31761     # var/reg <- copy-byte var2/reg2 => 8a/byte-> %var2 var/r32
    31762     0x11/imm32/alloc-id:fake
    31763     _string-copy-byte/imm32/name
    31764     0x11/imm32/alloc-id:fake
    31765     Single-byte-var-in-some-register/imm32/inouts
    31766     0x11/imm32/alloc-id:fake
    31767     Single-byte-var-in-some-register/imm32/outputs
    31768     0x11/imm32/alloc-id:fake
    31769     _string_8a_copy_byte/imm32/subx-name
    31770     1/imm32/rm32-is-first-inout
    31771     3/imm32/r32-is-first-output
    31772     0/imm32/no-imm32
    31773     0/imm32/no-imm8
    31774     0/imm32/no-disp32
    31775     0/imm32/no-xm32
    31776     0/imm32/no-x32
    31777     0x11/imm32/alloc-id:fake
    31778     _Primitive-copy-byte-from-mem/imm32/next
    31779 _Primitive-copy-byte-from-mem:
    31780     0x11/imm32/alloc-id:fake:payload
    31781     # var/reg <- copy-byte *var2/reg2 => 8a/byte-> *var2 var/r32
    31782     0x11/imm32/alloc-id:fake
    31783     _string-copy-byte/imm32/name
    31784     0x11/imm32/alloc-id:fake
    31785     Single-byte-var-in-mem/imm32/inouts
    31786     0x11/imm32/alloc-id:fake
    31787     Single-byte-var-in-some-register/imm32/outputs
    31788     0x11/imm32/alloc-id:fake
    31789     _string_8a_copy_byte/imm32/subx-name
    31790     1/imm32/rm32-is-first-inout
    31791     3/imm32/r32-is-first-output
    31792     0/imm32/no-imm32
    31793     0/imm32/no-imm8
    31794     0/imm32/no-disp32
    31795     0/imm32/no-xm32
    31796     0/imm32/no-x32
    31797     0x11/imm32/alloc-id:fake
    31798     _Primitive-copy-byte-to-mem/imm32/next
    31799 _Primitive-copy-byte-to-mem:
    31800     0x11/imm32/alloc-id:fake:payload
    31801     # copy-byte-to *var1/reg1, var2/reg2 => 88/byte<- *reg1 reg2/r32
    31802     0x11/imm32/alloc-id:fake
    31803     _string-copy-byte-to/imm32/name
    31804     0x11/imm32/alloc-id:fake
    31805     Two-args-byte-stack-byte-reg/imm32/inouts
    31806     0/imm32/no-outputs
    31807     0/imm32/no-outputs
    31808     0x11/imm32/alloc-id:fake
    31809     _string_88_copy_byte/imm32/subx-name
    31810     1/imm32/rm32-is-first-inout
    31811     2/imm32/r32-is-second-inout
    31812     0/imm32/no-imm32
    31813     0/imm32/no-imm8
    31814     0/imm32/no-disp32
    31815     0/imm32/no-xm32
    31816     0/imm32/no-x32
    31817     0x11/imm32/alloc-id:fake
    31818     _Primitive-address/imm32/next
    31819 # - address
    31820 _Primitive-address:  # (payload primitive)
    31821     0x11/imm32/alloc-id:fake:payload
    31822     # var1/reg <- address var2 => 8d/copy-address var2/rm32 var1/r32
    31823     0x11/imm32/alloc-id:fake
    31824     _string-address/imm32/name
    31825     0x11/imm32/alloc-id:fake
    31826     Single-int-var-in-mem/imm32/inouts
    31827     0x11/imm32/alloc-id:fake
    31828     Single-addr-var-in-some-register/imm32/outputs
    31829     0x11/imm32/alloc-id:fake
    31830     _string_8d_copy_address/imm32/subx-name
    31831     1/imm32/rm32-is-first-inout
    31832     3/imm32/r32-is-first-output
    31833     0/imm32/no-imm32
    31834     0/imm32/no-imm8
    31835     0/imm32/no-disp32
    31836     0/imm32/no-xm32
    31837     0/imm32/no-x32
    31838     0x11/imm32/alloc-id:fake
    31839     _Primitive-compare-reg-with-reg/imm32/next
    31840 # - compare
    31841 _Primitive-compare-reg-with-reg:  # (payload primitive)
    31842     0x11/imm32/alloc-id:fake:payload
    31843     # compare var1/reg1 var2/reg2 => 39/compare var1/rm32 var2/r32
    31844     0x11/imm32/alloc-id:fake
    31845     _string-compare/imm32/name
    31846     0x11/imm32/alloc-id:fake
    31847     Two-int-args-in-regs/imm32/inouts
    31848     0/imm32/no-outputs
    31849     0/imm32/no-outputs
    31850     0x11/imm32/alloc-id:fake
    31851     _string_39_compare->/imm32/subx-name
    31852     1/imm32/rm32-is-first-inout
    31853     2/imm32/r32-is-second-inout
    31854     0/imm32/no-imm32
    31855     0/imm32/no-imm8
    31856     0/imm32/no-disp32
    31857     0/imm32/no-xm32
    31858     0/imm32/no-x32
    31859     0x11/imm32/alloc-id:fake
    31860     _Primitive-compare-mem-with-reg/imm32/next
    31861 _Primitive-compare-mem-with-reg:  # (payload primitive)
    31862     0x11/imm32/alloc-id:fake:payload
    31863     # compare var1 var2/reg => 39/compare var1/rm32 var2/r32
    31864     0x11/imm32/alloc-id:fake
    31865     _string-compare/imm32/name
    31866     0x11/imm32/alloc-id:fake
    31867     Two-args-int-stack-int-reg/imm32/inouts
    31868     0/imm32/no-outputs
    31869     0/imm32/no-outputs
    31870     0x11/imm32/alloc-id:fake
    31871     _string_39_compare->/imm32/subx-name
    31872     1/imm32/rm32-is-first-inout
    31873     2/imm32/r32-is-second-inout
    31874     0/imm32/no-imm32
    31875     0/imm32/no-imm8
    31876     0/imm32/no-disp32
    31877     0/imm32/no-xm32
    31878     0/imm32/no-x32
    31879     0x11/imm32/alloc-id:fake
    31880     _Primitive-compare-reg-with-mem/imm32/next
    31881 _Primitive-compare-reg-with-mem:  # (payload primitive)
    31882     0x11/imm32/alloc-id:fake:payload
    31883     # compare var1/reg var2 => 3b/compare<- var2/rm32 var1/r32
    31884     0x11/imm32/alloc-id:fake
    31885     _string-compare/imm32/name
    31886     0x11/imm32/alloc-id:fake
    31887     Two-args-int-reg-int-stack/imm32/inouts
    31888     0/imm32/no-outputs
    31889     0/imm32/no-outputs
    31890     0x11/imm32/alloc-id:fake
    31891     _string_3b_compare<-/imm32/subx-name
    31892     2/imm32/rm32-is-second-inout
    31893     1/imm32/r32-is-first-inout
    31894     0/imm32/no-imm32
    31895     0/imm32/no-imm8
    31896     0/imm32/no-disp32
    31897     0/imm32/no-xm32
    31898     0/imm32/no-x32
    31899     0x11/imm32/alloc-id:fake
    31900     _Primitive-compare-eax-with-literal/imm32/next
    31901 _Primitive-compare-eax-with-literal:  # (payload primitive)
    31902     0x11/imm32/alloc-id:fake:payload
    31903     # compare var1/eax n => 3d/compare-eax-with n/imm32
    31904     0x11/imm32/alloc-id:fake
    31905     _string-compare/imm32/name
    31906     0x11/imm32/alloc-id:fake
    31907     Two-args-int-eax-int-literal/imm32/inouts
    31908     0/imm32/no-outputs
    31909     0/imm32/no-outputs
    31910     0x11/imm32/alloc-id:fake
    31911     _string_3d_compare_eax_with/imm32/subx-name
    31912     0/imm32/no-rm32
    31913     0/imm32/no-r32
    31914     2/imm32/imm32-is-second-inout
    31915     0/imm32/no-imm8
    31916     0/imm32/no-disp32
    31917     0/imm32/no-xm32
    31918     0/imm32/no-x32
    31919     0x11/imm32/alloc-id:fake
    31920     _Primitive-compare-reg-with-literal/imm32/next
    31921 _Primitive-compare-reg-with-literal:  # (payload primitive)
    31922     0x11/imm32/alloc-id:fake:payload
    31923     # compare var1/reg n => 81 7/subop/compare %reg n/imm32
    31924     0x11/imm32/alloc-id:fake
    31925     _string-compare/imm32/name
    31926     0x11/imm32/alloc-id:fake
    31927     Int-var-in-register-and-literal/imm32/inouts
    31928     0/imm32/no-outputs
    31929     0/imm32/no-outputs
    31930     0x11/imm32/alloc-id:fake
    31931     _string_81_subop_compare/imm32/subx-name
    31932     1/imm32/rm32-is-first-inout
    31933     0/imm32/no-r32
    31934     2/imm32/imm32-is-second-inout
    31935     0/imm32/no-imm8
    31936     0/imm32/no-disp32
    31937     0/imm32/no-xm32
    31938     0/imm32/no-x32
    31939     0x11/imm32/alloc-id:fake
    31940     _Primitive-compare-mem-with-literal/imm32/next
    31941 _Primitive-compare-mem-with-literal:  # (payload primitive)
    31942     0x11/imm32/alloc-id:fake:payload
    31943     # compare var1 n => 81 7/subop/compare *(ebp+___) n/imm32
    31944     0x11/imm32/alloc-id:fake
    31945     _string-compare/imm32/name
    31946     0x11/imm32/alloc-id:fake
    31947     Int-var-and-literal/imm32/inouts
    31948     0/imm32/no-outputs
    31949     0/imm32/no-outputs
    31950     0x11/imm32/alloc-id:fake
    31951     _string_81_subop_compare/imm32/subx-name
    31952     1/imm32/rm32-is-first-inout
    31953     0/imm32/no-r32
    31954     2/imm32/imm32-is-second-inout
    31955     0/imm32/no-imm8
    31956     0/imm32/no-disp32
    31957     0/imm32/no-xm32
    31958     0/imm32/no-x32
    31959     0x11/imm32/alloc-id:fake
    31960     _Primitive-negate-reg/imm32/next
    31961 # - negate
    31962 _Primitive-negate-reg:  # (payload primitive)
    31963     0x11/imm32/alloc-id:fake:payload
    31964     # var1/reg <- negate => f7 3/subop/negate var1/rm32
    31965     0x11/imm32/alloc-id:fake
    31966     _string-negate/imm32/name
    31967     0/imm32/no-inouts
    31968     0/imm32/no-inouts
    31969     0x11/imm32/alloc-id:fake
    31970     Single-int-var-in-some-register/imm32/outputs
    31971     0x11/imm32/alloc-id:fake
    31972     _string_f7_subop_negate/imm32/subx-name
    31973     3/imm32/rm32-is-first-output
    31974     0/imm32/no-r32
    31975     0/imm32/no-imm32
    31976     0/imm32/no-imm8
    31977     0/imm32/no-disp32
    31978     0/imm32/no-xm32
    31979     0/imm32/no-x32
    31980     0x11/imm32/alloc-id:fake
    31981     _Primitive-negate-mem/imm32/next
    31982 _Primitive-negate-mem:  # (payload primitive)
    31983     0x11/imm32/alloc-id:fake:payload
    31984     # negate var1 => f7 3/subop/negate var1/rm32
    31985     0x11/imm32/alloc-id:fake
    31986     _string-negate/imm32/name
    31987     0x11/imm32/alloc-id:fake
    31988     Single-int-var-in-mem/imm32/inouts
    31989     0/imm32/no-outputs
    31990     0/imm32/no-outputs
    31991     0x11/imm32/alloc-id:fake
    31992     _string_f7_subop_negate/imm32/subx-name
    31993     1/imm32/rm32-is-first-inout
    31994     0/imm32/no-r32
    31995     0/imm32/no-imm32
    31996     0/imm32/no-imm8
    31997     0/imm32/no-disp32
    31998     0/imm32/no-xm32
    31999     0/imm32/no-x32
    32000     0x11/imm32/alloc-id:fake
    32001     _Primitive-multiply-reg-by-reg/imm32/next
    32002 # - multiply
    32003 _Primitive-multiply-reg-by-reg:  # (payload primitive)
    32004     0x11/imm32/alloc-id:fake:payload
    32005     # var1/reg <- multiply var2 => 0f af/multiply var2/rm32 var1/r32
    32006     0x11/imm32/alloc-id:fake
    32007     _string-multiply/imm32/name
    32008     0x11/imm32/alloc-id:fake
    32009     Single-int-var-in-some-register/imm32/inouts
    32010     0x11/imm32/alloc-id:fake
    32011     Single-int-var-in-some-register/imm32/outputs
    32012     0x11/imm32/alloc-id:fake
    32013     _string_0f_af_multiply/imm32/subx-name
    32014     1/imm32/rm32-is-first-inout
    32015     3/imm32/r32-is-first-output
    32016     0/imm32/no-imm32
    32017     0/imm32/no-imm8
    32018     0/imm32/no-disp32
    32019     0/imm32/no-xm32
    32020     0/imm32/no-x32
    32021     0x11/imm32/alloc-id:fake
    32022     _Primitive-multiply-reg-by-mem/imm32/next
    32023 _Primitive-multiply-reg-by-mem:  # (payload primitive)
    32024     0x11/imm32/alloc-id:fake:payload
    32025     # var1/reg <- multiply var2 => 0f af/multiply var2/rm32 var1/r32
    32026     0x11/imm32/alloc-id:fake
    32027     _string-multiply/imm32/name
    32028     0x11/imm32/alloc-id:fake
    32029     Single-int-var-in-mem/imm32/inouts
    32030     0x11/imm32/alloc-id:fake
    32031     Single-int-var-in-some-register/imm32/outputs
    32032     0x11/imm32/alloc-id:fake
    32033     _string_0f_af_multiply/imm32/subx-name
    32034     1/imm32/rm32-is-first-inout
    32035     3/imm32/r32-is-first-output
    32036     0/imm32/no-imm32
    32037     0/imm32/no-imm8
    32038     0/imm32/no-disp32
    32039     0/imm32/no-xm32
    32040     0/imm32/no-x32
    32041     0x11/imm32/alloc-id:fake
    32042     _Primitive-convert-mem-to-xreg/imm32/next
    32043 # - convert int to floating point
    32044 _Primitive-convert-mem-to-xreg:  # (payload primitive)
    32045     0x11/imm32/alloc-id:fake:payload
    32046     # var1/xreg <- convert var2 => f3 0f 2a/convert-to-float var2/rm32 var1/x32
    32047     0x11/imm32/alloc-id:fake
    32048     _string-convert/imm32/name
    32049     0x11/imm32/alloc-id:fake
    32050     Single-int-var-in-mem/imm32/inouts
    32051     0x11/imm32/alloc-id:fake
    32052     Single-float-var-in-some-register/imm32/outputs
    32053     0x11/imm32/alloc-id:fake
    32054     _string_f3_0f_2a_convert_to_float/imm32/subx-name
    32055     1/imm32/rm32-is-first-inout
    32056     0/imm32/no-r32
    32057     0/imm32/no-imm32
    32058     0/imm32/no-imm8
    32059     0/imm32/no-disp32
    32060     0/imm32/no-xm32
    32061     3/imm32/x32-is-first-output
    32062     0x11/imm32/alloc-id:fake
    32063     _Primitive-convert-reg-to-xreg/imm32/next
    32064 _Primitive-convert-reg-to-xreg:  # (payload primitive)
    32065     0x11/imm32/alloc-id:fake:payload
    32066     # var1/xreg <- convert var2/reg => f3 0f 2a/convert-to-float var2/rm32 var1/x32
    32067     0x11/imm32/alloc-id:fake
    32068     _string-convert/imm32/name
    32069     0x11/imm32/alloc-id:fake
    32070     Single-int-var-in-some-register/imm32/inouts
    32071     0x11/imm32/alloc-id:fake
    32072     Single-float-var-in-some-register/imm32/outputs
    32073     0x11/imm32/alloc-id:fake
    32074     _string_f3_0f_2a_convert_to_float/imm32/subx-name
    32075     1/imm32/rm32-is-first-inout
    32076     0/imm32/no-r32
    32077     0/imm32/no-imm32
    32078     0/imm32/no-imm8
    32079     0/imm32/no-disp32
    32080     0/imm32/no-xm32
    32081     3/imm32/x32-is-first-output
    32082     0x11/imm32/alloc-id:fake
    32083     _Primitive-convert-xmem-to-reg/imm32/next
    32084 # - convert floating point to int
    32085 _Primitive-convert-xmem-to-reg:  # (payload primitive)
    32086     0x11/imm32/alloc-id:fake:payload
    32087     # var1/reg <- convert var2 => f3 0f 2d/convert-to-int var2/xm32 var1/r32
    32088     0x11/imm32/alloc-id:fake
    32089     _string-convert/imm32/name
    32090     0x11/imm32/alloc-id:fake
    32091     Single-float-var-in-mem/imm32/inouts
    32092     0x11/imm32/alloc-id:fake
    32093     Single-int-var-in-some-register/imm32/outputs
    32094     0x11/imm32/alloc-id:fake
    32095     _string_f3_0f_2d_convert_to_int/imm32/subx-name
    32096     0/imm32/no-rm32
    32097     3/imm32/r32-is-first-output
    32098     0/imm32/no-imm32
    32099     0/imm32/no-imm8
    32100     0/imm32/no-disp32
    32101     1/imm32/xm32-is-first-inout
    32102     0/imm32/no-x32
    32103     0x11/imm32/alloc-id:fake
    32104     _Primitive-convert-xreg-to-reg/imm32/next
    32105 _Primitive-convert-xreg-to-reg:  # (payload primitive)
    32106     0x11/imm32/alloc-id:fake:payload
    32107     # var1/reg <- convert var2/xreg => f3 0f 2d/convert-to-int var2/xm32 var1/r32
    32108     0x11/imm32/alloc-id:fake
    32109     _string-convert/imm32/name
    32110     0x11/imm32/alloc-id:fake
    32111     Single-float-var-in-some-register/imm32/inouts
    32112     0x11/imm32/alloc-id:fake
    32113     Single-int-var-in-some-register/imm32/outputs
    32114     0x11/imm32/alloc-id:fake
    32115     _string_f3_0f_2d_convert_to_int/imm32/subx-name
    32116     0/imm32/no-rm32
    32117     3/imm32/r32-is-first-output
    32118     0/imm32/no-imm32
    32119     0/imm32/no-imm8
    32120     0/imm32/no-disp32
    32121     1/imm32/xm32-is-first-inout
    32122     0/imm32/no-x32
    32123     0x11/imm32/alloc-id:fake
    32124     _Primitive-truncate-xmem-to-reg/imm32/next
    32125 _Primitive-truncate-xmem-to-reg:  # (payload primitive)
    32126     0x11/imm32/alloc-id:fake:payload
    32127     # var1/reg <- truncate var2 => f3 0f 2c/truncate-to-int var2/xm32 var1/r32
    32128     0x11/imm32/alloc-id:fake
    32129     _string-truncate/imm32/name
    32130     0x11/imm32/alloc-id:fake
    32131     Single-float-var-in-mem/imm32/inouts
    32132     0x11/imm32/alloc-id:fake
    32133     Single-int-var-in-some-register/imm32/outputs
    32134     0x11/imm32/alloc-id:fake
    32135     _string_f3_0f_2c_truncate_to_int/imm32/subx-name
    32136     0/imm32/no-rm32
    32137     3/imm32/r32-is-first-output
    32138     0/imm32/no-imm32
    32139     0/imm32/no-imm8
    32140     0/imm32/no-disp32
    32141     1/imm32/xm32-is-first-inout
    32142     0/imm32/no-x32
    32143     0x11/imm32/alloc-id:fake
    32144     _Primitive-truncate-xreg-to-reg/imm32/next
    32145 _Primitive-truncate-xreg-to-reg:  # (payload primitive)
    32146     0x11/imm32/alloc-id:fake:payload
    32147     # var1/reg <- truncate var2/xreg => f3 0f 2c/truncate-to-int var2/xm32 var1/r32
    32148     0x11/imm32/alloc-id:fake
    32149     _string-truncate/imm32/name
    32150     0x11/imm32/alloc-id:fake
    32151     Single-float-var-in-some-register/imm32/inouts
    32152     0x11/imm32/alloc-id:fake
    32153     Single-int-var-in-some-register/imm32/outputs
    32154     0x11/imm32/alloc-id:fake
    32155     _string_f3_0f_2c_truncate_to_int/imm32/subx-name
    32156     0/imm32/no-rm32
    32157     3/imm32/r32-is-first-output
    32158     0/imm32/no-imm32
    32159     0/imm32/no-imm8
    32160     0/imm32/no-disp32
    32161     1/imm32/xm32-is-first-inout
    32162     0/imm32/no-x32
    32163     0x11/imm32/alloc-id:fake
    32164     _Primitive-reinterpret-xmem-as-reg/imm32/next
    32165 # - reinterpret bytes (just for debugging)
    32166 _Primitive-reinterpret-xmem-as-reg:  # (payload primitive)
    32167     0x11/imm32/alloc-id:fake:payload
    32168     # var1/reg <- reinterpret var2 => 8b/-> var2/xm32 var1/r32
    32169     0x11/imm32/alloc-id:fake
    32170     _string-reinterpret/imm32/name
    32171     0x11/imm32/alloc-id:fake
    32172     Single-float-var-in-mem/imm32/inouts
    32173     0x11/imm32/alloc-id:fake
    32174     Single-int-var-in-some-register/imm32/outputs
    32175     0x11/imm32/alloc-id:fake
    32176     _string_8b_->/imm32/subx-name
    32177     0/imm32/no-rm32
    32178     3/imm32/r32-is-first-output
    32179     0/imm32/no-imm32
    32180     0/imm32/no-imm8
    32181     0/imm32/no-disp32
    32182     1/imm32/xm32-is-first-inout
    32183     0/imm32/no-x32
    32184     0x11/imm32/alloc-id:fake
    32185     _Primitive-reinterpret-mem-as-xreg/imm32/next
    32186 _Primitive-reinterpret-mem-as-xreg:  # (payload primitive)
    32187     0x11/imm32/alloc-id:fake:payload
    32188     # var1/xreg <- reinterpret var2 => f3 0f 10/-> var2/rm32 var1/x32
    32189     0x11/imm32/alloc-id:fake
    32190     _string-reinterpret/imm32/name
    32191     0x11/imm32/alloc-id:fake
    32192     Single-int-var-in-mem/imm32/inouts
    32193     0x11/imm32/alloc-id:fake
    32194     Single-float-var-in-some-register/imm32/outputs
    32195     0x11/imm32/alloc-id:fake
    32196     _string_f3_0f_10_copy/imm32/subx-name
    32197     1/imm32/rm32-is-first-inout
    32198     0/imm32/no-r32
    32199     0/imm32/no-imm32
    32200     0/imm32/no-imm8
    32201     0/imm32/no-disp32
    32202     0/imm32/no-xm32
    32203     3/imm32/x32-is-first-output
    32204     0x11/imm32/alloc-id:fake
    32205     _Primitive-copy-xreg-to-xreg/imm32/next
    32206 # - floating-point copy
    32207 _Primitive-copy-xreg-to-xreg:  # (payload primitive)
    32208     0x11/imm32/alloc-id:fake:payload
    32209     # var1/xreg <- copy var2/xreg => f3 0f 11/<- var1/xm32 var2/x32
    32210     0x11/imm32/alloc-id:fake
    32211     _string-copy/imm32/name
    32212     0x11/imm32/alloc-id:fake
    32213     Single-float-var-in-some-register/imm32/inouts
    32214     0x11/imm32/alloc-id:fake
    32215     Single-float-var-in-some-register/imm32/outputs
    32216     0x11/imm32/alloc-id:fake
    32217     _string_f3_0f_11_copy/imm32/subx-name
    32218     0/imm32/no-rm32
    32219     0/imm32/no-r32
    32220     0/imm32/no-imm32
    32221     0/imm32/no-imm8
    32222     0/imm32/no-disp32
    32223     3/imm32/xm32-is-first-output
    32224     1/imm32/x32-is-first-inout
    32225     0x11/imm32/alloc-id:fake
    32226     _Primitive-copy-xreg-to-mem/imm32/next
    32227 _Primitive-copy-xreg-to-mem:  # (payload primitive)
    32228     0x11/imm32/alloc-id:fake:payload
    32229     # copy-to var1 var2/xreg => f3 0f 11/<- var1 var2/x32
    32230     0x11/imm32/alloc-id:fake
    32231     _string-copy-to/imm32/name
    32232     0x11/imm32/alloc-id:fake
    32233     Two-args-float-stack-float-reg/imm32/inouts
    32234     0/imm32/no-outputs
    32235     0/imm32/no-outputs
    32236     0x11/imm32/alloc-id:fake
    32237     _string_f3_0f_11_copy/imm32/subx-name
    32238     0/imm32/no-rm32
    32239     0/imm32/no-r32
    32240     0/imm32/no-imm32
    32241     0/imm32/no-imm8
    32242     0/imm32/no-disp32
    32243     1/imm32/xm32-is-first-inout
    32244     2/imm32/x32-is-second-inout
    32245     0x11/imm32/alloc-id:fake
    32246     _Primitive-copy-mem-to-xreg/imm32/next
    32247 _Primitive-copy-mem-to-xreg:  # (payload primitive)
    32248     0x11/imm32/alloc-id:fake:payload
    32249     # var1/xreg <- copy var2 => f3 0f 10/-> var2/rm32 var1/x32
    32250     0x11/imm32/alloc-id:fake
    32251     _string-copy/imm32/name
    32252     0x11/imm32/alloc-id:fake
    32253     Single-float-var-in-mem/imm32/inouts
    32254     0x11/imm32/alloc-id:fake
    32255     Single-float-var-in-some-register/imm32/outputs
    32256     0x11/imm32/alloc-id:fake
    32257     _string_f3_0f_10_copy/imm32/subx-name
    32258     0/imm32/no-rm32
    32259     0/imm32/no-r32
    32260     0/imm32/no-imm32
    32261     0/imm32/no-imm8
    32262     0/imm32/no-disp32
    32263     1/imm32/xm32-is-first-inout
    32264     3/imm32/x32-is-first-output
    32265     0x11/imm32/alloc-id:fake
    32266     _Primitive-address-of-xmem/imm32/next
    32267 # - floating-point-address
    32268 _Primitive-address-of-xmem:  # (payload primitive)
    32269     0x11/imm32/alloc-id:fake:payload
    32270     # var1/reg <- address var2 => 8d/copy-address var2/rm32 var1/r32
    32271     0x11/imm32/alloc-id:fake
    32272     _string-address/imm32/name
    32273     0x11/imm32/alloc-id:fake
    32274     Single-float-var-in-mem/imm32/inouts
    32275     0x11/imm32/alloc-id:fake
    32276     Single-addr-var-in-some-register/imm32/outputs
    32277     0x11/imm32/alloc-id:fake
    32278     _string_8d_copy_address/imm32/subx-name
    32279     1/imm32/rm32-is-first-inout
    32280     3/imm32/r32-is-first-output
    32281     0/imm32/no-imm32
    32282     0/imm32/no-imm8
    32283     0/imm32/no-disp32
    32284     0/imm32/no-xm32
    32285     0/imm32/no-x32
    32286     0x11/imm32/alloc-id:fake
    32287     _Primitive-add-xreg-to-xreg/imm32/next
    32288 # - floating-point add
    32289 _Primitive-add-xreg-to-xreg:  # (payload primitive)
    32290     0x11/imm32/alloc-id:fake:payload
    32291     # var1/xreg <- add var2/xreg => f3 0f 58/add var1/xm32 var2/x32
    32292     0x11/imm32/alloc-id:fake
    32293     _string-add/imm32/name
    32294     0x11/imm32/alloc-id:fake
    32295     Single-float-var-in-some-register/imm32/inouts
    32296     0x11/imm32/alloc-id:fake
    32297     Single-float-var-in-some-register/imm32/outputs
    32298     0x11/imm32/alloc-id:fake
    32299     _string_f3_0f_58_add/imm32/subx-name
    32300     0/imm32/no-rm32
    32301     0/imm32/no-r32
    32302     0/imm32/no-imm32
    32303     0/imm32/no-imm8
    32304     0/imm32/no-disp32
    32305     1/imm32/xm32-is-first-inout
    32306     3/imm32/x32-is-first-output
    32307     0x11/imm32/alloc-id:fake
    32308     _Primitive-add-mem-to-xreg/imm32/next
    32309 _Primitive-add-mem-to-xreg:  # (payload primitive)
    32310     0x11/imm32/alloc-id:fake:payload
    32311     # var1/xreg <- add var2 => f3 0f 58/add var2/xm32 var1/x32
    32312     0x11/imm32/alloc-id:fake
    32313     _string-add/imm32/name
    32314     0x11/imm32/alloc-id:fake
    32315     Single-float-var-in-mem/imm32/inouts
    32316     0x11/imm32/alloc-id:fake
    32317     Single-float-var-in-some-register/imm32/outputs
    32318     0x11/imm32/alloc-id:fake
    32319     _string_f3_0f_58_add/imm32/subx-name
    32320     0/imm32/no-rm32
    32321     0/imm32/no-r32
    32322     0/imm32/no-imm32
    32323     0/imm32/no-imm8
    32324     0/imm32/no-disp32
    32325     1/imm32/xm32-is-first-inout
    32326     3/imm32/x32-is-first-output
    32327     0x11/imm32/alloc-id:fake
    32328     _Primitive-subtract-xreg-from-xreg/imm32/next
    32329 # - floating-point subtract
    32330 _Primitive-subtract-xreg-from-xreg:  # (payload primitive)
    32331     0x11/imm32/alloc-id:fake:payload
    32332     # var1/xreg <- subtract var2/xreg => f3 0f 5c/subtract var1/xm32 var2/x32
    32333     0x11/imm32/alloc-id:fake
    32334     _string-subtract/imm32/name
    32335     0x11/imm32/alloc-id:fake
    32336     Single-float-var-in-some-register/imm32/inouts
    32337     0x11/imm32/alloc-id:fake
    32338     Single-float-var-in-some-register/imm32/outputs
    32339     0x11/imm32/alloc-id:fake
    32340     _string_f3_0f_5c_subtract/imm32/subx-name
    32341     0/imm32/no-rm32
    32342     0/imm32/no-r32
    32343     0/imm32/no-imm32
    32344     0/imm32/no-imm8
    32345     0/imm32/no-disp32
    32346     1/imm32/xm32-is-first-inout
    32347     3/imm32/x32-is-first-output
    32348     0x11/imm32/alloc-id:fake
    32349     _Primitive-subtract-mem-from-xreg/imm32/next
    32350 _Primitive-subtract-mem-from-xreg:  # (payload primitive)
    32351     0x11/imm32/alloc-id:fake:payload
    32352     # var1/xreg <- subtract var2 => f3 0f 5c/subtract var2/xm32 var1/x32
    32353     0x11/imm32/alloc-id:fake
    32354     _string-subtract/imm32/name
    32355     0x11/imm32/alloc-id:fake
    32356     Single-float-var-in-mem/imm32/inouts
    32357     0x11/imm32/alloc-id:fake
    32358     Single-float-var-in-some-register/imm32/outputs
    32359     0x11/imm32/alloc-id:fake
    32360     _string_f3_0f_5c_subtract/imm32/subx-name
    32361     0/imm32/no-rm32
    32362     0/imm32/no-r32
    32363     0/imm32/no-imm32
    32364     0/imm32/no-imm8
    32365     0/imm32/no-disp32
    32366     1/imm32/xm32-is-first-inout
    32367     3/imm32/x32-is-first-output
    32368     0x11/imm32/alloc-id:fake
    32369     _Primitive-multiply-xreg-by-xreg/imm32/next
    32370 # - floating-point multiply
    32371 _Primitive-multiply-xreg-by-xreg:  # (payload primitive)
    32372     0x11/imm32/alloc-id:fake:payload
    32373     # var1/xreg <- multiply var2 => f3 0f 59/multiply var2/xm32 var1/x32
    32374     0x11/imm32/alloc-id:fake
    32375     _string-multiply/imm32/name
    32376     0x11/imm32/alloc-id:fake
    32377     Single-float-var-in-some-register/imm32/inouts
    32378     0x11/imm32/alloc-id:fake
    32379     Single-float-var-in-some-register/imm32/outputs
    32380     0x11/imm32/alloc-id:fake
    32381     _string_f3_0f_59_multiply/imm32/subx-name
    32382     0/imm32/no-rm32
    32383     0/imm32/no-r32
    32384     0/imm32/no-imm32
    32385     0/imm32/no-imm8
    32386     0/imm32/no-disp32
    32387     1/imm32/xm32-is-first-inout
    32388     3/imm32/x32-is-first-output
    32389     0x11/imm32/alloc-id:fake
    32390     _Primitive-multiply-xreg-by-mem/imm32/next
    32391 _Primitive-multiply-xreg-by-mem:  # (payload primitive)
    32392     0x11/imm32/alloc-id:fake:payload
    32393     # var1/xreg <- multiply var2 => 53 0f 59/multiply var2/xm32 var1/x32
    32394     0x11/imm32/alloc-id:fake
    32395     _string-multiply/imm32/name
    32396     0x11/imm32/alloc-id:fake
    32397     Single-float-var-in-mem/imm32/inouts
    32398     0x11/imm32/alloc-id:fake
    32399     Single-float-var-in-some-register/imm32/outputs
    32400     0x11/imm32/alloc-id:fake
    32401     _string_f3_0f_59_multiply/imm32/subx-name
    32402     0/imm32/no-rm32
    32403     0/imm32/no-r32
    32404     0/imm32/no-imm32
    32405     0/imm32/no-imm8
    32406     0/imm32/no-disp32
    32407     1/imm32/xm32-is-first-inout
    32408     3/imm32/x32-is-first-output
    32409     0x11/imm32/alloc-id:fake
    32410     _Primitive-divide-xreg-by-xreg/imm32/next
    32411 # - floating-point divide
    32412 _Primitive-divide-xreg-by-xreg:  # (payload primitive)
    32413     0x11/imm32/alloc-id:fake:payload
    32414     # var1/xreg <- divide var2 => f3 0f 5e/divide var2/xm32 var1/x32
    32415     0x11/imm32/alloc-id:fake
    32416     _string-divide/imm32/name
    32417     0x11/imm32/alloc-id:fake
    32418     Single-float-var-in-some-register/imm32/inouts
    32419     0x11/imm32/alloc-id:fake
    32420     Single-float-var-in-some-register/imm32/outputs
    32421     0x11/imm32/alloc-id:fake
    32422     _string_f3_0f_5e_divide/imm32/subx-name
    32423     0/imm32/no-rm32
    32424     0/imm32/no-r32
    32425     0/imm32/no-imm32
    32426     0/imm32/no-imm8
    32427     0/imm32/no-disp32
    32428     1/imm32/xm32-is-first-inout
    32429     3/imm32/x32-is-first-output
    32430     0x11/imm32/alloc-id:fake
    32431     _Primitive-divide-xreg-by-mem/imm32/next
    32432 _Primitive-divide-xreg-by-mem:  # (payload primitive)
    32433     0x11/imm32/alloc-id:fake:payload
    32434     # var1/xreg <- divide var2 => f3 0f 5e/divide var2/xm32 var1/x32
    32435     0x11/imm32/alloc-id:fake
    32436     _string-divide/imm32/name
    32437     0x11/imm32/alloc-id:fake
    32438     Single-float-var-in-mem/imm32/inouts
    32439     0x11/imm32/alloc-id:fake
    32440     Single-float-var-in-some-register/imm32/outputs
    32441     0x11/imm32/alloc-id:fake
    32442     _string_f3_0f_5e_divide/imm32/subx-name
    32443     0/imm32/no-rm32
    32444     0/imm32/no-r32
    32445     0/imm32/no-imm32
    32446     0/imm32/no-imm8
    32447     0/imm32/no-disp32
    32448     1/imm32/xm32-is-first-inout
    32449     3/imm32/x32-is-first-output
    32450     0x11/imm32/alloc-id:fake
    32451     _Primitive-max-xreg-with-xreg/imm32/next
    32452 # - floating-point maximum
    32453 _Primitive-max-xreg-with-xreg:  # (payload primitive)
    32454     0x11/imm32/alloc-id:fake:payload
    32455     # var1/xreg <- max var2 => f3 0f 5f/max var2/xm32 var1/x32
    32456     0x11/imm32/alloc-id:fake
    32457     _string-max/imm32/name
    32458     0x11/imm32/alloc-id:fake
    32459     Single-float-var-in-some-register/imm32/inouts
    32460     0x11/imm32/alloc-id:fake
    32461     Single-float-var-in-some-register/imm32/outputs
    32462     0x11/imm32/alloc-id:fake
    32463     _string_f3_0f_5f_max/imm32/subx-name
    32464     0/imm32/no-rm32
    32465     0/imm32/no-r32
    32466     0/imm32/no-imm32
    32467     0/imm32/no-imm8
    32468     0/imm32/no-disp32
    32469     1/imm32/xm32-is-first-inout
    32470     3/imm32/x32-is-first-output
    32471     0x11/imm32/alloc-id:fake
    32472     _Primitive-max-xreg-with-mem/imm32/next
    32473 _Primitive-max-xreg-with-mem:  # (payload primitive)
    32474     0x11/imm32/alloc-id:fake:payload
    32475     # var1/xreg <- divide var2 => f3 0f 5f/max var2/xm32 var1/x32
    32476     0x11/imm32/alloc-id:fake
    32477     _string-max/imm32/name
    32478     0x11/imm32/alloc-id:fake
    32479     Single-float-var-in-mem/imm32/inouts
    32480     0x11/imm32/alloc-id:fake
    32481     Single-float-var-in-some-register/imm32/outputs
    32482     0x11/imm32/alloc-id:fake
    32483     _string_f3_0f_5f_max/imm32/subx-name
    32484     0/imm32/no-rm32
    32485     0/imm32/no-r32
    32486     0/imm32/no-imm32
    32487     0/imm32/no-imm8
    32488     0/imm32/no-disp32
    32489     1/imm32/xm32-is-first-inout
    32490     3/imm32/x32-is-first-output
    32491     0x11/imm32/alloc-id:fake
    32492     _Primitive-min-xreg-with-xreg/imm32/next
    32493 # - floating-point minimum
    32494 _Primitive-min-xreg-with-xreg:  # (payload primitive)
    32495     0x11/imm32/alloc-id:fake:payload
    32496     # var1/xreg <- divide var2 => f3 0f 5d/min var2/xm32 var1/x32
    32497     0x11/imm32/alloc-id:fake
    32498     _string-min/imm32/name
    32499     0x11/imm32/alloc-id:fake
    32500     Single-float-var-in-some-register/imm32/inouts
    32501     0x11/imm32/alloc-id:fake
    32502     Single-float-var-in-some-register/imm32/outputs
    32503     0x11/imm32/alloc-id:fake
    32504     _string_f3_0f_5d_min/imm32/subx-name
    32505     0/imm32/no-rm32
    32506     0/imm32/no-r32
    32507     0/imm32/no-imm32
    32508     0/imm32/no-imm8
    32509     0/imm32/no-disp32
    32510     1/imm32/xm32-is-first-inout
    32511     3/imm32/x32-is-first-output
    32512     0x11/imm32/alloc-id:fake
    32513     _Primitive-min-xreg-with-mem/imm32/next
    32514 _Primitive-min-xreg-with-mem:  # (payload primitive)
    32515     0x11/imm32/alloc-id:fake:payload
    32516     # var1/xreg <- divide var2 => f3 0f 5d/min var2/xm32 var1/x32
    32517     0x11/imm32/alloc-id:fake
    32518     _string-min/imm32/name
    32519     0x11/imm32/alloc-id:fake
    32520     Single-float-var-in-mem/imm32/inouts
    32521     0x11/imm32/alloc-id:fake
    32522     Single-float-var-in-some-register/imm32/outputs
    32523     0x11/imm32/alloc-id:fake
    32524     _string_f3_0f_5d_min/imm32/subx-name
    32525     0/imm32/no-rm32
    32526     0/imm32/no-r32
    32527     0/imm32/no-imm32
    32528     0/imm32/no-imm8
    32529     0/imm32/no-disp32
    32530     1/imm32/xm32-is-first-inout
    32531     3/imm32/x32-is-first-output
    32532     0x11/imm32/alloc-id:fake
    32533     _Primitive-reciprocal-xreg-to-xreg/imm32/next
    32534 # - floating-point reciprocal
    32535 _Primitive-reciprocal-xreg-to-xreg:  # (payload primitive)
    32536     0x11/imm32/alloc-id:fake:payload
    32537     # var1/xreg <- reciprocal var2 => f3 0f 53/reciprocal var2/xm32 var1/x32
    32538     0x11/imm32/alloc-id:fake
    32539     _string-reciprocal/imm32/name
    32540     0x11/imm32/alloc-id:fake
    32541     Single-float-var-in-some-register/imm32/inouts
    32542     0x11/imm32/alloc-id:fake
    32543     Single-float-var-in-some-register/imm32/outputs
    32544     0x11/imm32/alloc-id:fake
    32545     _string_f3_0f_53_reciprocal/imm32/subx-name
    32546     0/imm32/no-rm32
    32547     0/imm32/no-r32
    32548     0/imm32/no-imm32
    32549     0/imm32/no-imm8
    32550     0/imm32/no-disp32
    32551     1/imm32/xm32-is-first-inout
    32552     3/imm32/x32-is-first-output
    32553     0x11/imm32/alloc-id:fake
    32554     _Primitive-reciprocal-mem-to-xreg/imm32/next
    32555 _Primitive-reciprocal-mem-to-xreg:  # (payload primitive)
    32556     0x11/imm32/alloc-id:fake:payload
    32557     # var1/xreg <- divide var2 => f3 0f 53/reciprocal var2/xm32 var1/x32
    32558     0x11/imm32/alloc-id:fake
    32559     _string-reciprocal/imm32/name
    32560     0x11/imm32/alloc-id:fake
    32561     Single-float-var-in-mem/imm32/inouts
    32562     0x11/imm32/alloc-id:fake
    32563     Single-float-var-in-some-register/imm32/outputs
    32564     0x11/imm32/alloc-id:fake
    32565     _string_f3_0f_53_reciprocal/imm32/subx-name
    32566     0/imm32/no-rm32
    32567     0/imm32/no-r32
    32568     0/imm32/no-imm32
    32569     0/imm32/no-imm8
    32570     0/imm32/no-disp32
    32571     1/imm32/xm32-is-first-inout
    32572     3/imm32/x32-is-first-output
    32573     0x11/imm32/alloc-id:fake
    32574     _Primitive-square-root-xreg-to-xreg/imm32/next
    32575 # - floating-point square root
    32576 _Primitive-square-root-xreg-to-xreg:  # (payload primitive)
    32577     0x11/imm32/alloc-id:fake:payload
    32578     # var1/xreg <- square-root var2 => f3 0f 51/square-root var2/xm32 var1/x32
    32579     0x11/imm32/alloc-id:fake
    32580     _string-square-root/imm32/name
    32581     0x11/imm32/alloc-id:fake
    32582     Single-float-var-in-some-register/imm32/inouts
    32583     0x11/imm32/alloc-id:fake
    32584     Single-float-var-in-some-register/imm32/outputs
    32585     0x11/imm32/alloc-id:fake
    32586     _string_f3_0f_51_square_root/imm32/subx-name
    32587     0/imm32/no-rm32
    32588     0/imm32/no-r32
    32589     0/imm32/no-imm32
    32590     0/imm32/no-imm8
    32591     0/imm32/no-disp32
    32592     1/imm32/xm32-is-first-inout
    32593     3/imm32/x32-is-first-output
    32594     0x11/imm32/alloc-id:fake
    32595     _Primitive-square-root-mem-to-xreg/imm32/next
    32596 _Primitive-square-root-mem-to-xreg:  # (payload primitive)
    32597     0x11/imm32/alloc-id:fake:payload
    32598     # var1/xreg <- divide var2 => f3 0f 51/square-root var2/xm32 var1/x32
    32599     0x11/imm32/alloc-id:fake
    32600     _string-square-root/imm32/name
    32601     0x11/imm32/alloc-id:fake
    32602     Single-float-var-in-mem/imm32/inouts
    32603     0x11/imm32/alloc-id:fake
    32604     Single-float-var-in-some-register/imm32/outputs
    32605     0x11/imm32/alloc-id:fake
    32606     _string_f3_0f_51_square_root/imm32/subx-name
    32607     0/imm32/no-rm32
    32608     0/imm32/no-r32
    32609     0/imm32/no-imm32
    32610     0/imm32/no-imm8
    32611     0/imm32/no-disp32
    32612     1/imm32/xm32-is-first-inout
    32613     3/imm32/x32-is-first-output
    32614     0x11/imm32/alloc-id:fake
    32615     _Primitive-inverse-square-root-xreg-to-xreg/imm32/next
    32616 # - floating-point inverse square root 1/sqrt(x)
    32617 _Primitive-inverse-square-root-xreg-to-xreg:  # (payload primitive)
    32618     0x11/imm32/alloc-id:fake:payload
    32619     # var1/xreg <- reciprocal var2 => f3 0f 52/inverse-square-root var2/xm32 var1/x32
    32620     0x11/imm32/alloc-id:fake
    32621     _string-inverse-square-root/imm32/name
    32622     0x11/imm32/alloc-id:fake
    32623     Single-float-var-in-some-register/imm32/inouts
    32624     0x11/imm32/alloc-id:fake
    32625     Single-float-var-in-some-register/imm32/outputs
    32626     0x11/imm32/alloc-id:fake
    32627     _string_f3_0f_52_inverse_square_root/imm32/subx-name
    32628     0/imm32/no-rm32
    32629     0/imm32/no-r32
    32630     0/imm32/no-imm32
    32631     0/imm32/no-imm8
    32632     0/imm32/no-disp32
    32633     1/imm32/xm32-is-first-inout
    32634     3/imm32/x32-is-first-output
    32635     0x11/imm32/alloc-id:fake
    32636     _Primitive-inverse-square-root-mem-to-xreg/imm32/next
    32637 _Primitive-inverse-square-root-mem-to-xreg:  # (payload primitive)
    32638     0x11/imm32/alloc-id:fake:payload
    32639     # var1/xreg <- divide var2 => f3 0f 52/inverse-square-root var2/xm32 var1/x32
    32640     0x11/imm32/alloc-id:fake
    32641     _string-inverse-square-root/imm32/name
    32642     0x11/imm32/alloc-id:fake
    32643     Single-float-var-in-mem/imm32/inouts
    32644     0x11/imm32/alloc-id:fake
    32645     Single-float-var-in-some-register/imm32/outputs
    32646     0x11/imm32/alloc-id:fake
    32647     _string_f3_0f_52_inverse_square_root/imm32/subx-name
    32648     0/imm32/no-rm32
    32649     0/imm32/no-r32
    32650     0/imm32/no-imm32
    32651     0/imm32/no-imm8
    32652     0/imm32/no-disp32
    32653     1/imm32/xm32-is-first-inout
    32654     3/imm32/x32-is-first-output
    32655     0x11/imm32/alloc-id:fake
    32656     _Primitive-compare-xreg-with-xreg/imm32/next
    32657 # - floating-point compare
    32658 _Primitive-compare-xreg-with-xreg:  # (payload primitive)
    32659     0x11/imm32/alloc-id:fake:payload
    32660     # compare var1/reg1 var2/reg2 => 0f 2f/compare var2/x32 var1/xm32
    32661     0x11/imm32/alloc-id:fake
    32662     _string-compare/imm32/name
    32663     0x11/imm32/alloc-id:fake
    32664     Two-float-args-in-regs/imm32/inouts
    32665     0/imm32/no-outputs
    32666     0/imm32/no-outputs
    32667     0x11/imm32/alloc-id:fake
    32668     _string_0f_2f_compare/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     2/imm32/xm32-is-second-inout
    32675     1/imm32/x32-is-first-inout
    32676     0x11/imm32/alloc-id:fake
    32677     _Primitive-compare-xreg-with-mem/imm32/next
    32678 _Primitive-compare-xreg-with-mem:  # (payload primitive)
    32679     0x11/imm32/alloc-id:fake:payload
    32680     # compare var1/xreg var2 => 0f 2f/compare var1/x32 var2/xm32
    32681     0x11/imm32/alloc-id:fake
    32682     _string-compare/imm32/name
    32683     0x11/imm32/alloc-id:fake
    32684     Two-args-float-reg-float-stack/imm32/inouts
    32685     0/imm32/no-outputs
    32686     0/imm32/no-outputs
    32687     0x11/imm32/alloc-id:fake
    32688     _string_0f_2f_compare/imm32/subx-name
    32689     0/imm32/no-rm32
    32690     0/imm32/no-r32
    32691     0/imm32/no-imm32
    32692     0/imm32/no-imm8
    32693     0/imm32/no-disp32
    32694     2/imm32/xm32-is-second-inout
    32695     1/imm32/x32-is-first-inout
    32696     0x11/imm32/alloc-id:fake
    32697     _Primitive-break-if-addr</imm32/next
    32698 # - branches
    32699 _Primitive-break-if-addr<:  # (payload primitive)
    32700     0x11/imm32/alloc-id:fake:payload
    32701     0x11/imm32/alloc-id:fake
    32702     _string-break-if-addr</imm32/name
    32703     0/imm32/no-inouts
    32704     0/imm32/no-inouts
    32705     0/imm32/no-outputs
    32706     0/imm32/no-outputs
    32707     0x11/imm32/alloc-id:fake
    32708     _string_0f_82_jump_break/imm32/subx-name
    32709     0/imm32/no-rm32
    32710     0/imm32/no-r32
    32711     0/imm32/no-imm32
    32712     0/imm32/no-imm8
    32713     0/imm32/no-disp32
    32714     0/imm32/no-xm32
    32715     0/imm32/no-x32
    32716     0x11/imm32/alloc-id:fake
    32717     _Primitive-break-if-addr>=/imm32/next
    32718 _Primitive-break-if-addr>=:  # (payload primitive)
    32719     0x11/imm32/alloc-id:fake:payload
    32720     0x11/imm32/alloc-id:fake
    32721     _string-break-if-addr>=/imm32/name
    32722     0/imm32/no-inouts
    32723     0/imm32/no-inouts
    32724     0/imm32/no-outputs
    32725     0/imm32/no-outputs
    32726     0x11/imm32/alloc-id:fake
    32727     _string_0f_83_jump_break/imm32/subx-name
    32728     0/imm32/no-rm32
    32729     0/imm32/no-r32
    32730     0/imm32/no-imm32
    32731     0/imm32/no-imm8
    32732     0/imm32/no-disp32
    32733     0/imm32/no-xm32
    32734     0/imm32/no-x32
    32735     0x11/imm32/alloc-id:fake
    32736     _Primitive-break-if-=/imm32/next
    32737 _Primitive-break-if-=:  # (payload primitive)
    32738     0x11/imm32/alloc-id:fake:payload
    32739     0x11/imm32/alloc-id:fake
    32740     _string-break-if-=/imm32/name
    32741     0/imm32/no-inouts
    32742     0/imm32/no-inouts
    32743     0/imm32/no-outputs
    32744     0/imm32/no-outputs
    32745     0x11/imm32/alloc-id:fake
    32746     _string_0f_84_jump_break/imm32/subx-name
    32747     0/imm32/no-rm32
    32748     0/imm32/no-r32
    32749     0/imm32/no-imm32
    32750     0/imm32/no-imm8
    32751     0/imm32/no-disp32
    32752     0/imm32/no-xm32
    32753     0/imm32/no-x32
    32754     0x11/imm32/alloc-id:fake
    32755     _Primitive-break-if-!=/imm32/next
    32756 _Primitive-break-if-!=:  # (payload primitive)
    32757     0x11/imm32/alloc-id:fake:payload
    32758     0x11/imm32/alloc-id:fake
    32759     _string-break-if-!=/imm32/name
    32760     0/imm32/no-inouts
    32761     0/imm32/no-inouts
    32762     0/imm32/no-outputs
    32763     0/imm32/no-outputs
    32764     0x11/imm32/alloc-id:fake
    32765     _string_0f_85_jump_break/imm32/subx-name
    32766     0/imm32/no-rm32
    32767     0/imm32/no-r32
    32768     0/imm32/no-imm32
    32769     0/imm32/no-imm8
    32770     0/imm32/no-disp32
    32771     0/imm32/no-xm32
    32772     0/imm32/no-x32
    32773     0x11/imm32/alloc-id:fake
    32774     _Primitive-break-if-addr<=/imm32/next
    32775 _Primitive-break-if-addr<=:  # (payload primitive)
    32776     0x11/imm32/alloc-id:fake:payload
    32777     0x11/imm32/alloc-id:fake
    32778     _string-break-if-addr<=/imm32/name
    32779     0/imm32/no-inouts
    32780     0/imm32/no-inouts
    32781     0/imm32/no-outputs
    32782     0/imm32/no-outputs
    32783     0x11/imm32/alloc-id:fake
    32784     _string_0f_86_jump_break/imm32/subx-name
    32785     0/imm32/no-rm32
    32786     0/imm32/no-r32
    32787     0/imm32/no-imm32
    32788     0/imm32/no-imm8
    32789     0/imm32/no-disp32
    32790     0/imm32/no-xm32
    32791     0/imm32/no-x32
    32792     0x11/imm32/alloc-id:fake
    32793     _Primitive-break-if-addr>/imm32/next
    32794 _Primitive-break-if-addr>:  # (payload primitive)
    32795     0x11/imm32/alloc-id:fake:payload
    32796     0x11/imm32/alloc-id:fake
    32797     _string-break-if-addr>/imm32/name
    32798     0/imm32/no-inouts
    32799     0/imm32/no-inouts
    32800     0/imm32/no-outputs
    32801     0/imm32/no-outputs
    32802     0x11/imm32/alloc-id:fake
    32803     _string_0f_87_jump_break/imm32/subx-name
    32804     0/imm32/no-rm32
    32805     0/imm32/no-r32
    32806     0/imm32/no-imm32
    32807     0/imm32/no-imm8
    32808     0/imm32/no-disp32
    32809     0/imm32/no-xm32
    32810     0/imm32/no-x32
    32811     0x11/imm32/alloc-id:fake
    32812     _Primitive-break-if-</imm32/next
    32813 _Primitive-break-if-<:  # (payload primitive)
    32814     0x11/imm32/alloc-id:fake:payload
    32815     0x11/imm32/alloc-id:fake
    32816     _string-break-if-</imm32/name
    32817     0/imm32/no-inouts
    32818     0/imm32/no-inouts
    32819     0/imm32/no-outputs
    32820     0/imm32/no-outputs
    32821     0x11/imm32/alloc-id:fake
    32822     _string_0f_8c_jump_break/imm32/subx-name
    32823     0/imm32/no-rm32
    32824     0/imm32/no-r32
    32825     0/imm32/no-imm32
    32826     0/imm32/no-imm8
    32827     0/imm32/no-disp32
    32828     0/imm32/no-xm32
    32829     0/imm32/no-x32
    32830     0x11/imm32/alloc-id:fake
    32831     _Primitive-break-if->=/imm32/next
    32832 _Primitive-break-if->=:  # (payload primitive)
    32833     0x11/imm32/alloc-id:fake:payload
    32834     0x11/imm32/alloc-id:fake
    32835     _string-break-if->=/imm32/name
    32836     0/imm32/no-inouts
    32837     0/imm32/no-inouts
    32838     0/imm32/no-outputs
    32839     0/imm32/no-outputs
    32840     0x11/imm32/alloc-id:fake
    32841     _string_0f_8d_jump_break/imm32/subx-name
    32842     0/imm32/no-rm32
    32843     0/imm32/no-r32
    32844     0/imm32/no-imm32
    32845     0/imm32/no-imm8
    32846     0/imm32/no-disp32
    32847     0/imm32/no-xm32
    32848     0/imm32/no-x32
    32849     0x11/imm32/alloc-id:fake
    32850     _Primitive-break-if-<=/imm32/next
    32851 _Primitive-break-if-<=:  # (payload primitive)
    32852     0x11/imm32/alloc-id:fake:payload
    32853     0x11/imm32/alloc-id:fake
    32854     _string-break-if-<=/imm32/name
    32855     0/imm32/no-inouts
    32856     0/imm32/no-inouts
    32857     0/imm32/no-outputs
    32858     0/imm32/no-outputs
    32859     0x11/imm32/alloc-id:fake
    32860     _string_0f_8e_jump_break/imm32/subx-name
    32861     0/imm32/no-rm32
    32862     0/imm32/no-r32
    32863     0/imm32/no-imm32
    32864     0/imm32/no-imm8
    32865     0/imm32/no-disp32
    32866     0/imm32/no-xm32
    32867     0/imm32/no-x32
    32868     0x11/imm32/alloc-id:fake
    32869     _Primitive-break-if->/imm32/next
    32870 _Primitive-break-if->:  # (payload primitive)
    32871     0x11/imm32/alloc-id:fake:payload
    32872     0x11/imm32/alloc-id:fake
    32873     _string-break-if->/imm32/name
    32874     0/imm32/no-inouts
    32875     0/imm32/no-inouts
    32876     0/imm32/no-outputs
    32877     0/imm32/no-outputs
    32878     0x11/imm32/alloc-id:fake
    32879     _string_0f_8f_jump_break/imm32/subx-name
    32880     0/imm32/no-rm32
    32881     0/imm32/no-r32
    32882     0/imm32/no-imm32
    32883     0/imm32/no-imm8
    32884     0/imm32/no-disp32
    32885     0/imm32/no-xm32
    32886     0/imm32/no-x32
    32887     0x11/imm32/alloc-id:fake
    32888     _Primitive-break-if-carry/imm32/next
    32889 _Primitive-break-if-carry:  # (payload primitive)
    32890     0x11/imm32/alloc-id:fake:payload
    32891     0x11/imm32/alloc-id:fake
    32892     _string-break-if-carry/imm32/name
    32893     0/imm32/no-inouts
    32894     0/imm32/no-inouts
    32895     0/imm32/no-outputs
    32896     0/imm32/no-outputs
    32897     0x11/imm32/alloc-id:fake
    32898     _string_0f_82_jump_break/imm32/subx-name
    32899     0/imm32/no-rm32
    32900     0/imm32/no-r32
    32901     0/imm32/no-imm32
    32902     0/imm32/no-imm8
    32903     0/imm32/no-disp32
    32904     0/imm32/no-xm32
    32905     0/imm32/no-x32
    32906     0x11/imm32/alloc-id:fake
    32907     _Primitive-break-if-not-carry/imm32/next
    32908 _Primitive-break-if-not-carry:  # (payload primitive)
    32909     0x11/imm32/alloc-id:fake:payload
    32910     0x11/imm32/alloc-id:fake
    32911     _string-break-if-not-carry/imm32/name
    32912     0/imm32/no-inouts
    32913     0/imm32/no-inouts
    32914     0/imm32/no-outputs
    32915     0/imm32/no-outputs
    32916     0x11/imm32/alloc-id:fake
    32917     _string_0f_83_jump_break/imm32/subx-name
    32918     0/imm32/no-rm32
    32919     0/imm32/no-r32
    32920     0/imm32/no-imm32
    32921     0/imm32/no-imm8
    32922     0/imm32/no-disp32
    32923     0/imm32/no-xm32
    32924     0/imm32/no-x32
    32925     0x11/imm32/alloc-id:fake
    32926     _Primitive-break-if-overflow/imm32/next
    32927 _Primitive-break-if-overflow:  # (payload primitive)
    32928     0x11/imm32/alloc-id:fake:payload
    32929     0x11/imm32/alloc-id:fake
    32930     _string-break-if-overflow/imm32/name
    32931     0/imm32/no-inouts
    32932     0/imm32/no-inouts
    32933     0/imm32/no-outputs
    32934     0/imm32/no-outputs
    32935     0x11/imm32/alloc-id:fake
    32936     _string_0f_80_jump_break/imm32/subx-name
    32937     0/imm32/no-rm32
    32938     0/imm32/no-r32
    32939     0/imm32/no-imm32
    32940     0/imm32/no-imm8
    32941     0/imm32/no-disp32
    32942     0/imm32/no-xm32
    32943     0/imm32/no-x32
    32944     0x11/imm32/alloc-id:fake
    32945     _Primitive-break-if-not-overflow/imm32/next
    32946 _Primitive-break-if-not-overflow:  # (payload primitive)
    32947     0x11/imm32/alloc-id:fake:payload
    32948     0x11/imm32/alloc-id:fake
    32949     _string-break-if-not-overflow/imm32/name
    32950     0/imm32/no-inouts
    32951     0/imm32/no-inouts
    32952     0/imm32/no-outputs
    32953     0/imm32/no-outputs
    32954     0x11/imm32/alloc-id:fake
    32955     _string_0f_81_jump_break/imm32/subx-name
    32956     0/imm32/no-rm32
    32957     0/imm32/no-r32
    32958     0/imm32/no-imm32
    32959     0/imm32/no-imm8
    32960     0/imm32/no-disp32
    32961     0/imm32/no-xm32
    32962     0/imm32/no-x32
    32963     0x11/imm32/alloc-id:fake
    32964     _Primitive-break/imm32/next
    32965 _Primitive-break:  # (payload primitive)
    32966     0x11/imm32/alloc-id:fake:payload
    32967     0x11/imm32/alloc-id:fake
    32968     _string-break/imm32/name
    32969     0/imm32/no-inouts
    32970     0/imm32/no-inouts
    32971     0/imm32/no-outputs
    32972     0/imm32/no-outputs
    32973     0x11/imm32/alloc-id:fake
    32974     _string_e9_jump_break/imm32/subx-name
    32975     0/imm32/no-rm32
    32976     0/imm32/no-r32
    32977     0/imm32/no-imm32
    32978     0/imm32/no-imm8
    32979     0/imm32/no-disp32
    32980     0/imm32/no-xm32
    32981     0/imm32/no-x32
    32982     0x11/imm32/alloc-id:fake
    32983     _Primitive-loop-if-addr</imm32/next
    32984 _Primitive-loop-if-addr<:  # (payload primitive)
    32985     0x11/imm32/alloc-id:fake:payload
    32986     0x11/imm32/alloc-id:fake
    32987     _string-loop-if-addr</imm32/name
    32988     0/imm32/no-inouts
    32989     0/imm32/no-inouts
    32990     0/imm32/no-outputs
    32991     0/imm32/no-outputs
    32992     0x11/imm32/alloc-id:fake
    32993     _string_0f_82_jump_loop/imm32/subx-name
    32994     0/imm32/no-rm32
    32995     0/imm32/no-r32
    32996     0/imm32/no-imm32
    32997     0/imm32/no-imm8
    32998     0/imm32/no-disp32
    32999     0/imm32/no-xm32
    33000     0/imm32/no-x32
    33001     0x11/imm32/alloc-id:fake
    33002     _Primitive-loop-if-addr>=/imm32/next
    33003 _Primitive-loop-if-addr>=:  # (payload primitive)
    33004     0x11/imm32/alloc-id:fake:payload
    33005     0x11/imm32/alloc-id:fake
    33006     _string-loop-if-addr>=/imm32/name
    33007     0/imm32/no-inouts
    33008     0/imm32/no-inouts
    33009     0/imm32/no-outputs
    33010     0/imm32/no-outputs
    33011     0x11/imm32/alloc-id:fake
    33012     _string_0f_83_jump_loop/imm32/subx-name
    33013     0/imm32/no-rm32
    33014     0/imm32/no-r32
    33015     0/imm32/no-imm32
    33016     0/imm32/no-imm8
    33017     0/imm32/no-disp32
    33018     0/imm32/no-xm32
    33019     0/imm32/no-x32
    33020     0x11/imm32/alloc-id:fake
    33021     _Primitive-loop-if-=/imm32/next
    33022 _Primitive-loop-if-=:  # (payload primitive)
    33023     0x11/imm32/alloc-id:fake:payload
    33024     0x11/imm32/alloc-id:fake
    33025     _string-loop-if-=/imm32/name
    33026     0/imm32/no-inouts
    33027     0/imm32/no-inouts
    33028     0/imm32/no-outputs
    33029     0/imm32/no-outputs
    33030     0x11/imm32/alloc-id:fake
    33031     _string_0f_84_jump_loop/imm32/subx-name
    33032     0/imm32/no-rm32
    33033     0/imm32/no-r32
    33034     0/imm32/no-imm32
    33035     0/imm32/no-imm8
    33036     0/imm32/no-disp32
    33037     0/imm32/no-xm32
    33038     0/imm32/no-x32
    33039     0x11/imm32/alloc-id:fake
    33040     _Primitive-loop-if-!=/imm32/next
    33041 _Primitive-loop-if-!=:  # (payload primitive)
    33042     0x11/imm32/alloc-id:fake:payload
    33043     0x11/imm32/alloc-id:fake
    33044     _string-loop-if-!=/imm32/name
    33045     0/imm32/no-inouts
    33046     0/imm32/no-inouts
    33047     0/imm32/no-outputs
    33048     0/imm32/no-outputs
    33049     0x11/imm32/alloc-id:fake
    33050     _string_0f_85_jump_loop/imm32/subx-name
    33051     0/imm32/no-rm32
    33052     0/imm32/no-r32
    33053     0/imm32/no-imm32
    33054     0/imm32/no-imm8
    33055     0/imm32/no-disp32
    33056     0/imm32/no-xm32
    33057     0/imm32/no-x32
    33058     0x11/imm32/alloc-id:fake
    33059     _Primitive-loop-if-addr<=/imm32/next
    33060 _Primitive-loop-if-addr<=:  # (payload primitive)
    33061     0x11/imm32/alloc-id:fake:payload
    33062     0x11/imm32/alloc-id:fake
    33063     _string-loop-if-addr<=/imm32/name
    33064     0/imm32/no-inouts
    33065     0/imm32/no-inouts
    33066     0/imm32/no-outputs
    33067     0/imm32/no-outputs
    33068     0x11/imm32/alloc-id:fake
    33069     _string_0f_86_jump_loop/imm32/subx-name
    33070     0/imm32/no-rm32
    33071     0/imm32/no-r32
    33072     0/imm32/no-imm32
    33073     0/imm32/no-imm8
    33074     0/imm32/no-disp32
    33075     0/imm32/no-xm32
    33076     0/imm32/no-x32
    33077     0x11/imm32/alloc-id:fake
    33078     _Primitive-loop-if-addr>/imm32/next
    33079 _Primitive-loop-if-addr>:  # (payload primitive)
    33080     0x11/imm32/alloc-id:fake:payload
    33081     0x11/imm32/alloc-id:fake
    33082     _string-loop-if-addr>/imm32/name
    33083     0/imm32/no-inouts
    33084     0/imm32/no-inouts
    33085     0/imm32/no-outputs
    33086     0/imm32/no-outputs
    33087     0x11/imm32/alloc-id:fake
    33088     _string_0f_87_jump_loop/imm32/subx-name
    33089     0/imm32/no-rm32
    33090     0/imm32/no-r32
    33091     0/imm32/no-imm32
    33092     0/imm32/no-imm8
    33093     0/imm32/no-disp32
    33094     0/imm32/no-xm32
    33095     0/imm32/no-x32
    33096     0x11/imm32/alloc-id:fake
    33097     _Primitive-loop-if-</imm32/next
    33098 _Primitive-loop-if-<:  # (payload primitive)
    33099     0x11/imm32/alloc-id:fake:payload
    33100     0x11/imm32/alloc-id:fake
    33101     _string-loop-if-</imm32/name
    33102     0/imm32/no-inouts
    33103     0/imm32/no-inouts
    33104     0/imm32/no-outputs
    33105     0/imm32/no-outputs
    33106     0x11/imm32/alloc-id:fake
    33107     _string_0f_8c_jump_loop/imm32/subx-name
    33108     0/imm32/no-rm32
    33109     0/imm32/no-r32
    33110     0/imm32/no-imm32
    33111     0/imm32/no-imm8
    33112     0/imm32/no-disp32
    33113     0/imm32/no-xm32
    33114     0/imm32/no-x32
    33115     0x11/imm32/alloc-id:fake
    33116     _Primitive-loop-if->=/imm32/next
    33117 _Primitive-loop-if->=:  # (payload primitive)
    33118     0x11/imm32/alloc-id:fake:payload
    33119     0x11/imm32/alloc-id:fake
    33120     _string-loop-if->=/imm32/name
    33121     0/imm32/no-inouts
    33122     0/imm32/no-inouts
    33123     0/imm32/no-outputs
    33124     0/imm32/no-outputs
    33125     0x11/imm32/alloc-id:fake
    33126     _string_0f_8d_jump_loop/imm32/subx-name
    33127     0/imm32/no-rm32
    33128     0/imm32/no-r32
    33129     0/imm32/no-imm32
    33130     0/imm32/no-imm8
    33131     0/imm32/no-disp32
    33132     0/imm32/no-xm32
    33133     0/imm32/no-x32
    33134     0x11/imm32/alloc-id:fake
    33135     _Primitive-loop-if-<=/imm32/next
    33136 _Primitive-loop-if-<=:  # (payload primitive)
    33137     0x11/imm32/alloc-id:fake:payload
    33138     0x11/imm32/alloc-id:fake
    33139     _string-loop-if-<=/imm32/name
    33140     0/imm32/no-inouts
    33141     0/imm32/no-inouts
    33142     0/imm32/no-outputs
    33143     0/imm32/no-outputs
    33144     0x11/imm32/alloc-id:fake
    33145     _string_0f_8e_jump_loop/imm32/subx-name
    33146     0/imm32/no-rm32
    33147     0/imm32/no-r32
    33148     0/imm32/no-imm32
    33149     0/imm32/no-imm8
    33150     0/imm32/no-disp32
    33151     0/imm32/no-xm32
    33152     0/imm32/no-x32
    33153     0x11/imm32/alloc-id:fake
    33154     _Primitive-loop-if->/imm32/next
    33155 _Primitive-loop-if->:  # (payload primitive)
    33156     0x11/imm32/alloc-id:fake:payload
    33157     0x11/imm32/alloc-id:fake
    33158     _string-loop-if->/imm32/name
    33159     0/imm32/no-inouts
    33160     0/imm32/no-inouts
    33161     0/imm32/no-outputs
    33162     0/imm32/no-outputs
    33163     0x11/imm32/alloc-id:fake
    33164     _string_0f_8f_jump_loop/imm32/subx-name
    33165     0/imm32/no-rm32
    33166     0/imm32/no-r32
    33167     0/imm32/no-imm32
    33168     0/imm32/no-imm8
    33169     0/imm32/no-disp32
    33170     0/imm32/no-xm32
    33171     0/imm32/no-x32
    33172     0x11/imm32/alloc-id:fake
    33173     _Primitive-loop-if-carry/imm32/next
    33174 _Primitive-loop-if-carry:  # (payload primitive)
    33175     0x11/imm32/alloc-id:fake:payload
    33176     0x11/imm32/alloc-id:fake
    33177     _string-loop-if-carry/imm32/name
    33178     0/imm32/no-inouts
    33179     0/imm32/no-inouts
    33180     0/imm32/no-outputs
    33181     0/imm32/no-outputs
    33182     0x11/imm32/alloc-id:fake
    33183     _string_0f_82_jump_loop/imm32/subx-name
    33184     0/imm32/no-rm32
    33185     0/imm32/no-r32
    33186     0/imm32/no-imm32
    33187     0/imm32/no-imm8
    33188     0/imm32/no-disp32
    33189     0/imm32/no-xm32
    33190     0/imm32/no-x32
    33191     0x11/imm32/alloc-id:fake
    33192     _Primitive-loop-if-not-carry/imm32/next
    33193 _Primitive-loop-if-not-carry:  # (payload primitive)
    33194     0x11/imm32/alloc-id:fake:payload
    33195     0x11/imm32/alloc-id:fake
    33196     _string-loop-if-not-carry/imm32/name
    33197     0/imm32/no-inouts
    33198     0/imm32/no-inouts
    33199     0/imm32/no-outputs
    33200     0/imm32/no-outputs
    33201     0x11/imm32/alloc-id:fake
    33202     _string_0f_83_jump_loop/imm32/subx-name
    33203     0/imm32/no-rm32
    33204     0/imm32/no-r32
    33205     0/imm32/no-imm32
    33206     0/imm32/no-imm8
    33207     0/imm32/no-disp32
    33208     0/imm32/no-xm32
    33209     0/imm32/no-x32
    33210     0x11/imm32/alloc-id:fake
    33211     _Primitive-loop-if-overflow/imm32/next
    33212 _Primitive-loop-if-overflow:  # (payload primitive)
    33213     0x11/imm32/alloc-id:fake:payload
    33214     0x11/imm32/alloc-id:fake
    33215     _string-loop-if-overflow/imm32/name
    33216     0/imm32/no-inouts
    33217     0/imm32/no-inouts
    33218     0/imm32/no-outputs
    33219     0/imm32/no-outputs
    33220     0x11/imm32/alloc-id:fake
    33221     _string_0f_80_jump_loop/imm32/subx-name
    33222     0/imm32/no-rm32
    33223     0/imm32/no-r32
    33224     0/imm32/no-imm32
    33225     0/imm32/no-imm8
    33226     0/imm32/no-disp32
    33227     0/imm32/no-xm32
    33228     0/imm32/no-x32
    33229     0x11/imm32/alloc-id:fake
    33230     _Primitive-loop-if-not-overflow/imm32/next
    33231 _Primitive-loop-if-not-overflow:  # (payload primitive)
    33232     0x11/imm32/alloc-id:fake:payload
    33233     0x11/imm32/alloc-id:fake
    33234     _string-loop-if-not-overflow/imm32/name
    33235     0/imm32/no-inouts
    33236     0/imm32/no-inouts
    33237     0/imm32/no-outputs
    33238     0/imm32/no-outputs
    33239     0x11/imm32/alloc-id:fake
    33240     _string_0f_81_jump_loop/imm32/subx-name
    33241     0/imm32/no-rm32
    33242     0/imm32/no-r32
    33243     0/imm32/no-imm32
    33244     0/imm32/no-imm8
    33245     0/imm32/no-disp32
    33246     0/imm32/no-xm32
    33247     0/imm32/no-x32
    33248     0x11/imm32/alloc-id:fake
    33249     _Primitive-loop/imm32/next  # we probably don't need an unconditional break
    33250 _Primitive-loop:  # (payload primitive)
    33251     0x11/imm32/alloc-id:fake:payload
    33252     0x11/imm32/alloc-id:fake
    33253     _string-loop/imm32/name
    33254     0/imm32/no-inouts
    33255     0/imm32/no-inouts
    33256     0/imm32/no-outputs
    33257     0/imm32/no-outputs
    33258     0x11/imm32/alloc-id:fake
    33259     _string_e9_jump_loop/imm32/subx-name
    33260     0/imm32/no-rm32
    33261     0/imm32/no-r32
    33262     0/imm32/no-imm32
    33263     0/imm32/no-imm8
    33264     0/imm32/no-disp32
    33265     0/imm32/no-xm32
    33266     0/imm32/no-x32
    33267     0x11/imm32/alloc-id:fake
    33268     _Primitive-break-if-addr<-named/imm32/next
    33269 # - branches to named blocks
    33270 _Primitive-break-if-addr<-named:  # (payload primitive)
    33271     0x11/imm32/alloc-id:fake:payload
    33272     0x11/imm32/alloc-id:fake
    33273     _string-break-if-addr</imm32/name
    33274     0x11/imm32/alloc-id:fake
    33275     Single-lit-var/imm32/inouts
    33276     0/imm32/no-outputs
    33277     0/imm32/no-outputs
    33278     0x11/imm32/alloc-id:fake
    33279     _string_0f_82_jump_label/imm32/subx-name
    33280     0/imm32/no-rm32
    33281     0/imm32/no-r32
    33282     0/imm32/no-imm32
    33283     0/imm32/no-imm8
    33284     1/imm32/disp32-is-first-inout
    33285     0/imm32/no-xm32
    33286     0/imm32/no-x32
    33287     0x11/imm32/alloc-id:fake
    33288     _Primitive-break-if-addr>=-named/imm32/next
    33289 _Primitive-break-if-addr>=-named:  # (payload primitive)
    33290     0x11/imm32/alloc-id:fake:payload
    33291     0x11/imm32/alloc-id:fake
    33292     _string-break-if-addr>=/imm32/name
    33293     0x11/imm32/alloc-id:fake
    33294     Single-lit-var/imm32/inouts
    33295     0/imm32/no-outputs
    33296     0/imm32/no-outputs
    33297     0x11/imm32/alloc-id:fake
    33298     _string_0f_83_jump_label/imm32/subx-name
    33299     0/imm32/no-rm32
    33300     0/imm32/no-r32
    33301     0/imm32/no-imm32
    33302     0/imm32/no-imm8
    33303     1/imm32/disp32-is-first-inout
    33304     0/imm32/no-xm32
    33305     0/imm32/no-x32
    33306     0x11/imm32/alloc-id:fake
    33307     _Primitive-break-if-=-named/imm32/next
    33308 _Primitive-break-if-=-named:  # (payload primitive)
    33309     0x11/imm32/alloc-id:fake:payload
    33310     0x11/imm32/alloc-id:fake
    33311     _string-break-if-=/imm32/name
    33312     0x11/imm32/alloc-id:fake
    33313     Single-lit-var/imm32/inouts
    33314     0/imm32/no-outputs
    33315     0/imm32/no-outputs
    33316     0x11/imm32/alloc-id:fake
    33317     _string_0f_84_jump_label/imm32/subx-name
    33318     0/imm32/no-rm32
    33319     0/imm32/no-r32
    33320     0/imm32/no-imm32
    33321     0/imm32/no-imm8
    33322     1/imm32/disp32-is-first-inout
    33323     0/imm32/no-xm32
    33324     0/imm32/no-x32
    33325     0x11/imm32/alloc-id:fake
    33326     _Primitive-break-if-!=-named/imm32/next
    33327 _Primitive-break-if-!=-named:  # (payload primitive)
    33328     0x11/imm32/alloc-id:fake:payload
    33329     0x11/imm32/alloc-id:fake
    33330     _string-break-if-!=/imm32/name
    33331     0x11/imm32/alloc-id:fake
    33332     Single-lit-var/imm32/inouts
    33333     0/imm32/no-outputs
    33334     0/imm32/no-outputs
    33335     0x11/imm32/alloc-id:fake
    33336     _string_0f_85_jump_label/imm32/subx-name
    33337     0/imm32/no-rm32
    33338     0/imm32/no-r32
    33339     0/imm32/no-imm32
    33340     0/imm32/no-imm8
    33341     1/imm32/disp32-is-first-inout
    33342     0/imm32/no-xm32
    33343     0/imm32/no-x32
    33344     0x11/imm32/alloc-id:fake
    33345     _Primitive-break-if-addr<=-named/imm32/next
    33346 _Primitive-break-if-addr<=-named:  # (payload primitive)
    33347     0x11/imm32/alloc-id:fake:payload
    33348     0x11/imm32/alloc-id:fake
    33349     _string-break-if-addr<=/imm32/name
    33350     0x11/imm32/alloc-id:fake
    33351     Single-lit-var/imm32/inouts
    33352     0/imm32/no-outputs
    33353     0/imm32/no-outputs
    33354     0x11/imm32/alloc-id:fake
    33355     _string_0f_86_jump_label/imm32/subx-name
    33356     0/imm32/no-rm32
    33357     0/imm32/no-r32
    33358     0/imm32/no-imm32
    33359     0/imm32/no-imm8
    33360     1/imm32/disp32-is-first-inout
    33361     0/imm32/no-xm32
    33362     0/imm32/no-x32
    33363     0x11/imm32/alloc-id:fake
    33364     _Primitive-break-if-addr>-named/imm32/next
    33365 _Primitive-break-if-addr>-named:  # (payload primitive)
    33366     0x11/imm32/alloc-id:fake:payload
    33367     0x11/imm32/alloc-id:fake
    33368     _string-break-if-addr>/imm32/name
    33369     0x11/imm32/alloc-id:fake
    33370     Single-lit-var/imm32/inouts
    33371     0/imm32/no-outputs
    33372     0/imm32/no-outputs
    33373     0x11/imm32/alloc-id:fake
    33374     _string_0f_87_jump_label/imm32/subx-name
    33375     0/imm32/no-rm32
    33376     0/imm32/no-r32
    33377     0/imm32/no-imm32
    33378     0/imm32/no-imm8
    33379     1/imm32/disp32-is-first-inout
    33380     0/imm32/no-xm32
    33381     0/imm32/no-x32
    33382     0x11/imm32/alloc-id:fake
    33383     _Primitive-break-if-<-named/imm32/next
    33384 _Primitive-break-if-<-named:  # (payload primitive)
    33385     0x11/imm32/alloc-id:fake:payload
    33386     0x11/imm32/alloc-id:fake
    33387     _string-break-if-</imm32/name
    33388     0x11/imm32/alloc-id:fake
    33389     Single-lit-var/imm32/inouts
    33390     0/imm32/no-outputs
    33391     0/imm32/no-outputs
    33392     0x11/imm32/alloc-id:fake
    33393     _string_0f_8c_jump_label/imm32/subx-name
    33394     0/imm32/no-rm32
    33395     0/imm32/no-r32
    33396     0/imm32/no-imm32
    33397     0/imm32/no-imm8
    33398     1/imm32/disp32-is-first-inout
    33399     0/imm32/no-xm32
    33400     0/imm32/no-x32
    33401     0x11/imm32/alloc-id:fake
    33402     _Primitive-break-if->=-named/imm32/next
    33403 _Primitive-break-if->=-named:  # (payload primitive)
    33404     0x11/imm32/alloc-id:fake:payload
    33405     0x11/imm32/alloc-id:fake
    33406     _string-break-if->=/imm32/name
    33407     0x11/imm32/alloc-id:fake
    33408     Single-lit-var/imm32/inouts
    33409     0/imm32/no-outputs
    33410     0/imm32/no-outputs
    33411     0x11/imm32/alloc-id:fake
    33412     _string_0f_8d_jump_label/imm32/subx-name
    33413     0/imm32/no-rm32
    33414     0/imm32/no-r32
    33415     0/imm32/no-imm32
    33416     0/imm32/no-imm8
    33417     1/imm32/disp32-is-first-inout
    33418     0/imm32/no-xm32
    33419     0/imm32/no-x32
    33420     0x11/imm32/alloc-id:fake
    33421     _Primitive-break-if-<=-named/imm32/next
    33422 _Primitive-break-if-<=-named:  # (payload primitive)
    33423     0x11/imm32/alloc-id:fake:payload
    33424     0x11/imm32/alloc-id:fake
    33425     _string-break-if-<=/imm32/name
    33426     0x11/imm32/alloc-id:fake
    33427     Single-lit-var/imm32/inouts
    33428     0/imm32/no-outputs
    33429     0/imm32/no-outputs
    33430     0x11/imm32/alloc-id:fake
    33431     _string_0f_8e_jump_label/imm32/subx-name
    33432     0/imm32/no-rm32
    33433     0/imm32/no-r32
    33434     0/imm32/no-imm32
    33435     0/imm32/no-imm8
    33436     1/imm32/disp32-is-first-inout
    33437     0/imm32/no-xm32
    33438     0/imm32/no-x32
    33439     0x11/imm32/alloc-id:fake
    33440     _Primitive-break-if->-named/imm32/next
    33441 _Primitive-break-if->-named:  # (payload primitive)
    33442     0x11/imm32/alloc-id:fake:payload
    33443     0x11/imm32/alloc-id:fake
    33444     _string-break-if->/imm32/name
    33445     0x11/imm32/alloc-id:fake
    33446     Single-lit-var/imm32/inouts
    33447     0/imm32/no-outputs
    33448     0/imm32/no-outputs
    33449     0x11/imm32/alloc-id:fake
    33450     _string_0f_8f_jump_label/imm32/subx-name
    33451     0/imm32/no-rm32
    33452     0/imm32/no-r32
    33453     0/imm32/no-imm32
    33454     0/imm32/no-imm8
    33455     1/imm32/disp32-is-first-inout
    33456     0/imm32/no-xm32
    33457     0/imm32/no-x32
    33458     0x11/imm32/alloc-id:fake
    33459     _Primitive-break-named/imm32/next
    33460 _Primitive-break-named:  # (payload primitive)
    33461     0x11/imm32/alloc-id:fake:payload
    33462     0x11/imm32/alloc-id:fake
    33463     _string-break/imm32/name
    33464     0x11/imm32/alloc-id:fake
    33465     Single-lit-var/imm32/inouts
    33466     0/imm32/no-outputs
    33467     0/imm32/no-outputs
    33468     0x11/imm32/alloc-id:fake
    33469     _string_e9_jump_label/imm32/subx-name
    33470     0/imm32/no-rm32
    33471     0/imm32/no-r32
    33472     0/imm32/no-imm32
    33473     0/imm32/no-imm8
    33474     1/imm32/disp32-is-first-inout
    33475     0/imm32/no-xm32
    33476     0/imm32/no-x32
    33477     0x11/imm32/alloc-id:fake
    33478     _Primitive-loop-if-addr<-named/imm32/next
    33479 _Primitive-loop-if-addr<-named:  # (payload primitive)
    33480     0x11/imm32/alloc-id:fake:payload
    33481     0x11/imm32/alloc-id:fake
    33482     _string-loop-if-addr</imm32/name
    33483     0x11/imm32/alloc-id:fake
    33484     Single-lit-var/imm32/inouts
    33485     0/imm32/no-outputs
    33486     0/imm32/no-outputs
    33487     0x11/imm32/alloc-id:fake
    33488     _string_0f_82_jump_label/imm32/subx-name
    33489     0/imm32/no-rm32
    33490     0/imm32/no-r32
    33491     0/imm32/no-imm32
    33492     0/imm32/no-imm8
    33493     1/imm32/disp32-is-first-inout
    33494     0/imm32/no-xm32
    33495     0/imm32/no-x32
    33496     0x11/imm32/alloc-id:fake
    33497     _Primitive-loop-if-addr>=-named/imm32/next
    33498 _Primitive-loop-if-addr>=-named:  # (payload primitive)
    33499     0x11/imm32/alloc-id:fake:payload
    33500     0x11/imm32/alloc-id:fake
    33501     _string-loop-if-addr>=/imm32/name
    33502     0x11/imm32/alloc-id:fake
    33503     Single-lit-var/imm32/inouts
    33504     0/imm32/no-outputs
    33505     0/imm32/no-outputs
    33506     0x11/imm32/alloc-id:fake
    33507     _string_0f_83_jump_label/imm32/subx-name
    33508     0/imm32/no-rm32
    33509     0/imm32/no-r32
    33510     0/imm32/no-imm32
    33511     0/imm32/no-imm8
    33512     1/imm32/disp32-is-first-inout
    33513     0/imm32/no-xm32
    33514     0/imm32/no-x32
    33515     0x11/imm32/alloc-id:fake
    33516     _Primitive-loop-if-=-named/imm32/next
    33517 _Primitive-loop-if-=-named:  # (payload primitive)
    33518     0x11/imm32/alloc-id:fake:payload
    33519     0x11/imm32/alloc-id:fake
    33520     _string-loop-if-=/imm32/name
    33521     0x11/imm32/alloc-id:fake
    33522     Single-lit-var/imm32/inouts
    33523     0/imm32/no-outputs
    33524     0/imm32/no-outputs
    33525     0x11/imm32/alloc-id:fake
    33526     _string_0f_84_jump_label/imm32/subx-name
    33527     0/imm32/no-rm32
    33528     0/imm32/no-r32
    33529     0/imm32/no-imm32
    33530     0/imm32/no-imm8
    33531     1/imm32/disp32-is-first-inout
    33532     0/imm32/no-xm32
    33533     0/imm32/no-x32
    33534     0x11/imm32/alloc-id:fake
    33535     _Primitive-loop-if-!=-named/imm32/next
    33536 _Primitive-loop-if-!=-named:  # (payload primitive)
    33537     0x11/imm32/alloc-id:fake:payload
    33538     0x11/imm32/alloc-id:fake
    33539     _string-loop-if-!=/imm32/name
    33540     0x11/imm32/alloc-id:fake
    33541     Single-lit-var/imm32/inouts
    33542     0/imm32/no-outputs
    33543     0/imm32/no-outputs
    33544     0x11/imm32/alloc-id:fake
    33545     _string_0f_85_jump_label/imm32/subx-name
    33546     0/imm32/no-rm32
    33547     0/imm32/no-r32
    33548     0/imm32/no-imm32
    33549     0/imm32/no-imm8
    33550     1/imm32/disp32-is-first-inout
    33551     0/imm32/no-xm32
    33552     0/imm32/no-x32
    33553     0x11/imm32/alloc-id:fake
    33554     _Primitive-loop-if-addr<=-named/imm32/next
    33555 _Primitive-loop-if-addr<=-named:  # (payload primitive)
    33556     0x11/imm32/alloc-id:fake:payload
    33557     0x11/imm32/alloc-id:fake
    33558     _string-loop-if-addr<=/imm32/name
    33559     0x11/imm32/alloc-id:fake
    33560     Single-lit-var/imm32/inouts
    33561     0/imm32/no-outputs
    33562     0/imm32/no-outputs
    33563     0x11/imm32/alloc-id:fake
    33564     _string_0f_86_jump_label/imm32/subx-name
    33565     0/imm32/no-rm32
    33566     0/imm32/no-r32
    33567     0/imm32/no-imm32
    33568     0/imm32/no-imm8
    33569     1/imm32/disp32-is-first-inout
    33570     0/imm32/no-xm32
    33571     0/imm32/no-x32
    33572     0x11/imm32/alloc-id:fake
    33573     _Primitive-loop-if-addr>-named/imm32/next
    33574 _Primitive-loop-if-addr>-named:  # (payload primitive)
    33575     0x11/imm32/alloc-id:fake:payload
    33576     0x11/imm32/alloc-id:fake
    33577     _string-loop-if-addr>/imm32/name
    33578     0x11/imm32/alloc-id:fake
    33579     Single-lit-var/imm32/inouts
    33580     0/imm32/no-outputs
    33581     0/imm32/no-outputs
    33582     0x11/imm32/alloc-id:fake
    33583     _string_0f_87_jump_label/imm32/subx-name
    33584     0/imm32/no-rm32
    33585     0/imm32/no-r32
    33586     0/imm32/no-imm32
    33587     0/imm32/no-imm8
    33588     1/imm32/disp32-is-first-inout
    33589     0/imm32/no-xm32
    33590     0/imm32/no-x32
    33591     0x11/imm32/alloc-id:fake
    33592     _Primitive-loop-if-<-named/imm32/next
    33593 _Primitive-loop-if-<-named:  # (payload primitive)
    33594     0x11/imm32/alloc-id:fake:payload
    33595     0x11/imm32/alloc-id:fake
    33596     _string-loop-if-</imm32/name
    33597     0x11/imm32/alloc-id:fake
    33598     Single-lit-var/imm32/inouts
    33599     0/imm32/no-outputs
    33600     0/imm32/no-outputs
    33601     0x11/imm32/alloc-id:fake
    33602     _string_0f_8c_jump_label/imm32/subx-name
    33603     0/imm32/no-rm32
    33604     0/imm32/no-r32
    33605     0/imm32/no-imm32
    33606     0/imm32/no-imm8
    33607     1/imm32/disp32-is-first-inout
    33608     0/imm32/no-xm32
    33609     0/imm32/no-x32
    33610     0x11/imm32/alloc-id:fake
    33611     _Primitive-loop-if->=-named/imm32/next
    33612 _Primitive-loop-if->=-named:  # (payload primitive)
    33613     0x11/imm32/alloc-id:fake:payload
    33614     0x11/imm32/alloc-id:fake
    33615     _string-loop-if->=/imm32/name
    33616     0x11/imm32/alloc-id:fake
    33617     Single-lit-var/imm32/inouts
    33618     0/imm32/no-outputs
    33619     0/imm32/no-outputs
    33620     0x11/imm32/alloc-id:fake
    33621     _string_0f_8d_jump_label/imm32/subx-name
    33622     0/imm32/no-rm32
    33623     0/imm32/no-r32
    33624     0/imm32/no-imm32
    33625     0/imm32/no-imm8
    33626     1/imm32/disp32-is-first-inout
    33627     0/imm32/no-xm32
    33628     0/imm32/no-x32
    33629     0x11/imm32/alloc-id:fake
    33630     _Primitive-loop-if-<=-named/imm32/next
    33631 _Primitive-loop-if-<=-named:  # (payload primitive)
    33632     0x11/imm32/alloc-id:fake:payload
    33633     0x11/imm32/alloc-id:fake
    33634     _string-loop-if-<=/imm32/name
    33635     0x11/imm32/alloc-id:fake
    33636     Single-lit-var/imm32/inouts
    33637     0/imm32/no-outputs
    33638     0/imm32/no-outputs
    33639     0x11/imm32/alloc-id:fake
    33640     _string_0f_8e_jump_label/imm32/subx-name
    33641     0/imm32/no-rm32
    33642     0/imm32/no-r32
    33643     0/imm32/no-imm32
    33644     0/imm32/no-imm8
    33645     1/imm32/disp32-is-first-inout
    33646     0/imm32/no-xm32
    33647     0/imm32/no-x32
    33648     0x11/imm32/alloc-id:fake
    33649     _Primitive-loop-if->-named/imm32/next
    33650 _Primitive-loop-if->-named:  # (payload primitive)
    33651     0x11/imm32/alloc-id:fake:payload
    33652     0x11/imm32/alloc-id:fake
    33653     _string-loop-if->/imm32/name
    33654     0x11/imm32/alloc-id:fake
    33655     Single-lit-var/imm32/inouts
    33656     0/imm32/no-outputs
    33657     0/imm32/no-outputs
    33658     0x11/imm32/alloc-id:fake
    33659     _string_0f_8f_jump_label/imm32/subx-name
    33660     0/imm32/no-rm32
    33661     0/imm32/no-r32
    33662     0/imm32/no-imm32
    33663     0/imm32/no-imm8
    33664     1/imm32/disp32-is-first-inout
    33665     0/imm32/no-xm32
    33666     0/imm32/no-x32
    33667     0x11/imm32/alloc-id:fake
    33668     _Primitive-loop-named/imm32/next  # we probably don't need an unconditional break
    33669 _Primitive-loop-named:  # (payload primitive)
    33670     0x11/imm32/alloc-id:fake:payload
    33671     0x11/imm32/alloc-id:fake
    33672     _string-loop/imm32/name
    33673     0x11/imm32/alloc-id:fake
    33674     Single-lit-var/imm32/inouts
    33675     0/imm32/no-outputs
    33676     0/imm32/no-outputs
    33677     0x11/imm32/alloc-id:fake
    33678     _string_e9_jump_label/imm32/subx-name
    33679     0/imm32/no-rm32
    33680     0/imm32/no-r32
    33681     0/imm32/no-imm32
    33682     0/imm32/no-imm8
    33683     1/imm32/disp32-is-first-inout
    33684     0/imm32/no-xm32
    33685     0/imm32/no-x32
    33686     0x11/imm32/alloc-id:fake
    33687     _Primitive-break-if-float</imm32/next
    33688 # - branches based on floating-point comparisons
    33689 _Primitive-break-if-float<:  # (payload primitive)
    33690     0x11/imm32/alloc-id:fake:payload
    33691     0x11/imm32/alloc-id:fake
    33692     _string-break-if-float</imm32/name
    33693     0/imm32/no-inouts
    33694     0/imm32/no-inouts
    33695     0/imm32/no-outputs
    33696     0/imm32/no-outputs
    33697     0x11/imm32/alloc-id:fake
    33698     _string_0f_82_jump_break/imm32/subx-name
    33699     0/imm32/no-rm32
    33700     0/imm32/no-r32
    33701     0/imm32/no-imm32
    33702     0/imm32/no-imm8
    33703     0/imm32/no-disp32
    33704     0/imm32/no-xm32
    33705     0/imm32/no-x32
    33706     0x11/imm32/alloc-id:fake
    33707     _Primitive-break-if-float>=/imm32/next
    33708 _Primitive-break-if-float>=:  # (payload primitive)
    33709     0x11/imm32/alloc-id:fake:payload
    33710     0x11/imm32/alloc-id:fake
    33711     _string-break-if-float>=/imm32/name
    33712     0/imm32/no-inouts
    33713     0/imm32/no-inouts
    33714     0/imm32/no-outputs
    33715     0/imm32/no-outputs
    33716     0x11/imm32/alloc-id:fake
    33717     _string_0f_83_jump_break/imm32/subx-name
    33718     0/imm32/no-rm32
    33719     0/imm32/no-r32
    33720     0/imm32/no-imm32
    33721     0/imm32/no-imm8
    33722     0/imm32/no-disp32
    33723     0/imm32/no-xm32
    33724     0/imm32/no-x32
    33725     0x11/imm32/alloc-id:fake
    33726     _Primitive-break-if-float<=/imm32/next
    33727 _Primitive-break-if-float<=:  # (payload primitive)
    33728     0x11/imm32/alloc-id:fake:payload
    33729     0x11/imm32/alloc-id:fake
    33730     _string-break-if-float<=/imm32/name
    33731     0/imm32/no-inouts
    33732     0/imm32/no-inouts
    33733     0/imm32/no-outputs
    33734     0/imm32/no-outputs
    33735     0x11/imm32/alloc-id:fake
    33736     _string_0f_86_jump_break/imm32/subx-name
    33737     0/imm32/no-rm32
    33738     0/imm32/no-r32
    33739     0/imm32/no-imm32
    33740     0/imm32/no-imm8
    33741     0/imm32/no-disp32
    33742     0/imm32/no-xm32
    33743     0/imm32/no-x32
    33744     0x11/imm32/alloc-id:fake
    33745     _Primitive-break-if-float>/imm32/next
    33746 _Primitive-break-if-float>:  # (payload primitive)
    33747     0x11/imm32/alloc-id:fake:payload
    33748     0x11/imm32/alloc-id:fake
    33749     _string-break-if-float>/imm32/name
    33750     0/imm32/no-inouts
    33751     0/imm32/no-inouts
    33752     0/imm32/no-outputs
    33753     0/imm32/no-outputs
    33754     0x11/imm32/alloc-id:fake
    33755     _string_0f_87_jump_break/imm32/subx-name
    33756     0/imm32/no-rm32
    33757     0/imm32/no-r32
    33758     0/imm32/no-imm32
    33759     0/imm32/no-imm8
    33760     0/imm32/no-disp32
    33761     0/imm32/no-xm32
    33762     0/imm32/no-x32
    33763     0x11/imm32/alloc-id:fake
    33764     _Primitive-loop-if-float</imm32/next
    33765 _Primitive-loop-if-float<:  # (payload primitive)
    33766     0x11/imm32/alloc-id:fake:payload
    33767     0x11/imm32/alloc-id:fake
    33768     _string-loop-if-float</imm32/name
    33769     0/imm32/no-inouts
    33770     0/imm32/no-inouts
    33771     0/imm32/no-outputs
    33772     0/imm32/no-outputs
    33773     0x11/imm32/alloc-id:fake
    33774     _string_0f_82_jump_loop/imm32/subx-name
    33775     0/imm32/no-rm32
    33776     0/imm32/no-r32
    33777     0/imm32/no-imm32
    33778     0/imm32/no-imm8
    33779     0/imm32/no-disp32
    33780     0/imm32/no-xm32
    33781     0/imm32/no-x32
    33782     0x11/imm32/alloc-id:fake
    33783     _Primitive-loop-if-float>=/imm32/next
    33784 _Primitive-loop-if-float>=:  # (payload primitive)
    33785     0x11/imm32/alloc-id:fake:payload
    33786     0x11/imm32/alloc-id:fake
    33787     _string-loop-if-float>=/imm32/name
    33788     0/imm32/no-inouts
    33789     0/imm32/no-inouts
    33790     0/imm32/no-outputs
    33791     0/imm32/no-outputs
    33792     0x11/imm32/alloc-id:fake
    33793     _string_0f_83_jump_loop/imm32/subx-name
    33794     0/imm32/no-rm32
    33795     0/imm32/no-r32
    33796     0/imm32/no-imm32
    33797     0/imm32/no-imm8
    33798     0/imm32/no-disp32
    33799     0/imm32/no-xm32
    33800     0/imm32/no-x32
    33801     0x11/imm32/alloc-id:fake
    33802     _Primitive-loop-if-float<=/imm32/next
    33803 _Primitive-loop-if-float<=:  # (payload primitive)
    33804     0x11/imm32/alloc-id:fake:payload
    33805     0x11/imm32/alloc-id:fake
    33806     _string-loop-if-float<=/imm32/name
    33807     0/imm32/no-inouts
    33808     0/imm32/no-inouts
    33809     0/imm32/no-outputs
    33810     0/imm32/no-outputs
    33811     0x11/imm32/alloc-id:fake
    33812     _string_0f_86_jump_loop/imm32/subx-name
    33813     0/imm32/no-rm32
    33814     0/imm32/no-r32
    33815     0/imm32/no-imm32
    33816     0/imm32/no-imm8
    33817     0/imm32/no-disp32
    33818     0/imm32/no-xm32
    33819     0/imm32/no-x32
    33820     0x11/imm32/alloc-id:fake
    33821     _Primitive-loop-if-float>/imm32/next
    33822 _Primitive-loop-if-float>:  # (payload primitive)
    33823     0x11/imm32/alloc-id:fake:payload
    33824     0x11/imm32/alloc-id:fake
    33825     _string-loop-if-float>/imm32/name
    33826     0/imm32/no-inouts
    33827     0/imm32/no-inouts
    33828     0/imm32/no-outputs
    33829     0/imm32/no-outputs
    33830     0x11/imm32/alloc-id:fake
    33831     _string_0f_87_jump_loop/imm32/subx-name
    33832     0/imm32/no-rm32
    33833     0/imm32/no-r32
    33834     0/imm32/no-imm32
    33835     0/imm32/no-imm8
    33836     0/imm32/no-disp32
    33837     0/imm32/no-xm32
    33838     0/imm32/no-x32
    33839     0x11/imm32/alloc-id:fake
    33840     _Primitive-break-if-float<-named/imm32/next
    33841 _Primitive-break-if-float<-named:  # (payload primitive)
    33842     0x11/imm32/alloc-id:fake:payload
    33843     0x11/imm32/alloc-id:fake
    33844     _string-break-if-float</imm32/name
    33845     0x11/imm32/alloc-id:fake
    33846     Single-lit-var/imm32/inouts
    33847     0/imm32/no-outputs
    33848     0/imm32/no-outputs
    33849     0x11/imm32/alloc-id:fake
    33850     _string_0f_82_jump_label/imm32/subx-name
    33851     0/imm32/no-rm32
    33852     0/imm32/no-r32
    33853     0/imm32/no-imm32
    33854     0/imm32/no-imm8
    33855     1/imm32/disp32-is-first-inout
    33856     0/imm32/no-xm32
    33857     0/imm32/no-x32
    33858     0x11/imm32/alloc-id:fake
    33859     _Primitive-break-if-float>=-named/imm32/next
    33860 _Primitive-break-if-float>=-named:  # (payload primitive)
    33861     0x11/imm32/alloc-id:fake:payload
    33862     0x11/imm32/alloc-id:fake
    33863     _string-break-if-float>=/imm32/name
    33864     0x11/imm32/alloc-id:fake
    33865     Single-lit-var/imm32/inouts
    33866     0/imm32/no-outputs
    33867     0/imm32/no-outputs
    33868     0x11/imm32/alloc-id:fake
    33869     _string_0f_83_jump_label/imm32/subx-name
    33870     0/imm32/no-rm32
    33871     0/imm32/no-r32
    33872     0/imm32/no-imm32
    33873     0/imm32/no-imm8
    33874     1/imm32/disp32-is-first-inout
    33875     0/imm32/no-xm32
    33876     0/imm32/no-x32
    33877     0x11/imm32/alloc-id:fake
    33878     _Primitive-break-if-float<=-named/imm32/next
    33879 _Primitive-break-if-float<=-named:  # (payload primitive)
    33880     0x11/imm32/alloc-id:fake:payload
    33881     0x11/imm32/alloc-id:fake
    33882     _string-break-if-float<=/imm32/name
    33883     0x11/imm32/alloc-id:fake
    33884     Single-lit-var/imm32/inouts
    33885     0/imm32/no-outputs
    33886     0/imm32/no-outputs
    33887     0x11/imm32/alloc-id:fake
    33888     _string_0f_86_jump_label/imm32/subx-name
    33889     0/imm32/no-rm32
    33890     0/imm32/no-r32
    33891     0/imm32/no-imm32
    33892     0/imm32/no-imm8
    33893     1/imm32/disp32-is-first-inout
    33894     0/imm32/no-xm32
    33895     0/imm32/no-x32
    33896     0x11/imm32/alloc-id:fake
    33897     _Primitive-break-if-float>-named/imm32/next
    33898 _Primitive-break-if-float>-named:  # (payload primitive)
    33899     0x11/imm32/alloc-id:fake:payload
    33900     0x11/imm32/alloc-id:fake
    33901     _string-break-if-float>/imm32/name
    33902     0x11/imm32/alloc-id:fake
    33903     Single-lit-var/imm32/inouts
    33904     0/imm32/no-outputs
    33905     0/imm32/no-outputs
    33906     0x11/imm32/alloc-id:fake
    33907     _string_0f_87_jump_label/imm32/subx-name
    33908     0/imm32/no-rm32
    33909     0/imm32/no-r32
    33910     0/imm32/no-imm32
    33911     0/imm32/no-imm8
    33912     1/imm32/disp32-is-first-inout
    33913     0/imm32/no-xm32
    33914     0/imm32/no-x32
    33915     0x11/imm32/alloc-id:fake
    33916     _Primitive-loop-if-float<-named/imm32/next
    33917 _Primitive-loop-if-float<-named:  # (payload primitive)
    33918     0x11/imm32/alloc-id:fake:payload
    33919     0x11/imm32/alloc-id:fake
    33920     _string-loop-if-float</imm32/name
    33921     0x11/imm32/alloc-id:fake
    33922     Single-lit-var/imm32/inouts
    33923     0/imm32/no-outputs
    33924     0/imm32/no-outputs
    33925     0x11/imm32/alloc-id:fake
    33926     _string_0f_82_jump_label/imm32/subx-name
    33927     0/imm32/no-rm32
    33928     0/imm32/no-r32
    33929     0/imm32/no-imm32
    33930     0/imm32/no-imm8
    33931     1/imm32/disp32-is-first-inout
    33932     0/imm32/no-xm32
    33933     0/imm32/no-x32
    33934     0x11/imm32/alloc-id:fake
    33935     _Primitive-loop-if-float>=-named/imm32/next
    33936 _Primitive-loop-if-float>=-named:  # (payload primitive)
    33937     0x11/imm32/alloc-id:fake:payload
    33938     0x11/imm32/alloc-id:fake
    33939     _string-loop-if-float>=/imm32/name
    33940     0x11/imm32/alloc-id:fake
    33941     Single-lit-var/imm32/inouts
    33942     0/imm32/no-outputs
    33943     0/imm32/no-outputs
    33944     0x11/imm32/alloc-id:fake
    33945     _string_0f_83_jump_label/imm32/subx-name
    33946     0/imm32/no-rm32
    33947     0/imm32/no-r32
    33948     0/imm32/no-imm32
    33949     0/imm32/no-imm8
    33950     1/imm32/disp32-is-first-inout
    33951     0/imm32/no-xm32
    33952     0/imm32/no-x32
    33953     0x11/imm32/alloc-id:fake
    33954     _Primitive-loop-if-float<=-named/imm32/next
    33955 _Primitive-loop-if-float<=-named:  # (payload primitive)
    33956     0x11/imm32/alloc-id:fake:payload
    33957     0x11/imm32/alloc-id:fake
    33958     _string-loop-if-float<=/imm32/name
    33959     0x11/imm32/alloc-id:fake
    33960     Single-lit-var/imm32/inouts
    33961     0/imm32/no-outputs
    33962     0/imm32/no-outputs
    33963     0x11/imm32/alloc-id:fake
    33964     _string_0f_86_jump_label/imm32/subx-name
    33965     0/imm32/no-rm32
    33966     0/imm32/no-r32
    33967     0/imm32/no-imm32
    33968     0/imm32/no-imm8
    33969     1/imm32/disp32-is-first-inout
    33970     0/imm32/no-xm32
    33971     0/imm32/no-x32
    33972     0x11/imm32/alloc-id:fake
    33973     _Primitive-loop-if-float>-named/imm32/next
    33974 _Primitive-loop-if-float>-named:  # (payload primitive)
    33975     0x11/imm32/alloc-id:fake:payload
    33976     0x11/imm32/alloc-id:fake
    33977     _string-loop-if-float>/imm32/name
    33978     0x11/imm32/alloc-id:fake
    33979     Single-lit-var/imm32/inouts
    33980     0/imm32/no-outputs
    33981     0/imm32/no-outputs
    33982     0x11/imm32/alloc-id:fake
    33983     _string_0f_87_jump_label/imm32/subx-name
    33984     0/imm32/no-rm32
    33985     0/imm32/no-r32
    33986     0/imm32/no-imm32
    33987     0/imm32/no-imm8
    33988     1/imm32/disp32-is-first-inout
    33989     0/imm32/no-xm32
    33990     0/imm32/no-x32
    33991     0/imm32/next
    33992     0/imm32/next
    33993
    33994 # string literals for Mu instructions
    33995 _string-add:  # (payload array byte)
    33996     0x11/imm32/alloc-id:fake:payload
    33997     # "add"
    33998     0x3/imm32/size
    33999     0x61/a 0x64/d 0x64/d
    34000 _string-address:  # (payload array byte)
    34001     0x11/imm32/alloc-id:fake:payload
    34002     # "address"
    34003     0x7/imm32/size
    34004     0x61/a 0x64/d 0x64/d 0x72/r 0x65/e 0x73/s 0x73/s
    34005 _string-add-to:  # (payload array byte)
    34006     0x11/imm32/alloc-id:fake:payload
    34007     # "add-to"
    34008     0x6/imm32/size
    34009     0x61/a 0x64/d 0x64/d 0x2d/dash 0x74/t 0x6f/o
    34010 _string-and:  # (payload array byte)
    34011     0x11/imm32/alloc-id:fake:payload
    34012     # "and"
    34013     0x3/imm32/size
    34014     0x61/a 0x6e/n 0x64/d
    34015 _string-and-with:  # (payload array byte)
    34016     0x11/imm32/alloc-id:fake:payload
    34017     # "and-with"
    34018     0x8/imm32/size
    34019     0x61/a 0x6e/n 0x64/d 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h
    34020 _string-break:  # (payload array byte)
    34021     0x11/imm32/alloc-id:fake:payload
    34022     # "break"
    34023     0x5/imm32/size
    34024     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k
    34025 _string-break-if-<:  # (payload array byte)
    34026     0x11/imm32/alloc-id:fake:payload
    34027     # "break-if-<"
    34028     0xa/imm32/size
    34029     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3c/<
    34030 _string-break-if-<=:  # (payload array byte)
    34031     0x11/imm32/alloc-id:fake:payload
    34032     # "break-if-<="
    34033     0xb/imm32/size
    34034     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3c/< 0x3d/=
    34035 _string-break-if-=:  # (payload array byte)
    34036     0x11/imm32/alloc-id:fake:payload
    34037     # "break-if-="
    34038     0xa/imm32/size
    34039     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3d/=
    34040 _string-break-if->:  # (payload array byte)
    34041     0x11/imm32/alloc-id:fake:payload
    34042     # "break-if->"
    34043     0xa/imm32/size
    34044     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3e/>
    34045 _string-break-if->=:  # (payload array byte)
    34046     0x11/imm32/alloc-id:fake:payload
    34047     # "break-if->="
    34048     0xb/imm32/size
    34049     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3e/> 0x3d/=
    34050 _string-break-if-!=:  # (payload array byte)
    34051     0x11/imm32/alloc-id:fake:payload
    34052     # "break-if-!="
    34053     0xb/imm32/size
    34054     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x21/! 0x3d/=
    34055 _string-break-if-addr<:  # (payload array byte)
    34056     0x11/imm32/alloc-id:fake:payload
    34057     # "break-if-addr<"
    34058     0xe/imm32/size
    34059     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/<
    34060 _string-break-if-addr<=:  # (payload array byte)
    34061     0x11/imm32/alloc-id:fake:payload
    34062     # "break-if-addr<="
    34063     0xf/imm32/size
    34064     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/=
    34065 _string-break-if-addr>:  # (payload array byte)
    34066     0x11/imm32/alloc-id:fake:payload
    34067     # "break-if-addr>"
    34068     0xe/imm32/size
    34069     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/>
    34070 _string-break-if-addr>=:  # (payload array byte)
    34071     0x11/imm32/alloc-id:fake:payload
    34072     # "break-if-addr>="
    34073     0xf/imm32/size
    34074     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/=
    34075 _string-break-if-float<:  # (payload array byte)
    34076     0x11/imm32/alloc-id:fake:payload
    34077     # "break-if-float<"
    34078     0xf/imm32/size
    34079     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/<
    34080 _string-break-if-float<=:  # (payload array byte)
    34081     0x11/imm32/alloc-id:fake:payload
    34082     # "break-if-float<="
    34083     0x10/imm32/size
    34084     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/=
    34085 _string-break-if-float>:  # (payload array byte)
    34086     0x11/imm32/alloc-id:fake:payload
    34087     # "break-if-float>"
    34088     0xf/imm32/size
    34089     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/>
    34090 _string-break-if-float>=:  # (payload array byte)
    34091     0x11/imm32/alloc-id:fake:payload
    34092     # "break-if-float>="
    34093     0x10/imm32/size
    34094     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/=
    34095 _string-break-if-carry:  # (payload array byte)
    34096     0x11/imm32/alloc-id:fake:payload
    34097     # "break-if-carry"
    34098     0xe/imm32/size
    34099     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x63/c 0x61/a 0x72/r 0x72/r 0x79/y
    34100 _string-break-if-not-carry:  # (payload array byte)
    34101     0x11/imm32/alloc-id:fake:payload
    34102     # "break-if-not-carry"
    34103     0x12/imm32/size
    34104     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x6e/n 0x6f/o 0x74/t 0x2d/dash 0x63/c 0x61/a 0x72/r 0x72/r 0x79/y
    34105 _string-break-if-overflow:  # (payload array byte)
    34106     0x11/imm32/alloc-id:fake:payload
    34107     # "break-if-overflow"
    34108     0x11/imm32/size
    34109     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x6f/o 0x76/v 0x65/e 0x72/r 0x66/f 0x6c/l 0x6f/o 0x77/w
    34110 _string-break-if-not-overflow:  # (payload array byte)
    34111     0x11/imm32/alloc-id:fake:payload
    34112     # "break-if-not-overflow"
    34113     0x15/imm32/size
    34114     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x6e/n 0x6f/o 0x74/t 0x2d/dash 0x6f/o 0x76/v 0x65/e 0x72/r 0x66/f 0x6c/l 0x6f/o 0x77/w
    34115 _string-compare:  # (payload array byte)
    34116     0x11/imm32/alloc-id:fake:payload
    34117     # "compare"
    34118     0x7/imm32/size
    34119     0x63/c 0x6f/o 0x6d/m 0x70/p 0x61/a 0x72/r 0x65/e
    34120 _string-copy:  # (payload array byte)
    34121     0x11/imm32/alloc-id:fake:payload
    34122     # "copy"
    34123     0x4/imm32/size
    34124     0x63/c 0x6f/o 0x70/p 0x79/y
    34125 _string-copy-to:  # (payload array byte)
    34126     0x11/imm32/alloc-id:fake:payload
    34127     # "copy-to"
    34128     0x7/imm32/size
    34129     0x63/c 0x6f/o 0x70/p 0x79/y 0x2d/dash 0x74/t 0x6f/o
    34130 _string-copy-byte:
    34131     0x11/imm32/alloc-id:fake:payload
    34132     # "copy-byte"
    34133     0x9/imm32/size
    34134     0x63/c 0x6f/o 0x70/p 0x79/y 0x2d/dash 0x62/b 0x79/y 0x74/t 0x65/e
    34135 _string-copy-byte-to:
    34136     0x11/imm32/alloc-id:fake:payload
    34137     # "copy-byte-to"
    34138     0xc/imm32/size
    34139     0x63/c 0x6f/o 0x70/p 0x79/y 0x2d/dash 0x62/b 0x79/y 0x74/t 0x65/e 0x2d/dash 0x74/t 0x6f/o
    34140 _string-decrement:  # (payload array byte)
    34141     0x11/imm32/alloc-id:fake:payload
    34142     # "decrement"
    34143     0x9/imm32/size
    34144     0x64/d 0x65/e 0x63/c 0x72/r 0x65/e 0x6d/m 0x65/e 0x6e/n 0x74/t
    34145 _string-increment:  # (payload array byte)
    34146     0x11/imm32/alloc-id:fake:payload
    34147     # "increment"
    34148     0x9/imm32/size
    34149     0x69/i 0x6e/n 0x63/c 0x72/r 0x65/e 0x6d/m 0x65/e 0x6e/n 0x74/t
    34150 _string-loop:  # (payload array byte)
    34151     0x11/imm32/alloc-id:fake:payload
    34152     # "loop"
    34153     0x4/imm32/size
    34154     0x6c/l 0x6f/o 0x6f/o 0x70/p
    34155 _string-loop-if-<:  # (payload array byte)
    34156     0x11/imm32/alloc-id:fake:payload
    34157     # "loop-if-<"
    34158     0x9/imm32/size
    34159     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3c/<
    34160 _string-loop-if-<=:  # (payload array byte)
    34161     0x11/imm32/alloc-id:fake:payload
    34162     # "loop-if-<="
    34163     0xa/imm32/size
    34164     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3c/< 0x3d/=
    34165 _string-loop-if-=:  # (payload array byte)
    34166     0x11/imm32/alloc-id:fake:payload
    34167     # "loop-if-="
    34168     0x9/imm32/size
    34169     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3d/=
    34170 _string-loop-if->:  # (payload array byte)
    34171     0x11/imm32/alloc-id:fake:payload
    34172     # "loop-if->"
    34173     0x9/imm32/size
    34174     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3e/>
    34175 _string-loop-if->=:  # (payload array byte)
    34176     0x11/imm32/alloc-id:fake:payload
    34177     # "loop-if->="
    34178     0xa/imm32/size
    34179     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3e/> 0x3d/=
    34180 _string-loop-if-!=:  # (payload array byte)
    34181     0x11/imm32/alloc-id:fake:payload
    34182     # "loop-if-!="
    34183     0xa/imm32/size
    34184     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x21/! 0x3d/=
    34185 _string-loop-if-addr<:  # (payload array byte)
    34186     0x11/imm32/alloc-id:fake:payload
    34187     # "loop-if-addr<"
    34188     0xd/imm32/size
    34189     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/<
    34190 _string-loop-if-addr<=:  # (payload array byte)
    34191     0x11/imm32/alloc-id:fake:payload
    34192     # "loop-if-addr<="
    34193     0xe/imm32/size
    34194     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/=
    34195 _string-loop-if-addr>:  # (payload array byte)
    34196     0x11/imm32/alloc-id:fake:payload
    34197     # "loop-if-addr>"
    34198     0xd/imm32/size
    34199     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/>
    34200 _string-loop-if-addr>=:  # (payload array byte)
    34201     0x11/imm32/alloc-id:fake:payload
    34202     # "loop-if-addr>="
    34203     0xe/imm32/size
    34204     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/=
    34205 _string-loop-if-float<:  # (payload array byte)
    34206     0x11/imm32/alloc-id:fake:payload
    34207     # "loop-if-float<"
    34208     0xe/imm32/size
    34209     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/<
    34210 _string-loop-if-float<=:  # (payload array byte)
    34211     0x11/imm32/alloc-id:fake:payload
    34212     # "loop-if-float<="
    34213     0xf/imm32/size
    34214     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/=
    34215 _string-loop-if-float>:  # (payload array byte)
    34216     0x11/imm32/alloc-id:fake:payload
    34217     # "loop-if-float>"
    34218     0xe/imm32/size
    34219     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/>
    34220 _string-loop-if-float>=:  # (payload array byte)
    34221     0x11/imm32/alloc-id:fake:payload
    34222     # "loop-if-float>="
    34223     0xf/imm32/size
    34224     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/=
    34225 _string-loop-if-carry:  # (payload array byte)
    34226     0x11/imm32/alloc-id:fake:payload
    34227     # "loop-if-carry"
    34228     0xd/imm32/size
    34229     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x63/c 0x61/a 0x72/r 0x72/r 0x79/y
    34230 _string-loop-if-not-carry:  # (payload array byte)
    34231     0x11/imm32/alloc-id:fake:payload
    34232     # "loop-if-not-carry"
    34233     0x11/imm32/size
    34234     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x6e/n 0x6f/o 0x74/t 0x2d/dash 0x63/c 0x61/a 0x72/r 0x72/r 0x79/y
    34235 _string-loop-if-overflow:  # (payload array byte)
    34236     0x11/imm32/alloc-id:fake:payload
    34237     # "loop-if-overflow"
    34238     0x10/imm32/size
    34239     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x6f/o 0x76/v 0x65/e 0x72/r 0x66/f 0x6c/l 0x6f/o 0x77/w
    34240 _string-loop-if-not-overflow:  # (payload array byte)
    34241     0x11/imm32/alloc-id:fake:payload
    34242     # "loop-if-not-overflow"
    34243     0x14/imm32/size
    34244     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x6e/n 0x6f/o 0x74/t 0x2d/dash 0x6f/o 0x76/v 0x65/e 0x72/r 0x66/f 0x6c/l 0x6f/o 0x77/w
    34245 _string-multiply:  # (payload array byte)
    34246     0x11/imm32/alloc-id:fake:payload
    34247     # "multiply"
    34248     0x8/imm32/size
    34249     0x6d/m 0x75/u 0x6c/l 0x74/t 0x69/i 0x70/p 0x6c/l 0x79/y
    34250 _string-convert:  # (payload array byte)
    34251     0x11/imm32/alloc-id:fake:payload
    34252     # "convert"
    34253     0x7/imm32/size
    34254     0x63/c 0x6f/o 0x6e/n 0x76/v 0x65/e 0x72/r 0x74/t
    34255 _string-truncate:  # (payload array byte)
    34256     0x11/imm32/alloc-id:fake:payload
    34257     # "truncate"
    34258     0x8/imm32/size
    34259     0x74/t 0x72/r 0x75/u 0x6e/n 0x63/c 0x61/a 0x74/t 0x65/e
    34260 _string-reinterpret:  # (payload array byte)
    34261     0x11/imm32/alloc-id:fake:payload
    34262     # "reinterpret"
    34263     0xb/imm32/size
    34264     0x72/r 0x65/e 0x69/i 0x6e/n 0x74/t 0x65/e 0x72/r 0x70/p 0x72/r 0x65/e 0x74/t
    34265 _string-divide:
    34266     0x11/imm32/alloc-id:fake:payload
    34267     # "divide"
    34268     0x6/imm32/size
    34269     0x64/d 0x69/i 0x76/v 0x69/i 0x64/d 0x65/e
    34270 _string-max:
    34271     0x11/imm32/alloc-id:fake:payload
    34272     # "max"
    34273     0x3/imm32/size
    34274     0x6d/m 0x61/a 0x78/x
    34275 _string-min:
    34276     0x11/imm32/alloc-id:fake:payload
    34277     # "min"
    34278     0x3/imm32/size
    34279     0x6d/m 0x69/i 0x6e/n
    34280 _string-reciprocal:
    34281     0x11/imm32/alloc-id:fake:payload
    34282     # "reciprocal"
    34283     0xa/imm32/size
    34284     0x72/r 0x65/e 0x63/c 0x69/i 0x70/p 0x72/r 0x6f/o 0x63/c 0x61/a 0x6c/l
    34285 _string-square-root:
    34286     0x11/imm32/alloc-id:fake:payload
    34287     # "square-root"
    34288     0xb/imm32/size
    34289     0x73/s 0x71/q 0x75/u 0x61/a 0x72/r 0x65/e 0x2d/dash 0x72/r 0x6f/o 0x6f/o 0x74/t
    34290 _string-inverse-square-root:
    34291     0x11/imm32/alloc-id:fake:payload
    34292     # "inverse-square-root"
    34293     0x13/imm32/size
    34294     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
    34295 _string-negate:  # (payload array byte)
    34296     0x11/imm32/alloc-id:fake:payload
    34297     # "negate"
    34298     0x6/imm32/size
    34299     0x6e/n 0x65/e 0x67/g 0x61/a 0x74/t 0x65/e
    34300 _string-not:  # (payload array byte)
    34301     0x11/imm32/alloc-id:fake:payload
    34302     # "not"
    34303     0x3/imm32/size
    34304     0x6e/n 0x6f/o 0x74/t
    34305 _string-or:  # (payload array byte)
    34306     0x11/imm32/alloc-id:fake:payload
    34307     # "or"
    34308     0x2/imm32/size
    34309     0x6f/o 0x72/r
    34310 _string-or-with:  # (payload array byte)
    34311     0x11/imm32/alloc-id:fake:payload
    34312     # "or-with"
    34313     0x7/imm32/size
    34314     0x6f/o 0x72/r 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h
    34315 _string-subtract:  # (payload array byte)
    34316     0x11/imm32/alloc-id:fake:payload
    34317     # "subtract"
    34318     0x8/imm32/size
    34319     0x73/s 0x75/u 0x62/b 0x74/t 0x72/r 0x61/a 0x63/c 0x74/t
    34320 _string-subtract-from:  # (payload array byte)
    34321     0x11/imm32/alloc-id:fake:payload
    34322     # "subtract-from"
    34323     0xd/imm32/size
    34324     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
    34325 _string-xor:  # (payload array byte)
    34326     0x11/imm32/alloc-id:fake:payload
    34327     # "xor"
    34328     0x3/imm32/size
    34329     0x78/x 0x6f/o 0x72/r
    34330 _string-xor-with:  # (payload array byte)
    34331     0x11/imm32/alloc-id:fake:payload
    34332     # "xor-with"
    34333     0x8/imm32/size
    34334     0x78/x 0x6f/o 0x72/r 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h
    34335 _string-shift-left:  # (payload array byte)
    34336     0x11/imm32/alloc-id:fake:payload
    34337     # "shift-left"
    34338     0xa/imm32/size
    34339     0x73/s 0x68/h 0x69/i 0x66/f 0x74/t 0x2d/dash 0x6c/l 0x65/e 0x66/f 0x74/t
    34340 _string-shift-right:  # (payload array byte)
    34341     0x11/imm32/alloc-id:fake:payload
    34342     # "shift-right"
    34343     0xb/imm32/size
    34344     0x73/s 0x68/h 0x69/i 0x66/f 0x74/t 0x2d/dash 0x72/r 0x69/i 0x67/g 0x68/h 0x74/t
    34345 _string-shift-right-signed:  # (payload array byte)
    34346     0x11/imm32/alloc-id:fake:payload
    34347     # "shift-right-signed"
    34348     0x12/imm32/size
    34349     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
    34350
    34351 # string literals for SubX instructions
    34352 _string_01_add_to:  # (payload array byte)
    34353     0x11/imm32/alloc-id:fake:payload
    34354     # "01/add-to"
    34355     0x9/imm32/size
    34356     0x30/0 0x31/1 0x2f/slash 0x61/a 0x64/d 0x64/d 0x2d/dash 0x74/t 0x6f/o
    34357 _string_03_add:  # (payload array byte)
    34358     0x11/imm32/alloc-id:fake:payload
    34359     # "03/add"
    34360     0x6/imm32/size
    34361     0x30/0 0x33/3 0x2f/slash 0x61/a 0x64/d 0x64/d
    34362 _string_05_add_to_eax:  # (payload array byte)
    34363     0x11/imm32/alloc-id:fake:payload
    34364     # "05/add-to-eax"
    34365     0xd/imm32/size
    34366     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
    34367 _string_09_or_with:  # (payload array byte)
    34368     0x11/imm32/alloc-id:fake:payload
    34369     # "09/or-with"
    34370     0xa/imm32/size
    34371     0x30/0 0x39/9 0x2f/slash 0x6f/o 0x72/r 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h
    34372 _string_0b_or:  # (payload array byte)
    34373     0x11/imm32/alloc-id:fake:payload
    34374     # "0b/or"
    34375     0x5/imm32/size
    34376     0x30/0 0x62/b 0x2f/slash 0x6f/o 0x72/r
    34377 _string_0d_or_with_eax:  # (payload array byte)
    34378     0x11/imm32/alloc-id:fake:payload
    34379     # "0d/or-with-eax"
    34380     0xe/imm32/size
    34381     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
    34382 _string_0f_80_jump_label:  # (payload array byte)
    34383     0x11/imm32/alloc-id:fake:payload
    34384     # "0f 80/jump-if-overflow"
    34385     0x16/imm32/size
    34386     0x30/0 0x66/f 0x20/space 0x38/8 0x30/0 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x6f/o 0x76/v 0x65/e 0x72/r 0x66/f 0x6c/l 0x6f/o 0x77/w
    34387 _string_0f_80_jump_break:  # (payload array byte)
    34388     0x11/imm32/alloc-id:fake:payload
    34389     # "0f 80/jump-if-overflow break/disp32"
    34390     0x23/imm32/size
    34391     0x30/0 0x66/f 0x20/space 0x38/8 0x30/0 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x6f/o 0x76/v 0x65/e 0x72/r 0x66/f 0x6c/l 0x6f/o 0x77/w 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
    34392 _string_0f_80_jump_loop:  # (payload array byte)
    34393     0x11/imm32/alloc-id:fake:payload
    34394     # "0f 80/jump-if-overflow loop/disp32"
    34395     0x22/imm32/size
    34396     0x30/0 0x66/f 0x20/space 0x38/8 0x30/0 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x6f/o 0x76/v 0x65/e 0x72/r 0x66/f 0x6c/l 0x6f/o 0x77/w 0x20/space 0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2
    34397 _string_0f_81_jump_label:  # (payload array byte)
    34398     0x11/imm32/alloc-id:fake:payload
    34399     # "0f 81/jump-if-not-overflow"
    34400     0x1a/imm32/size
    34401     0x30/0 0x66/f 0x20/space 0x38/8 0x31/1 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x6e/n 0x6f/o 0x74/t 0x2d/dash 0x6f/o 0x76/v 0x65/e 0x72/r 0x66/f 0x6c/l 0x6f/o 0x77/w
    34402 _string_0f_81_jump_break:  # (payload array byte)
    34403     0x11/imm32/alloc-id:fake:payload
    34404     # "0f 81/jump-if-not-overflow break/disp32"
    34405     0x27/imm32/size
    34406     0x30/0 0x66/f 0x20/space 0x38/8 0x31/1 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x6e/n 0x6f/o 0x74/t 0x2d/dash 0x6f/o 0x76/v 0x65/e 0x72/r 0x66/f 0x6c/l 0x6f/o 0x77/w 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
    34407 _string_0f_81_jump_loop:  # (payload array byte)
    34408     0x11/imm32/alloc-id:fake:payload
    34409     # "0f 81/jump-if-not-overflow loop/disp32"
    34410     0x26/imm32/size
    34411     0x30/0 0x66/f 0x20/space 0x38/8 0x31/1 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x6e/n 0x6f/o 0x74/t 0x2d/dash 0x6f/o 0x76/v 0x65/e 0x72/r 0x66/f 0x6c/l 0x6f/o 0x77/w 0x20/space 0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2f/slash 0x64/d 0x69/i 0x73/s 0x70/p 0x33/3 0x32/2
    34412 _string_0f_82_jump_label:  # (payload array byte)
    34413     0x11/imm32/alloc-id:fake:payload
    34414     # "0f 82/jump-if-addr<"
    34415     0x13/imm32/size
    34416     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/<
    34417 _string_0f_82_jump_break:  # (payload array byte)
    34418     0x11/imm32/alloc-id:fake:payload
    34419     # "0f 82/jump-if-addr< break/disp32"
    34420     0x20/imm32/size
    34421     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
    34422 _string_0f_82_jump_loop:  # (payload array byte)
    34423     0x11/imm32/alloc-id:fake:payload
    34424     # "0f 82/jump-if-addr< loop/disp32"
    34425     0x1f/imm32/size
    34426     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
    34427 _string_0f_83_jump_label:  # (payload array byte)
    34428     0x11/imm32/alloc-id:fake:payload
    34429     # "0f 83/jump-if-addr>="
    34430     0x14/imm32/size
    34431     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/=
    34432 _string_0f_83_jump_break:  # (payload array byte)
    34433     0x11/imm32/alloc-id:fake:payload
    34434     # "0f 83/jump-if-addr>= break/disp32"
    34435     0x21/imm32/size
    34436     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
    34437 _string_0f_83_jump_loop:  # (payload array byte)
    34438     0x11/imm32/alloc-id:fake:payload
    34439     # "0f 83/jump-if-addr>= loop/disp32"
    34440     0x20/imm32/size
    34441     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
    34442 _string_0f_84_jump_label:  # (payload array byte)
    34443     0x11/imm32/alloc-id:fake:payload
    34444     # "0f 84/jump-if-="
    34445     0xf/imm32/size
    34446     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/=
    34447 _string_0f_84_jump_break:  # (payload array byte)
    34448     0x11/imm32/alloc-id:fake:payload
    34449     # "0f 84/jump-if-= break/disp32"
    34450     0x1c/imm32/size
    34451     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
    34452 _string_0f_84_jump_loop:  # (payload array byte)
    34453     0x11/imm32/alloc-id:fake:payload
    34454     # "0f 84/jump-if-= loop/disp32"
    34455     0x1a/imm32/size
    34456     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
    34457 _string_0f_85_jump_label:  # (payload array byte)
    34458     0x11/imm32/alloc-id:fake:payload
    34459     # "0f 85/jump-if-!="
    34460     0x10/imm32/size
    34461     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/=
    34462 _string_0f_85_jump_break:  # (payload array byte)
    34463     0x11/imm32/alloc-id:fake:payload
    34464     # "0f 85/jump-if-!= break/disp32"
    34465     0x1d/imm32/size
    34466     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
    34467 _string_0f_85_jump_loop:  # (payload array byte)
    34468     0x11/imm32/alloc-id:fake:payload
    34469     # "0f 85/jump-if-!= loop/disp32"
    34470     0x1c/imm32/size
    34471     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
    34472 _string_0f_86_jump_label:  # (payload array byte)
    34473     0x11/imm32/alloc-id:fake:payload
    34474     # "0f 86/jump-if-addr<="
    34475     0x14/imm32/size
    34476     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/=
    34477 _string_0f_86_jump_break:  # (payload array byte)
    34478     0x11/imm32/alloc-id:fake:payload
    34479     # "0f 86/jump-if-addr<= break/disp32"
    34480     0x21/imm32/size
    34481     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
    34482 _string_0f_86_jump_loop:  # (payload array byte)
    34483     0x11/imm32/alloc-id:fake:payload
    34484     # "0f 86/jump-if-addr<= loop/disp32"
    34485     0x20/imm32/size
    34486     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
    34487 _string_0f_87_jump_label:  # (payload array byte)
    34488     0x11/imm32/alloc-id:fake:payload
    34489     # "0f 87/jump-if-addr>"
    34490     0x13/imm32/size
    34491     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/>
    34492 _string_0f_87_jump_break:  # (payload array byte)
    34493     0x11/imm32/alloc-id:fake:payload
    34494     # "0f 87/jump-if-addr> break/disp32"
    34495     0x20/imm32/size
    34496     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
    34497 _string_0f_87_jump_loop:  # (payload array byte)
    34498     0x11/imm32/alloc-id:fake:payload
    34499     # "0f 87/jump-if-addr> loop/disp32"
    34500     0x1f/imm32/size
    34501     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
    34502 _string_0f_8c_jump_label:  # (payload array byte)
    34503     0x11/imm32/alloc-id:fake:payload
    34504     # "0f 8c/jump-if-<"
    34505     0xf/imm32/size
    34506     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/<
    34507 _string_0f_8c_jump_break:  # (payload array byte)
    34508     0x11/imm32/alloc-id:fake:payload
    34509     # "0f 8c/jump-if-< break/disp32"
    34510     0x1c/imm32/size
    34511     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
    34512 _string_0f_8c_jump_loop:  # (payload array byte)
    34513     0x11/imm32/alloc-id:fake:payload
    34514     # "0f 8c/jump-if-< loop/disp32"
    34515     0x1b/imm32/size
    34516     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
    34517 _string_0f_8d_jump_label:  # (payload array byte)
    34518     0x11/imm32/alloc-id:fake:payload
    34519     # "0f 8d/jump-if->="
    34520     0x10/imm32/size
    34521     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/=
    34522 _string_0f_8d_jump_break:  # (payload array byte)
    34523     0x11/imm32/alloc-id:fake:payload
    34524     # "0f 8d/jump-if->= break/disp32"
    34525     0x1d/imm32/size
    34526     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
    34527 _string_0f_8d_jump_loop:  # (payload array byte)
    34528     0x11/imm32/alloc-id:fake:payload
    34529     # "0f 8d/jump-if->= loop/disp32"
    34530     0x1c/imm32/size
    34531     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
    34532 _string_0f_8e_jump_label:  # (payload array byte)
    34533     0x11/imm32/alloc-id:fake:payload
    34534     # "0f 8e/jump-if-<="
    34535     0x10/imm32/size
    34536     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/=
    34537 _string_0f_8e_jump_break:  # (payload array byte)
    34538     0x11/imm32/alloc-id:fake:payload
    34539     # "0f 8e/jump-if-<= break/disp32"
    34540     0x1d/imm32/size
    34541     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
    34542 _string_0f_8e_jump_loop:  # (payload array byte)
    34543     0x11/imm32/alloc-id:fake:payload
    34544     # "0f 8e/jump-if-<= loop/disp32"
    34545     0x1c/imm32/size
    34546     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
    34547 _string_0f_8f_jump_label:  # (payload array byte)
    34548     0x11/imm32/alloc-id:fake:payload
    34549     # "0f 8f/jump-if->"
    34550     0xf/imm32/size
    34551     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/>
    34552 _string_0f_8f_jump_break:  # (payload array byte)
    34553     0x11/imm32/alloc-id:fake:payload
    34554     # "0f 8f/jump-if-> break/disp32"
    34555     0x1c/imm32/size
    34556     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
    34557 _string_0f_8f_jump_loop:  # (payload array byte)
    34558     0x11/imm32/alloc-id:fake:payload
    34559     # "0f 8f/jump-if-> loop/disp32"
    34560     0x1b/imm32/size
    34561     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
    34562 _string_0f_af_multiply:  # (payload array byte)
    34563     0x11/imm32/alloc-id:fake:payload
    34564     # "0f af/multiply"
    34565     0xe/imm32/size
    34566     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
    34567 _string_f3_0f_2a_convert_to_float:
    34568     0x11/imm32/alloc-id:fake:payload
    34569     # "f3 0f 2a/convert-to-float"
    34570     0x19/imm32/size
    34571     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
    34572 _string_f3_0f_2d_convert_to_int:
    34573     0x11/imm32/alloc-id:fake:payload
    34574     # "f3 0f 2d/convert-to-int"
    34575     0x17/imm32/size
    34576     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
    34577 _string_f3_0f_2c_truncate_to_int:
    34578     0x11/imm32/alloc-id:fake:payload
    34579     # "f3 0f 2c/truncate-to-int"
    34580     0x18/imm32/size
    34581     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
    34582 _string_f3_0f_58_add:
    34583     0x11/imm32/alloc-id:fake:payload
    34584     # "f3 0f 58/add"
    34585     0xc/imm32/size
    34586     0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x35/5 0x38/8 0x2f/slash 0x61/a 0x64/d 0x64/d
    34587 _string_f3_0f_5c_subtract:
    34588     0x11/imm32/alloc-id:fake:payload
    34589     # "f3 0f 5c/subtract"
    34590     0x11/imm32/size
    34591     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
    34592 _string_f3_0f_59_multiply:
    34593     0x11/imm32/alloc-id:fake:payload
    34594     # "f3 0f 59/multiply"
    34595     0x11/imm32/size
    34596     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
    34597 _string_f3_0f_5e_divide:
    34598     0x11/imm32/alloc-id:fake:payload
    34599     # "f3 0f 5e/divide"
    34600     0xf/imm32/size
    34601     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
    34602 _string_f3_0f_53_reciprocal:
    34603     0x11/imm32/alloc-id:fake:payload
    34604     # "f3 0f 53/reciprocal"
    34605     0x13/imm32/size
    34606     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
    34607 _string_f3_0f_51_square_root:
    34608     0x11/imm32/alloc-id:fake:payload
    34609     # "f3 0f 51/square-root"
    34610     0x14/imm32/size
    34611     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
    34612 _string_f3_0f_52_inverse_square_root:
    34613     0x11/imm32/alloc-id:fake:payload
    34614     # "f3 0f 52/inverse-square-root"
    34615     0x1c/imm32/size
    34616     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
    34617 _string_f3_0f_5d_min:
    34618     0x11/imm32/alloc-id:fake:payload
    34619     # "f3 0f 5d/min"
    34620     0xc/imm32/size
    34621     0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x35/5 0x64/d 0x2f/slash 0x6d/m 0x69/i 0x6e/n
    34622 _string_f3_0f_5f_max:
    34623     0x11/imm32/alloc-id:fake:payload
    34624     # "f3 0f 5f/max"
    34625     0xc/imm32/size
    34626     0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x35/5 0x66/f 0x2f/slash 0x6d/m 0x61/a 0x78/x
    34627 _string_f3_0f_10_copy:
    34628     0x11/imm32/alloc-id:fake:payload
    34629     # "f3 0f 10/copy"
    34630     0xd/imm32/size
    34631     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
    34632 _string_f3_0f_11_copy:
    34633     0x11/imm32/alloc-id:fake:payload
    34634     # "f3 0f 11/copy"
    34635     0xd/imm32/size
    34636     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
    34637 _string_0f_2f_compare:
    34638     0x11/imm32/alloc-id:fake:payload
    34639     # "0f 2f/compare"
    34640     0xd/imm32/size
    34641     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
    34642 _string_21_and_with:  # (payload array byte)
    34643     0x11/imm32/alloc-id:fake:payload
    34644     # "21/and-with"
    34645     0xb/imm32/size
    34646     0x32/2 0x31/1 0x2f/slash 0x61/a 0x6e/n 0x64/d 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h
    34647 _string_23_and:  # (payload array byte)
    34648     0x11/imm32/alloc-id:fake:payload
    34649     # "23/and"
    34650     0x6/imm32/size
    34651     0x32/2 0x33/3 0x2f/slash 0x61/a 0x6e/n 0x64/d
    34652 _string_25_and_with_eax:  # (payload array byte)
    34653     0x11/imm32/alloc-id:fake:payload
    34654     # "25/and-with-eax"
    34655     0xf/imm32/size
    34656     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
    34657 _string_29_subtract_from:  # (payload array byte)
    34658     0x11/imm32/alloc-id:fake:payload
    34659     # "29/subtract-from"
    34660     0x10/imm32/size
    34661     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
    34662 _string_2b_subtract:  # (payload array byte)
    34663     0x11/imm32/alloc-id:fake:payload
    34664     # "2b/subtract"
    34665     0xb/imm32/size
    34666     0x32/2 0x62/b 0x2f/slash 0x73/s 0x75/u 0x62/b 0x74/t 0x72/r 0x61/a 0x63/c 0x74/t
    34667 _string_2d_subtract_from_eax:  # (payload array byte)
    34668     0x11/imm32/alloc-id:fake:payload
    34669     # "2d/subtract-from-eax"
    34670     0x14/imm32/size
    34671     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
    34672 _string_31_xor_with:  # (payload array byte)
    34673     0x11/imm32/alloc-id:fake:payload
    34674     # "31/xor-with"
    34675     0xb/imm32/size
    34676     0x33/3 0x31/1 0x2f/slash 0x78/x 0x6f/o 0x72/r 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h
    34677 _string_33_xor:  # (payload array byte)
    34678     0x11/imm32/alloc-id:fake:payload
    34679     # "33/xor"
    34680     0x6/imm32/size
    34681     0x33/3 0x33/3 0x2f/slash 0x78/x 0x6f/o 0x72/r
    34682 _string_35_xor_with_eax:  # (payload array byte)
    34683     0x11/imm32/alloc-id:fake:payload
    34684     # "35/xor-with-eax"
    34685     0xf/imm32/size
    34686     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
    34687 _string_39_compare->:  # (payload array byte)
    34688     0x11/imm32/alloc-id:fake:payload
    34689     # "39/compare->"
    34690     0xc/imm32/size
    34691     0x33/3 0x39/9 0x2f/slash 0x63/c 0x6f/o 0x6d/m 0x70/p 0x61/a 0x72/r 0x65/e 0x2d/dash 0x3e/>
    34692 _string_3b_compare<-:  # (payload array byte)
    34693     0x11/imm32/alloc-id:fake:payload
    34694     # "3b/compare<-"
    34695     0xc/imm32/size
    34696     0x33/3 0x62/b 0x2f/slash 0x63/c 0x6f/o 0x6d/m 0x70/p 0x61/a 0x72/r 0x65/e 0x3c/< 0x2d/dash
    34697 _string_3d_compare_eax_with:  # (payload array byte)
    34698     0x11/imm32/alloc-id:fake:payload
    34699     # "3d/compare-eax-with"
    34700     0x13/imm32/size
    34701     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
    34702 _string_40_increment_eax:  # (payload array byte)
    34703     0x11/imm32/alloc-id:fake:payload
    34704     # "40/increment-eax"
    34705     0x10/imm32/size
    34706     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
    34707 _string_41_increment_ecx:  # (payload array byte)
    34708     0x11/imm32/alloc-id:fake:payload
    34709     # "41/increment-ecx"
    34710     0x10/imm32/size
    34711     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
    34712 _string_42_increment_edx:  # (payload array byte)
    34713     0x11/imm32/alloc-id:fake:payload
    34714     # "42/increment-edx"
    34715     0x10/imm32/size
    34716     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
    34717 _string_43_increment_ebx:  # (payload array byte)
    34718     0x11/imm32/alloc-id:fake:payload
    34719     # "43/increment-ebx"
    34720     0x10/imm32/size
    34721     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
    34722 _string_46_increment_esi:  # (payload array byte)
    34723     0x11/imm32/alloc-id:fake:payload
    34724     # "46/increment-esi"
    34725     0x10/imm32/size
    34726     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
    34727 _string_47_increment_edi:  # (payload array byte)
    34728     0x11/imm32/alloc-id:fake:payload
    34729     # "47/increment-edi"
    34730     0x10/imm32/size
    34731     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
    34732 _string_48_decrement_eax:  # (payload array byte)
    34733     0x11/imm32/alloc-id:fake:payload
    34734     # "48/decrement-eax"
    34735     0x10/imm32/size
    34736     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
    34737 _string_49_decrement_ecx:  # (payload array byte)
    34738     0x11/imm32/alloc-id:fake:payload
    34739     # "49/decrement-ecx"
    34740     0x10/imm32/size
    34741     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
    34742 _string_4a_decrement_edx:  # (payload array byte)
    34743     0x11/imm32/alloc-id:fake:payload
    34744     # "4a/decrement-edx"
    34745     0x10/imm32/size
    34746     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
    34747 _string_4b_decrement_ebx:  # (payload array byte)
    34748     0x11/imm32/alloc-id:fake:payload
    34749     # "4b/decrement-ebx"
    34750     0x10/imm32/size
    34751     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
    34752 _string_4e_decrement_esi:  # (payload array byte)
    34753     0x11/imm32/alloc-id:fake:payload
    34754     # "4e/decrement-esi"
    34755     0x10/imm32/size
    34756     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
    34757 _string_4f_decrement_edi:  # (payload array byte)
    34758     0x11/imm32/alloc-id:fake:payload
    34759     # "4f/decrement-edi"
    34760     0x10/imm32/size
    34761     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
    34762 _string_81_subop_add:  # (payload array byte)
    34763     0x11/imm32/alloc-id:fake:payload
    34764     # "81 0/subop/add"
    34765     0xe/imm32/size
    34766     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
    34767 _string_81_subop_or:  # (payload array byte)
    34768     0x11/imm32/alloc-id:fake:payload
    34769     # "81 1/subop/or"
    34770     0xd/imm32/size
    34771     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
    34772 _string_81_subop_and:  # (payload array byte)
    34773     0x11/imm32/alloc-id:fake:payload
    34774     # "81 4/subop/and"
    34775     0xe/imm32/size
    34776     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
    34777 _string_81_subop_subtract:  # (payload array byte)
    34778     0x11/imm32/alloc-id:fake:payload
    34779     # "81 5/subop/subtract"
    34780     0x13/imm32/size
    34781     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
    34782 _string_81_subop_xor:  # (payload array byte)
    34783     0x11/imm32/alloc-id:fake:payload
    34784     # "81 6/subop/xor"
    34785     0xe/imm32/size
    34786     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
    34787 _string_81_subop_compare:  # (payload array byte)
    34788     0x11/imm32/alloc-id:fake:payload
    34789     # "81 7/subop/compare"
    34790     0x12/imm32/size
    34791     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
    34792 _string_89_<-:  # (payload array byte)
    34793     0x11/imm32/alloc-id:fake:payload
    34794     # "89/<-"
    34795     0x5/imm32/size
    34796     0x38/8 0x39/9 0x2f/slash 0x3c/< 0x2d/dash
    34797 _string_8b_->:  # (payload array byte)
    34798     0x11/imm32/alloc-id:fake:payload
    34799     # "8b/->"
    34800     0x5/imm32/size
    34801     0x38/8 0x62/b 0x2f/slash 0x2d/dash 0x3e/>
    34802 _string_8a_copy_byte:
    34803     0x11/imm32/alloc-id:fake:payload
    34804     # "8a/byte->"
    34805     0x9/imm32/size
    34806     0x38/8 0x61/a 0x2f/slash 0x62/b 0x79/y 0x74/t 0x65/e 0x2d/dash 0x3e/>
    34807 _string_88_copy_byte:
    34808     0x11/imm32/alloc-id:fake:payload
    34809     # "88/byte<-"
    34810     0x9/imm32/size
    34811     0x38/8 0x38/8 0x2f/slash 0x62/b 0x79/y 0x74/t 0x65/e 0x3c/< 0x2d/-
    34812 _string_8d_copy_address:  # (payload array byte)
    34813     0x11/imm32/alloc-id:fake:payload
    34814     # "8d/copy-address"
    34815     0xf/imm32/size
    34816     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
    34817 _string_b8_copy_to_eax:  # (payload array byte)
    34818     0x11/imm32/alloc-id:fake:payload
    34819     # "b8/copy-to-eax"
    34820     0xe/imm32/size
    34821     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
    34822 _string_b9_copy_to_ecx:  # (payload array byte)
    34823     0x11/imm32/alloc-id:fake:payload
    34824     # "b9/copy-to-ecx"
    34825     0xe/imm32/size
    34826     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
    34827 _string_ba_copy_to_edx:  # (payload array byte)
    34828     0x11/imm32/alloc-id:fake:payload
    34829     # "ba/copy-to-edx"
    34830     0xe/imm32/size
    34831     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
    34832 _string_bb_copy_to_ebx:  # (payload array byte)
    34833     0x11/imm32/alloc-id:fake:payload
    34834     # "bb/copy-to-ebx"
    34835     0xe/imm32/size
    34836     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
    34837 _string_be_copy_to_esi:  # (payload array byte)
    34838     0x11/imm32/alloc-id:fake:payload
    34839     # "be/copy-to-esi"
    34840     0xe/imm32/size
    34841     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
    34842 _string_bf_copy_to_edi:  # (payload array byte)
    34843     0x11/imm32/alloc-id:fake:payload
    34844     # "bf/copy-to-edi"
    34845     0xe/imm32/size
    34846     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
    34847 _string_c7_subop_copy:  # (payload array byte)
    34848     0x11/imm32/alloc-id:fake:payload
    34849     # "c7 0/subop/copy"
    34850     0xf/imm32/size
    34851     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
    34852 _string_e9_jump_label:  # (payload array byte)
    34853     0x11/imm32/alloc-id:fake:payload
    34854     # "e9/jump"
    34855     0x7/imm32/size
    34856     0x65/e 0x39/9 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p
    34857 _string_e9_jump_break:  # (payload array byte)
    34858     0x11/imm32/alloc-id:fake:payload
    34859     # "e9/jump break/disp32"
    34860     0x14/imm32/size
    34861     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
    34862 _string_e9_jump_loop:  # (payload array byte)
    34863     0x11/imm32/alloc-id:fake:payload
    34864     # "e9/jump loop/disp32"
    34865     0x13/imm32/size
    34866     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
    34867 _string_f7_subop_negate:
    34868     0x11/imm32/alloc-id:fake:payload
    34869     # "f7 3/subop/negate"
    34870     0x11/imm32/size
    34871     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
    34872 _string_f7_subop_not:
    34873     0x11/imm32/alloc-id:fake:payload
    34874     # "f7 2/subop/not"
    34875     0xe/imm32/size
    34876     0x66/f 0x37/7 0x20/space 0x32/2 0x2f/slash 0x73/s 0x75/u 0x62/b 0x6f/o 0x70/p 0x2f/slash 0x6e/n 0x6f/o 0x74/t
    34877 _string_ff_subop_increment:  # (payload array byte)
    34878     0x11/imm32/alloc-id:fake:payload
    34879     # "ff 0/subop/increment"
    34880     0x14/imm32/size
    34881     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
    34882 _string_ff_subop_decrement:  # (payload array byte)
    34883     0x11/imm32/alloc-id:fake:payload
    34884     # "ff 1/subop/decrement"
    34885     0x14/imm32/size
    34886     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
    34887 _string_c1_subop_shift_left:  # (payload array byte)
    34888     0x11/imm32/alloc-id:fake:payload
    34889     # "c1/shift 4/subop/left"
    34890     0x15/imm32/size
    34891     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
    34892 _string_c1_subop_shift_right_padding_zeroes:  # (payload array byte)
    34893     0x11/imm32/alloc-id:fake:payload
    34894     # "c1/shift 5/subop/right-padding-zeroes"
    34895     0x25/imm32/size
    34896     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
    34897 _string_c1_subop_shift_right_preserving_sign:  # (payload array byte)
    34898     0x11/imm32/alloc-id:fake:payload
    34899     # "c1/shift 7/subop/right-preserving-sign"
    34900     0x26/imm32/size
    34901     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
    34902
    34903 Single-int-var-in-mem:  # (payload list var)
    34904     0x11/imm32/alloc-id:fake:payload
    34905     0x11/imm32/alloc-id:fake
    34906     Int-var-in-mem/imm32
    34907     0/imm32/next
    34908     0/imm32/next
    34909
    34910 Int-var-in-mem:  # (payload var)
    34911     0x11/imm32/alloc-id:fake:payload
    34912     0/imm32/name
    34913     0/imm32/name
    34914     0x11/imm32/alloc-id:fake
    34915     Type-int/imm32
    34916     1/imm32/some-block-depth
    34917     1/imm32/some-stack-offset
    34918     0/imm32/no-register
    34919     0/imm32/no-register
    34920
    34921 # Not really legal, but closest we can currently represent a dereference of an (addr byte)
    34922 Single-byte-var-in-mem:  # (payload list var)
    34923     0x11/imm32/alloc-id:fake:payload
    34924     0x11/imm32/alloc-id:fake
    34925     Byte-var-in-mem/imm32
    34926     0/imm32/next
    34927     0/imm32/next
    34928
    34929 # Not really legal, but closest we can currently represent a dereference of an (addr byte)
    34930 Byte-var-in-mem:  # (payload var)
    34931     0x11/imm32/alloc-id:fake:payload
    34932     0/imm32/name
    34933     0/imm32/name
    34934     0x11/imm32/alloc-id:fake
    34935     Type-byte/imm32
    34936     1/imm32/some-block-depth
    34937     1/imm32/some-stack-offset
    34938     0/imm32/no-register
    34939     0/imm32/no-register
    34940
    34941 Two-args-int-stack-int-reg:  # (payload list var)
    34942     0x11/imm32/alloc-id:fake:payload
    34943     0x11/imm32/alloc-id:fake
    34944     Int-var-in-mem/imm32
    34945     0x11/imm32/alloc-id:fake
    34946     Single-int-var-in-some-register/imm32/next
    34947
    34948 Two-int-args-in-regs:  # (payload list var)
    34949     0x11/imm32/alloc-id:fake:payload
    34950     0x11/imm32/alloc-id:fake
    34951     Int-var-in-some-register/imm32
    34952     0x11/imm32/alloc-id:fake
    34953     Single-int-var-in-some-register/imm32/next
    34954
    34955 # Not really legal, but closest we can currently represent a dereference of an (addr byte)
    34956 Two-args-byte-stack-byte-reg:  # (payload list var)
    34957     0x11/imm32/alloc-id:fake:payload
    34958     0x11/imm32/alloc-id:fake
    34959     Byte-var-in-mem/imm32
    34960     0x11/imm32/alloc-id:fake
    34961     Single-byte-var-in-some-register/imm32/next
    34962
    34963 Two-args-int-reg-int-stack:  # (payload list var)
    34964     0x11/imm32/alloc-id:fake:payload
    34965     0x11/imm32/alloc-id:fake
    34966     Int-var-in-some-register/imm32
    34967     0x11/imm32/alloc-id:fake
    34968     Single-int-var-in-mem/imm32/next
    34969
    34970 Two-args-int-eax-int-literal:  # (payload list var)
    34971     0x11/imm32/alloc-id:fake:payload
    34972     0x11/imm32/alloc-id:fake
    34973     Int-var-in-eax/imm32
    34974     0x11/imm32/alloc-id:fake
    34975     Single-lit-var/imm32/next
    34976
    34977 Int-var-and-literal:  # (payload list var)
    34978     0x11/imm32/alloc-id:fake:payload
    34979     0x11/imm32/alloc-id:fake
    34980     Int-var-in-mem/imm32
    34981     0x11/imm32/alloc-id:fake
    34982     Single-lit-var/imm32/next
    34983
    34984 Int-var-in-register-and-literal:  # (payload list var)
    34985     0x11/imm32/alloc-id:fake:payload
    34986     0x11/imm32/alloc-id:fake
    34987     Int-var-in-some-register/imm32
    34988     0x11/imm32/alloc-id:fake
    34989     Single-lit-var/imm32/next
    34990
    34991 Two-float-args-in-regs:  # (payload list var)
    34992     0x11/imm32/alloc-id:fake:payload
    34993     0x11/imm32/alloc-id:fake
    34994     Float-var-in-some-register/imm32
    34995     0x11/imm32/alloc-id:fake
    34996     Single-float-var-in-some-register/imm32/next
    34997
    34998 Two-args-float-reg-float-stack:  # (payload list var)
    34999     0x11/imm32/alloc-id:fake:payload
    35000     0x11/imm32/alloc-id:fake
    35001     Float-var-in-some-register/imm32
    35002     0x11/imm32/alloc-id:fake
    35003     Single-float-var-in-mem/imm32/next
    35004
    35005 Two-args-float-stack-float-reg:  # (payload list var)
    35006     0x11/imm32/alloc-id:fake:payload
    35007     0x11/imm32/alloc-id:fake
    35008     Float-var-in-mem/imm32
    35009     0x11/imm32/alloc-id:fake
    35010     Single-float-var-in-some-register/imm32/next
    35011
    35012 Single-int-var-in-some-register:  # (payload list var)
    35013     0x11/imm32/alloc-id:fake:payload
    35014     0x11/imm32/alloc-id:fake
    35015     Int-var-in-some-register/imm32
    35016     0/imm32/next
    35017     0/imm32/next
    35018
    35019 Single-addr-var-in-some-register:  # (payload list var)
    35020     0x11/imm32/alloc-id:fake:payload
    35021     0x11/imm32/alloc-id:fake
    35022     Addr-var-in-some-register/imm32
    35023     0/imm32/next
    35024     0/imm32/next
    35025
    35026 Single-byte-var-in-some-register:  # (payload list var)
    35027     0x11/imm32/alloc-id:fake:payload
    35028     0x11/imm32/alloc-id:fake
    35029     Byte-var-in-some-register/imm32
    35030     0/imm32/next
    35031     0/imm32/next
    35032
    35033 Int-var-in-some-register:  # (payload var)
    35034     0x11/imm32/alloc-id:fake:payload
    35035     0/imm32/name
    35036     0/imm32/name
    35037     0x11/imm32/alloc-id:fake
    35038     Type-int/imm32
    35039     1/imm32/some-block-depth
    35040     0/imm32/no-stack-offset
    35041     0x11/imm32/alloc-id:fake
    35042     Any-register/imm32
    35043
    35044 Any-register:  # (payload array byte)
    35045     0x11/imm32/alloc-id:fake:payload
    35046     1/imm32/size
    35047     # data
    35048     2a/asterisk
    35049
    35050 Addr-var-in-some-register:  # (payload var)
    35051     0x11/imm32/alloc-id:fake:payload
    35052     0/imm32/name
    35053     0/imm32/name
    35054     0x11/imm32/alloc-id:fake
    35055     Type-addr/imm32
    35056     1/imm32/some-block-depth
    35057     0/imm32/no-stack-offset
    35058     0x11/imm32/alloc-id:fake
    35059     Any-register/imm32
    35060
    35061 Byte-var-in-some-register:  # (payload var)
    35062     0x11/imm32/alloc-id:fake:payload
    35063     0/imm32/name
    35064     0/imm32/name
    35065     0x11/imm32/alloc-id:fake
    35066     Type-byte/imm32
    35067     1/imm32/some-block-depth
    35068     0/imm32/no-stack-offset
    35069     0x11/imm32/alloc-id:fake
    35070     Any-register/imm32
    35071
    35072 Single-int-var-in-eax:  # (payload list var)
    35073     0x11/imm32/alloc-id:fake:payload
    35074     0x11/imm32/alloc-id:fake
    35075     Int-var-in-eax/imm32
    35076     0/imm32/next
    35077     0/imm32/next
    35078
    35079 Int-var-in-eax:
    35080     0x11/imm32/alloc-id:fake:payload
    35081     0/imm32/name
    35082     0/imm32/name
    35083     0x11/imm32/alloc-id:fake
    35084     Type-int/imm32
    35085     1/imm32/some-block-depth
    35086     0/imm32/no-stack-offset
    35087     0x11/imm32/alloc-id:fake
    35088     $Mu-register-eax/imm32  # can't use Register-eax only to keep our buggy tools/treeshake.cc happy (TODO)
    35089
    35090 Single-int-var-in-ecx:  # (payload list var)
    35091     0x11/imm32/alloc-id:fake:payload
    35092     0x11/imm32/alloc-id:fake
    35093     Int-var-in-ecx/imm32
    35094     0/imm32/next
    35095     0/imm32/next
    35096
    35097 Int-var-in-ecx:
    35098     0x11/imm32/alloc-id:fake:payload
    35099     0/imm32/name
    35100     0/imm32/name
    35101     0x11/imm32/alloc-id:fake
    35102     Type-int/imm32
    35103     1/imm32/some-block-depth
    35104     0/imm32/no-stack-offset
    35105     0x11/imm32/alloc-id:fake
    35106     $Register-ecx/imm32/register
    35107
    35108 Single-int-var-in-edx:  # (payload list var)
    35109     0x11/imm32/alloc-id:fake:payload
    35110     0x11/imm32/alloc-id:fake
    35111     Int-var-in-edx/imm32
    35112     0/imm32/next
    35113     0/imm32/next
    35114
    35115 Int-var-in-edx:  # (payload list var)
    35116     0x11/imm32/alloc-id:fake:payload
    35117     0/imm32/name
    35118     0/imm32/name
    35119     0x11/imm32/alloc-id:fake
    35120     Type-int/imm32
    35121     1/imm32/some-block-depth
    35122     0/imm32/no-stack-offset
    35123     0x11/imm32/alloc-id:fake
    35124     $Register-edx/imm32/register
    35125
    35126 Single-int-var-in-ebx:  # (payload list var)
    35127     0x11/imm32/alloc-id:fake:payload
    35128     0x11/imm32/alloc-id:fake
    35129     Int-var-in-ebx/imm32
    35130     0/imm32/next
    35131     0/imm32/next
    35132
    35133 Int-var-in-ebx:  # (payload list var)
    35134     0x11/imm32/alloc-id:fake:payload
    35135     0/imm32/name
    35136     0/imm32/name
    35137     0x11/imm32/alloc-id:fake
    35138     Type-int/imm32
    35139     1/imm32/some-block-depth
    35140     0/imm32/no-stack-offset
    35141     0x11/imm32/alloc-id:fake
    35142     $Register-ebx/imm32/register
    35143
    35144 Single-int-var-in-esi:  # (payload list var)
    35145     0x11/imm32/alloc-id:fake:payload
    35146     0x11/imm32/alloc-id:fake
    35147     Int-var-in-esi/imm32
    35148     0/imm32/next
    35149     0/imm32/next
    35150
    35151 Int-var-in-esi:  # (payload list var)
    35152     0x11/imm32/alloc-id:fake:payload
    35153     0/imm32/name
    35154     0/imm32/name
    35155     0x11/imm32/alloc-id:fake
    35156     Type-int/imm32
    35157     1/imm32/some-block-depth
    35158     0/imm32/no-stack-offset
    35159     0x11/imm32/alloc-id:fake
    35160     $Register-esi/imm32/register
    35161
    35162 Single-int-var-in-edi:  # (payload list var)
    35163     0x11/imm32/alloc-id:fake:payload
    35164     0x11/imm32/alloc-id:fake
    35165     Int-var-in-edi/imm32
    35166     0/imm32/next
    35167     0/imm32/next
    35168
    35169 Int-var-in-edi:  # (payload list var)
    35170     0x11/imm32/alloc-id:fake:payload
    35171     0/imm32/name
    35172     0/imm32/name
    35173     0x11/imm32/alloc-id:fake
    35174     Type-int/imm32
    35175     1/imm32/some-block-depth
    35176     0/imm32/no-stack-offset
    35177     0x11/imm32/alloc-id:fake
    35178     $Register-edi/imm32/register
    35179
    35180 Single-lit-var:  # (payload list var)
    35181     0x11/imm32/alloc-id:fake:payload
    35182     0x11/imm32/alloc-id:fake
    35183     Lit-var/imm32
    35184     0/imm32/next
    35185     0/imm32/next
    35186
    35187 Lit-var:  # (payload var)
    35188     0x11/imm32/alloc-id:fake:payload
    35189     0/imm32/name
    35190     0/imm32/name
    35191     0x11/imm32/alloc-id:fake
    35192     Type-literal/imm32
    35193     1/imm32/some-block-depth
    35194     0/imm32/no-stack-offset
    35195     0/imm32/no-register
    35196     0/imm32/no-register
    35197
    35198 Single-float-var-in-mem:  # (payload list var)
    35199     0x11/imm32/alloc-id:fake:payload
    35200     0x11/imm32/alloc-id:fake
    35201     Float-var-in-mem/imm32
    35202     0/imm32/next
    35203     0/imm32/next
    35204
    35205 Float-var-in-mem:  # (payload var)
    35206     0x11/imm32/alloc-id:fake:payload
    35207     0/imm32/name
    35208     0/imm32/name
    35209     0x11/imm32/alloc-id:fake
    35210     Type-float/imm32
    35211     1/imm32/some-block-depth
    35212     1/imm32/some-stack-offset
    35213     0/imm32/no-register
    35214     0/imm32/no-register
    35215
    35216 Single-float-var-in-some-register:  # (payload list var)
    35217     0x11/imm32/alloc-id:fake:payload
    35218     0x11/imm32/alloc-id:fake
    35219     Float-var-in-some-register/imm32
    35220     0/imm32/next
    35221     0/imm32/next
    35222
    35223 Float-var-in-some-register:  # (payload var)
    35224     0x11/imm32/alloc-id:fake:payload
    35225     0/imm32/name
    35226     0/imm32/name
    35227     0x11/imm32/alloc-id:fake
    35228     Type-float/imm32
    35229     1/imm32/some-block-depth
    35230     0/imm32/no-stack-offset
    35231     0x11/imm32/alloc-id:fake
    35232     Any-register/imm32
    35233
    35234 Type-int:  # (payload type-tree)
    35235     0x11/imm32/alloc-id:fake:payload
    35236     1/imm32/is-atom
    35237     1/imm32/value:int
    35238     0/imm32/left:unused
    35239     0/imm32/right:null
    35240     0/imm32/right:null
    35241
    35242 Type-literal:  # (payload type-tree)
    35243     0x11/imm32/alloc-id:fake:payload
    35244     1/imm32/is-atom
    35245     0/imm32/value:literal
    35246     0/imm32/left:unused
    35247     0/imm32/right:null
    35248     0/imm32/right:null
    35249
    35250 Type-addr:  # (payload type-tree)
    35251     0x11/imm32/alloc-id:fake:payload
    35252     1/imm32/is-atom
    35253     2/imm32/value:addr
    35254     0/imm32/left:unused
    35255     0/imm32/right:null
    35256     0/imm32/right:null
    35257
    35258 Type-byte:  # (payload type-tree)
    35259     0x11/imm32/alloc-id:fake:payload
    35260     1/imm32/is-atom
    35261     8/imm32/value:byte
    35262     0/imm32/left:unused
    35263     0/imm32/right:null
    35264     0/imm32/right:null
    35265
    35266 Type-float:  # (payload type-tree)
    35267     0x11/imm32/alloc-id:fake:payload
    35268     1/imm32/is-atom
    35269     0xf/imm32/value:float
    35270     0/imm32/left:unused
    35271     0/imm32/right:null
    35272     0/imm32/right:null
    35273
    35274 == code
    35275 emit-subx-primitive:  # out: (addr buffered-file), stmt: (addr stmt), primitive: (addr primitive), err: (addr buffered-file), ed: (addr exit-descriptor)
    35276     # . prologue
    35277     55/push-ebp
    35278     89/<- %ebp 4/r32/esp
    35279     # . save registers
    35280     50/push-eax
    35281     51/push-ecx
    35282     # ecx = primitive
    35283     8b/-> *(ebp+0x10) 1/r32/ecx
    35284     # emit primitive name
    35285     (emit-indent *(ebp+8) *Curr-block-depth)
    35286     (lookup *(ecx+0x18) *(ecx+0x1c))  # Primitive-subx-name Primitive-subx-name => eax
    35287     (write-buffered *(ebp+8) %eax)
    35288     # emit rm32 if necessary
    35289     (emit-subx-rm32 *(ebp+8) *(ecx+0x20) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))  # Primitive-subx-rm32
    35290     # emit xm32 if necessary
    35291     (emit-subx-rm32 *(ebp+8) *(ecx+0x34) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))  # Primitive-subx-xm32
    35292     # emit r32 if necessary
    35293     (emit-subx-r32 *(ebp+8) *(ecx+0x24) *(ebp+0xc))  # Primitive-subx-r32
    35294     # emit x32 if necessary
    35295     (emit-subx-x32 *(ebp+8) *(ecx+0x38) *(ebp+0xc))  # Primitive-subx-x32
    35296     # emit imm32 if necessary
    35297     (emit-subx-imm32 *(ebp+8) *(ecx+0x28) *(ebp+0xc))  # Primitive-subx-imm32
    35298     # emit imm8 if necessary
    35299     (emit-subx-imm8 *(ebp+8) *(ecx+0x2c) *(ebp+0xc))  # Primitive-subx-imm8
    35300     # emit disp32 if necessary
    35301     (emit-subx-disp32 *(ebp+8) *(ecx+0x30) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))  # Primitive-subx-disp32
    35302     (write-buffered *(ebp+8) Newline)
    35303 $emit-subx-primitive:end:
    35304     # . restore registers
    35305     59/pop-to-ecx
    35306     58/pop-to-eax
    35307     # . epilogue
    35308     89/<- %esp 5/r32/ebp
    35309     5d/pop-to-ebp
    35310     c3/return
    35311
    35312 emit-subx-rm32:  # out: (addr buffered-file), l: arg-location, stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
    35313     # . prologue
    35314     55/push-ebp
    35315     89/<- %ebp 4/r32/esp
    35316     # . save registers
    35317     50/push-eax
    35318     # if (l == 0) return
    35319     81 7/subop/compare *(ebp+0xc) 0/imm32
    35320     74/jump-if-= $emit-subx-rm32:end/disp8
    35321     # var v/eax: (addr stmt-var)
    35322     (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))  # => eax
    35323     (emit-subx-var-as-rm32 *(ebp+8) %eax)
    35324 $emit-subx-rm32:end:
    35325     # . restore registers
    35326     58/pop-to-eax
    35327     # . epilogue
    35328     89/<- %esp 5/r32/ebp
    35329     5d/pop-to-ebp
    35330     c3/return
    35331
    35332 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)
    35333     # . prologue
    35334     55/push-ebp
    35335     89/<- %ebp 4/r32/esp
    35336     # . save registers
    35337     51/push-ecx
    35338     # eax = l
    35339     8b/-> *(ebp+0xc) 0/r32/eax
    35340     # ecx = stmt
    35341     8b/-> *(ebp+8) 1/r32/ecx
    35342     # if (l == 1) return stmt->inouts
    35343     {
    35344       3d/compare-eax-and 1/imm32
    35345       75/jump-if-!= break/disp8
    35346 $get-stmt-operand-from-arg-location:1:
    35347       (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    35348       eb/jump $get-stmt-operand-from-arg-location:end/disp8
    35349     }
    35350     # if (l == 2) return stmt->inouts->next
    35351     {
    35352       3d/compare-eax-and 2/imm32
    35353       75/jump-if-!= break/disp8
    35354 $get-stmt-operand-from-arg-location:2:
    35355       (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    35356       (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    35357       eb/jump $get-stmt-operand-from-arg-location:end/disp8
    35358     }
    35359     # if (l == 3) return stmt->outputs
    35360     {
    35361       3d/compare-eax-and 3/imm32
    35362       75/jump-if-!= break/disp8
    35363 $get-stmt-operand-from-arg-location:3:
    35364       (lookup *(ecx+0x14) *(ecx+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    35365       eb/jump $get-stmt-operand-from-arg-location:end/disp8
    35366     }
    35367     # abort
    35368     e9/jump $get-stmt-operand-from-arg-location:abort/disp32
    35369 $get-stmt-operand-from-arg-location:end:
    35370     # . restore registers
    35371     59/pop-to-ecx
    35372     # . epilogue
    35373     89/<- %esp 5/r32/ebp
    35374     5d/pop-to-ebp
    35375     c3/return
    35376
    35377 $get-stmt-operand-from-arg-location:abort:
    35378     # error("invalid arg-location " eax)
    35379     (write-buffered *(ebp+0x10) "invalid arg-location ")
    35380     (write-int32-hex-buffered *(ebp+0x10) %eax)
    35381     (write-buffered *(ebp+0x10) Newline)
    35382     (flush *(ebp+0x10))
    35383     (stop *(ebp+0x14) 1)
    35384     # never gets here
    35385
    35386 emit-subx-r32:  # out: (addr buffered-file), l: arg-location, stmt: (addr stmt)
    35387     # . prologue
    35388     55/push-ebp
    35389     89/<- %ebp 4/r32/esp
    35390     # . save registers
    35391     50/push-eax
    35392     51/push-ecx
    35393     # if (l == 0) return
    35394     81 7/subop/compare *(ebp+0xc) 0/imm32
    35395     0f 84/jump-if-= $emit-subx-r32:end/disp32
    35396     # var v/eax: (addr stmt-var)
    35397     (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc))  # => eax
    35398     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    35399     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    35400 #?     (write-buffered Stderr "looking up ")
    35401 #?     (write-buffered Stderr %eax)
    35402 #?     (write-buffered Stderr Newline)
    35403 #?     (flush Stderr)
    35404     (maybe-get Mu-registers %eax 0xc)  # => eax: (addr register-index)
    35405     (write-buffered *(ebp+8) Space)
    35406     (write-int32-hex-buffered *(ebp+8) *eax)
    35407     (write-buffered *(ebp+8) "/r32")
    35408 $emit-subx-r32:end:
    35409     # . restore registers
    35410     59/pop-to-ecx
    35411     58/pop-to-eax
    35412     # . epilogue
    35413     89/<- %esp 5/r32/ebp
    35414     5d/pop-to-ebp
    35415     c3/return
    35416
    35417 emit-subx-x32:  # out: (addr buffered-file), l: arg-location, stmt: (addr stmt)
    35418     # . prologue
    35419     55/push-ebp
    35420     89/<- %ebp 4/r32/esp
    35421     # . save registers
    35422     50/push-eax
    35423     51/push-ecx
    35424     # if (l == 0) return
    35425     81 7/subop/compare *(ebp+0xc) 0/imm32
    35426     0f 84/jump-if-= $emit-subx-x32:end/disp32
    35427     # var v/eax: (addr stmt-var)
    35428     (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc))  # => eax
    35429     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    35430     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    35431 #?     (write-buffered Stderr "looking up ")
    35432 #?     (write-buffered Stderr %eax)
    35433 #?     (write-buffered Stderr Newline)
    35434 #?     (flush Stderr)
    35435     (maybe-get Mu-registers %eax 0xc)  # => eax: (addr register-index)
    35436     (write-buffered *(ebp+8) Space)
    35437     (write-int32-hex-buffered *(ebp+8) *eax)
    35438     (write-buffered *(ebp+8) "/x32")
    35439 $emit-subx-x32:end:
    35440     # . restore registers
    35441     59/pop-to-ecx
    35442     58/pop-to-eax
    35443     # . epilogue
    35444     89/<- %esp 5/r32/ebp
    35445     5d/pop-to-ebp
    35446     c3/return
    35447
    35448 emit-subx-imm32:  # out: (addr buffered-file), l: arg-location, stmt: (addr stmt)
    35449     # . prologue
    35450     55/push-ebp
    35451     89/<- %ebp 4/r32/esp
    35452     # . save registers
    35453     50/push-eax
    35454     51/push-ecx
    35455     # if (l == 0) return
    35456     81 7/subop/compare *(ebp+0xc) 0/imm32
    35457     0f 84/jump-if-= $emit-subx-imm32:end/disp32
    35458     # var v/eax: (handle var)
    35459     (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc))  # => eax
    35460     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    35461     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    35462     (write-buffered *(ebp+8) Space)
    35463     (write-buffered *(ebp+8) %eax)
    35464     (write-buffered *(ebp+8) "/imm32")
    35465 $emit-subx-imm32:end:
    35466     # . restore registers
    35467     59/pop-to-ecx
    35468     58/pop-to-eax
    35469     # . epilogue
    35470     89/<- %esp 5/r32/ebp
    35471     5d/pop-to-ebp
    35472     c3/return
    35473
    35474 emit-subx-imm8:  # out: (addr buffered-file), l: arg-location, stmt: (addr stmt)
    35475     # . prologue
    35476     55/push-ebp
    35477     89/<- %ebp 4/r32/esp
    35478     # . save registers
    35479     50/push-eax
    35480     51/push-ecx
    35481     # if (l == 0) return
    35482     81 7/subop/compare *(ebp+0xc) 0/imm32
    35483     0f 84/jump-if-= $emit-subx-imm32:end/disp32
    35484     # var v/eax: (handle var)
    35485     (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc))  # => eax
    35486     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    35487     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    35488     (write-buffered *(ebp+8) Space)
    35489     (write-buffered *(ebp+8) %eax)
    35490     (write-buffered *(ebp+8) "/imm8")
    35491 $emit-subx-imm8:end:
    35492     # . restore registers
    35493     59/pop-to-ecx
    35494     58/pop-to-eax
    35495     # . epilogue
    35496     89/<- %esp 5/r32/ebp
    35497     5d/pop-to-ebp
    35498     c3/return
    35499
    35500 emit-subx-disp32:  # out: (addr buffered-file), l: arg-location, stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
    35501     # . prologue
    35502     55/push-ebp
    35503     89/<- %ebp 4/r32/esp
    35504     # . save registers
    35505     50/push-eax
    35506     51/push-ecx
    35507     # if (location == 0) return
    35508     81 7/subop/compare *(ebp+0xc) 0/imm32
    35509     0f 84/jump-if-= $emit-subx-disp32:end/disp32
    35510     # var v/eax: (addr stmt-var)
    35511     (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))  # => eax
    35512     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    35513     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    35514     (write-buffered *(ebp+8) Space)
    35515     (write-buffered *(ebp+8) %eax)
    35516     # hack: if instruction operation starts with "break", emit ":break"
    35517     # var name/ecx: (addr array byte) = lookup(stmt->operation)
    35518     8b/-> *(ebp+0x10) 0/r32/eax
    35519     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
    35520     89/<- %ecx 0/r32/eax
    35521     {
    35522       (string-starts-with? %ecx "break")  # => eax
    35523       3d/compare-eax-and 0/imm32/false
    35524       74/jump-if-= break/disp8
    35525       (write-buffered *(ebp+8) ":break")
    35526     }
    35527     # hack: if instruction operation starts with "loop", emit ":loop"
    35528     {
    35529       (string-starts-with? %ecx "loop")  # => eax
    35530       3d/compare-eax-and 0/imm32/false
    35531       74/jump-if-= break/disp8
    35532       (write-buffered *(ebp+8) ":loop")
    35533     }
    35534     (write-buffered *(ebp+8) "/disp32")
    35535 $emit-subx-disp32:end:
    35536     # . restore registers
    35537     59/pop-to-ecx
    35538     58/pop-to-eax
    35539     # . epilogue
    35540     89/<- %esp 5/r32/ebp
    35541     5d/pop-to-ebp
    35542     c3/return
    35543
    35544 emit-call:  # out: (addr buffered-file), stmt: (addr stmt)
    35545     # . prologue
    35546     55/push-ebp
    35547     89/<- %ebp 4/r32/esp
    35548     # . save registers
    35549     50/push-eax
    35550     51/push-ecx
    35551     #
    35552     (emit-indent *(ebp+8) *Curr-block-depth)
    35553     (write-buffered *(ebp+8) "(")
    35554     # ecx = stmt
    35555     8b/-> *(ebp+0xc) 1/r32/ecx
    35556     # - emit function name
    35557     (lookup *(ecx+4) *(ecx+8))  # Stmt1-operation Stmt1-operation => eax
    35558     (write-buffered *(ebp+8) %eax)
    35559     # - emit arguments
    35560     # var curr/eax: (addr stmt-var) = lookup(stmt->inouts)
    35561     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    35562     {
    35563       # if (curr == null) break
    35564       3d/compare-eax-and 0/imm32
    35565       74/jump-if-= break/disp8
    35566       #
    35567       (emit-subx-call-operand *(ebp+8) %eax)
    35568       # curr = lookup(curr->next)
    35569       (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    35570       eb/jump loop/disp8
    35571     }
    35572     #
    35573     (write-buffered *(ebp+8) ")\n")
    35574 $emit-call:end:
    35575     # . restore registers
    35576     59/pop-to-ecx
    35577     58/pop-to-eax
    35578     # . epilogue
    35579     89/<- %esp 5/r32/ebp
    35580     5d/pop-to-ebp
    35581     c3/return
    35582
    35583 emit-subx-call-operand:  # out: (addr buffered-file), s: (addr stmt-var)
    35584     # shares code with emit-subx-var-as-rm32
    35585     # . prologue
    35586     55/push-ebp
    35587     89/<- %ebp 4/r32/esp
    35588     # . save registers
    35589     50/push-eax
    35590     51/push-ecx
    35591     56/push-esi
    35592     # ecx = s
    35593     8b/-> *(ebp+0xc) 1/r32/ecx
    35594     # var operand/esi: (addr var) = lookup(s->value)
    35595     (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
    35596     89/<- %esi 0/r32/eax
    35597     # if (operand->register && !s->is-deref?) emit "%__"
    35598     {
    35599 $emit-subx-call-operand:check-for-register-direct:
    35600       81 7/subop/compare *(esi+0x18) 0/imm32  # Var-register
    35601       74/jump-if-= break/disp8
    35602       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
    35603       75/jump-if-!= break/disp8
    35604 $emit-subx-call-operand:register-direct:
    35605       (write-buffered *(ebp+8) " %")
    35606       (lookup *(esi+0x18) *(esi+0x1c))  # Var-register Var-register => eax
    35607       (write-buffered *(ebp+8) %eax)
    35608       e9/jump $emit-subx-call-operand:end/disp32
    35609     }
    35610     # else if (operand->register && s->is-deref?) emit "*__"
    35611     {
    35612 $emit-subx-call-operand:check-for-register-indirect:
    35613       81 7/subop/compare *(esi+0x18) 0/imm32  # Var-register
    35614       74/jump-if-= break/disp8
    35615       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
    35616       74/jump-if-= break/disp8
    35617 $emit-subx-call-operand:register-indirect:
    35618       (emit-subx-call-operand-register-indirect *(ebp+8) %esi)
    35619       e9/jump $emit-subx-call-operand:end/disp32
    35620     }
    35621     # else if (operand->stack-offset) emit "*(ebp+__)"
    35622     {
    35623       81 7/subop/compare *(esi+0x14) 0/imm32  # Var-offset
    35624       74/jump-if-= break/disp8
    35625 $emit-subx-call-operand:stack:
    35626       (emit-subx-call-operand-stack *(ebp+8) %esi)
    35627       e9/jump $emit-subx-call-operand:end/disp32
    35628     }
    35629     # else if (operand->type == literal) emit "__"
    35630     {
    35631       (lookup *(esi+8) *(esi+0xc))  # Var-type Var-type => eax
    35632       81 7/subop/compare *(eax+4) 0/imm32  # Type-tree-value
    35633       75/jump-if-!= break/disp8
    35634 $emit-subx-call-operand:literal:
    35635       (write-buffered *(ebp+8) Space)
    35636       (lookup *esi *(esi+4))  # Var-name Var-name => eax
    35637       (write-buffered *(ebp+8) %eax)
    35638       e9/jump $emit-subx-call-operand:end/disp32
    35639     }
    35640     # else if (operand->type == literal-string) emit "__"
    35641     {
    35642       (lookup *(esi+8) *(esi+0xc))  # Var-type Var-type => eax
    35643       81 7/subop/compare *(eax+4) 0x10/imm32  # Type-tree-value
    35644       75/jump-if-!= break/disp8
    35645 $emit-subx-call-operand:literal-string:
    35646       (write-buffered *(ebp+8) Space)
    35647       (lookup *esi *(esi+4))  # Var-name Var-name => eax
    35648       (write-buffered *(ebp+8) %eax)
    35649     }
    35650 $emit-subx-call-operand:end:
    35651     # . restore registers
    35652     5e/pop-to-esi
    35653     59/pop-to-ecx
    35654     58/pop-to-eax
    35655     # . epilogue
    35656     89/<- %esp 5/r32/ebp
    35657     5d/pop-to-ebp
    35658     c3/return
    35659
    35660 emit-subx-call-operand-register-indirect:  # out: (addr buffered-file), v: (addr var)
    35661     # . prologue
    35662     55/push-ebp
    35663     89/<- %ebp 4/r32/esp
    35664     # . save registers
    35665     50/push-eax
    35666     51/push-ecx
    35667     56/push-esi
    35668     # esi = v
    35669     8b/-> *(ebp+0xc) 6/r32/esi
    35670     # var size/ecx: int = size-of-deref(v)
    35671     (size-of-deref %esi)  # => eax
    35672     89/<- %ecx 0/r32/eax
    35673     # var reg-name/esi: (addr array byte) = lookup(v->register)
    35674     (lookup *(esi+0x18) *(esi+0x1c))  # Var-register Var-register => eax
    35675     89/<- %esi 0/r32/eax
    35676     # TODO: assert size is a multiple of 4
    35677     # var i/eax: int = 0
    35678     b8/copy-to-eax 0/imm32
    35679     {
    35680 $emit-subx-call-operand-register-indirect:loop:
    35681       # if (i >= size) break
    35682       39/compare %eax 1/r32/ecx
    35683       7d/jump-if->= break/disp8
    35684       # emit " *(" v->register "+" i ")"
    35685       (write-buffered *(ebp+8) " *(")
    35686       (write-buffered *(ebp+8) %esi)
    35687       (write-buffered *(ebp+8) "+")
    35688       (write-int32-hex-buffered *(ebp+8) %eax)
    35689       (write-buffered *(ebp+8) ")")
    35690       # i += 4
    35691       05/add-to-eax 4/imm32
    35692       #
    35693       eb/jump loop/disp8
    35694     }
    35695 $emit-subx-call-operand-register-indirect:end:
    35696     # . restore registers
    35697     5e/pop-to-esi
    35698     59/pop-to-ecx
    35699     58/pop-to-eax
    35700     # . epilogue
    35701     89/<- %esp 5/r32/ebp
    35702     5d/pop-to-ebp
    35703     c3/return
    35704
    35705 emit-subx-call-operand-stack:  # out: (addr buffered-file), v: (addr var)
    35706     # . prologue
    35707     55/push-ebp
    35708     89/<- %ebp 4/r32/esp
    35709     # . save registers
    35710     50/push-eax
    35711     51/push-ecx
    35712     56/push-esi
    35713     # esi = v
    35714     8b/-> *(ebp+0xc) 6/r32/esi
    35715     # var curr/ecx: int = v->offset
    35716     8b/-> *(esi+0x14) 1/r32/ecx  # Var-offset
    35717     # var max/eax: int = v->offset + size-of(v)
    35718     (size-of %esi)  # => eax
    35719     # TODO: assert size is a multiple of 4
    35720     01/add-to %eax 1/r32/ecx
    35721     {
    35722 $emit-subx-call-operand-stack:loop:
    35723       # if (curr >= max) break
    35724       39/compare %ecx 0/r32/eax
    35725       7d/jump-if->= break/disp8
    35726       # emit " *(ebp+" curr ")"
    35727       (write-buffered *(ebp+8) " *(ebp+")
    35728       (write-int32-hex-buffered *(ebp+8) %ecx)
    35729       (write-buffered *(ebp+8) ")")
    35730       # i += 4
    35731       81 0/subop/add %ecx 4/imm32
    35732       #
    35733       eb/jump loop/disp8
    35734     }
    35735 $emit-subx-call-operand-stack:end:
    35736     # . restore registers
    35737     5e/pop-to-esi
    35738     59/pop-to-ecx
    35739     58/pop-to-eax
    35740     # . epilogue
    35741     89/<- %esp 5/r32/ebp
    35742     5d/pop-to-ebp
    35743     c3/return
    35744
    35745 emit-subx-var-as-rm32:  # out: (addr buffered-file), s: (addr stmt-var)
    35746     # . prologue
    35747     55/push-ebp
    35748     89/<- %ebp 4/r32/esp
    35749     # . save registers
    35750     50/push-eax
    35751     51/push-ecx
    35752     56/push-esi
    35753     # ecx = s
    35754     8b/-> *(ebp+0xc) 1/r32/ecx
    35755     # var operand/esi: (addr var) = lookup(s->value)
    35756     (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
    35757     89/<- %esi 0/r32/eax
    35758     # if (operand->register && s->is-deref?) emit "*__"
    35759     {
    35760 $emit-subx-var-as-rm32:check-for-register-indirect:
    35761       81 7/subop/compare *(esi+0x18) 0/imm32  # Var-register
    35762       74/jump-if-= break/disp8
    35763       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
    35764       74/jump-if-= break/disp8
    35765 $emit-subx-var-as-rm32:register-indirect:
    35766       (write-buffered *(ebp+8) " *")
    35767       (lookup *(esi+0x18) *(esi+0x1c))  # Var-register Var-register => eax
    35768       (write-buffered *(ebp+8) %eax)
    35769       e9/jump $emit-subx-var-as-rm32:end/disp32
    35770     }
    35771     # if (operand->register && !s->is-deref?) emit "%__"
    35772     {
    35773 $emit-subx-var-as-rm32:check-for-register-direct:
    35774       81 7/subop/compare *(esi+0x18) 0/imm32  # Var-register
    35775       74/jump-if-= break/disp8
    35776       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
    35777       75/jump-if-!= break/disp8
    35778 $emit-subx-var-as-rm32:register-direct:
    35779       (write-buffered *(ebp+8) " %")
    35780       (lookup *(esi+0x18) *(esi+0x1c))  # Var-register Var-register => eax
    35781       (write-buffered *(ebp+8) %eax)
    35782       e9/jump $emit-subx-var-as-rm32:end/disp32
    35783     }
    35784     # else if (operand->stack-offset) emit "*(ebp+__)"
    35785     {
    35786       81 7/subop/compare *(esi+0x14) 0/imm32  # Var-offset
    35787       74/jump-if-= break/disp8
    35788 $emit-subx-var-as-rm32:stack:
    35789       (write-buffered *(ebp+8) Space)
    35790       (write-buffered *(ebp+8) "*(ebp+")
    35791       (write-int32-hex-buffered *(ebp+8) *(esi+0x14))  # Var-offset
    35792       (write-buffered *(ebp+8) ")")
    35793     }
    35794 $emit-subx-var-as-rm32:end:
    35795     # . restore registers
    35796     5e/pop-to-esi
    35797     59/pop-to-ecx
    35798     58/pop-to-eax
    35799     # . epilogue
    35800     89/<- %esp 5/r32/ebp
    35801     5d/pop-to-ebp
    35802     c3/return
    35803
    35804 find-matching-primitive:  # primitives: (addr primitive), stmt: (addr stmt) -> result/eax: (addr primitive)
    35805     # . prologue
    35806     55/push-ebp
    35807     89/<- %ebp 4/r32/esp
    35808     # . save registers
    35809     51/push-ecx
    35810     # var curr/ecx: (addr primitive) = primitives
    35811     8b/-> *(ebp+8) 1/r32/ecx
    35812     {
    35813 $find-matching-primitive:loop:
    35814       # if (curr == null) break
    35815       81 7/subop/compare %ecx 0/imm32
    35816       74/jump-if-= break/disp8
    35817       # if match(curr, stmt) return curr
    35818       {
    35819         (mu-stmt-matches-primitive? *(ebp+0xc) %ecx)  # => eax
    35820         3d/compare-eax-and 0/imm32/false
    35821         74/jump-if-= break/disp8
    35822         89/<- %eax 1/r32/ecx
    35823         eb/jump $find-matching-primitive:end/disp8
    35824       }
    35825 $find-matching-primitive:next-primitive:
    35826       # curr = curr->next
    35827       (lookup *(ecx+0x3c) *(ecx+0x40))  # Primitive-next Primitive-next => eax
    35828       89/<- %ecx 0/r32/eax
    35829       #
    35830       e9/jump loop/disp32
    35831     }
    35832     # return null
    35833     b8/copy-to-eax 0/imm32
    35834 $find-matching-primitive:end:
    35835     # . restore registers
    35836     59/pop-to-ecx
    35837     # . epilogue
    35838     89/<- %esp 5/r32/ebp
    35839     5d/pop-to-ebp
    35840     c3/return
    35841
    35842 mu-stmt-matches-primitive?:  # stmt: (addr stmt), primitive: (addr primitive) -> result/eax: boolean
    35843     # A mu stmt matches a primitive if the name matches, all the inout vars
    35844     # match, and all the output vars match.
    35845     # Vars match if types match and registers match.
    35846     # In addition, a stmt output matches a primitive's output if types match
    35847     # and the primitive has a wildcard register.
    35848     # . prologue
    35849     55/push-ebp
    35850     89/<- %ebp 4/r32/esp
    35851     # . save registers
    35852     51/push-ecx
    35853     52/push-edx
    35854     53/push-ebx
    35855     56/push-esi
    35856     57/push-edi
    35857     # ecx = stmt
    35858     8b/-> *(ebp+8) 1/r32/ecx
    35859     # edx = primitive
    35860     8b/-> *(ebp+0xc) 2/r32/edx
    35861     {
    35862 $mu-stmt-matches-primitive?:check-name:
    35863       # if (primitive->name != stmt->operation) return false
    35864       # . var esi: (addr array byte) = lookup(stmt->operation)
    35865       (lookup *(ecx+4) *(ecx+8))  # Stmt1-operation Stmt1-operation => eax
    35866       89/<- %esi 0/r32/eax
    35867       # . var edi: (addr array byte) = lookup(primitive->name)
    35868       (lookup *edx *(edx+4))  # Primitive-name Primitive-name => eax
    35869 #?       (write-buffered Stderr %eax)
    35870 #?       (write-buffered Stderr Newline)
    35871 #?       (flush Stderr)
    35872       89/<- %edi 0/r32/eax
    35873       (string-equal? %esi %edi)  # => eax
    35874       3d/compare-eax-and 0/imm32/false
    35875       75/jump-if-!= break/disp8
    35876       b8/copy-to-eax 0/imm32
    35877       e9/jump $mu-stmt-matches-primitive?:end/disp32
    35878     }
    35879     # var curr/esi: (addr stmt-var) = lookup(stmt->inouts)
    35880     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    35881     89/<- %esi 0/r32/eax
    35882     # var curr2/edi: (addr list var) = lookup(primitive->inouts)
    35883     (lookup *(edx+8) *(edx+0xc))  # Primitive-inouts Primitive-inouts => eax
    35884     89/<- %edi 0/r32/eax
    35885     {
    35886 $mu-stmt-matches-primitive?:inouts-loop:
    35887       # if (curr == 0 && curr2 == 0) move on to check outputs
    35888       {
    35889 $mu-stmt-matches-primitive?:check-both-inouts-null:
    35890         81 7/subop/compare %esi 0/imm32
    35891         75/jump-if-!= break/disp8
    35892 $mu-stmt-matches-primitive?:stmt-inout-null:
    35893         81 7/subop/compare %edi 0/imm32
    35894         0f 84/jump-if-= $mu-stmt-matches-primitive?:check-outputs/disp32
    35895 $mu-stmt-matches-primitive?:stmt-inout-null-and-prim-inout-not-null:
    35896         # return false
    35897         b8/copy-to-eax 0/imm32/false
    35898         e9/jump $mu-stmt-matches-primitive?:end/disp32
    35899       }
    35900       # if (curr2 == 0) return false
    35901       {
    35902 $mu-stmt-matches-primitive?:check-prim-inout-null:
    35903         81 7/subop/compare %edi 0/imm32
    35904         75/jump-if-!= break/disp8
    35905 $mu-stmt-matches-primitive?:prim-inout-null:
    35906         b8/copy-to-eax 0/imm32/false
    35907         e9/jump $mu-stmt-matches-primitive?:end/disp32
    35908       }
    35909       # if (curr != curr2) return false
    35910       {
    35911 $mu-stmt-matches-primitive?:check-inouts-match:
    35912         (lookup *edi *(edi+4))  # List-value List-value => eax
    35913         (operand-matches-primitive? %esi %eax)  # => eax
    35914         3d/compare-eax-and 0/imm32/false
    35915         75/jump-if-!= break/disp8
    35916 $mu-stmt-matches-primitive?:inouts-match:
    35917         b8/copy-to-eax 0/imm32/false
    35918         e9/jump $mu-stmt-matches-primitive?:end/disp32
    35919       }
    35920 $mu-stmt-matches-primitive?:next-inout:
    35921       # curr = lookup(curr->next)
    35922       (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
    35923       89/<- %esi 0/r32/eax
    35924       # curr2 = lookup(curr2->next)
    35925       (lookup *(edi+8) *(edi+0xc))  # List-next List-next => eax
    35926       89/<- %edi 0/r32/eax
    35927       #
    35928       e9/jump loop/disp32
    35929     }
    35930 $mu-stmt-matches-primitive?:check-outputs:
    35931     # var curr/esi: (addr stmt-var) = lookup(stmt->outputs)
    35932     (lookup *(ecx+0x14) *(ecx+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    35933     89/<- %esi 0/r32/eax
    35934     # var curr2/edi: (addr list var) = lookup(primitive->outputs)
    35935     (lookup *(edx+0x10) *(edx+0x14))  # Primitive-outputs Primitive-outputs => eax
    35936     89/<- %edi 0/r32/eax
    35937     {
    35938 $mu-stmt-matches-primitive?:outputs-loop:
    35939       # if (curr == 0) return (curr2 == 0)
    35940       {
    35941 $mu-stmt-matches-primitive?:check-both-outputs-null:
    35942         81 7/subop/compare %esi 0/imm32
    35943         75/jump-if-!= break/disp8
    35944         {
    35945 $mu-stmt-matches-primitive?:stmt-output-null:
    35946           81 7/subop/compare %edi 0/imm32
    35947           75/jump-if-!= break/disp8
    35948 $mu-stmt-matches-primitive?:both-outputs-null:
    35949           # return true
    35950           b8/copy-to-eax 1/imm32
    35951           e9/jump $mu-stmt-matches-primitive?:end/disp32
    35952         }
    35953 $mu-stmt-matches-primitive?:stmt-output-null-and-prim-output-not-null:
    35954         # return false
    35955         b8/copy-to-eax 0/imm32
    35956         e9/jump $mu-stmt-matches-primitive?:end/disp32
    35957       }
    35958       # if (curr2 == 0) return false
    35959       {
    35960 $mu-stmt-matches-primitive?:check-prim-output-null:
    35961         81 7/subop/compare %edi 0/imm32
    35962         75/jump-if-!= break/disp8
    35963 $mu-stmt-matches-primitive?:prim-output-is-null:
    35964         b8/copy-to-eax 0/imm32
    35965         e9/jump $mu-stmt-matches-primitive?:end/disp32
    35966       }
    35967       # if (curr != curr2) return false
    35968       {
    35969 $mu-stmt-matches-primitive?:check-outputs-match:
    35970         (lookup *edi *(edi+4))  # List-value List-value => eax
    35971         (operand-matches-primitive? %esi %eax)  # => eax
    35972         3d/compare-eax-and 0/imm32/false
    35973         75/jump-if-!= break/disp8
    35974 $mu-stmt-matches-primitive?:outputs-match:
    35975         b8/copy-to-eax 0/imm32
    35976         e9/jump $mu-stmt-matches-primitive?:end/disp32
    35977       }
    35978 $mu-stmt-matches-primitive?:next-output:
    35979       # curr = lookup(curr->next)
    35980       (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
    35981       89/<- %esi 0/r32/eax
    35982       # curr2 = lookup(curr2->next)
    35983       (lookup *(edi+8) *(edi+0xc))  # List-next List-next => eax
    35984       89/<- %edi 0/r32/eax
    35985       #
    35986       e9/jump loop/disp32
    35987     }
    35988 $mu-stmt-matches-primitive?:return-true:
    35989     b8/copy-to-eax 1/imm32
    35990 $mu-stmt-matches-primitive?:end:
    35991     # . restore registers
    35992     5f/pop-to-edi
    35993     5e/pop-to-esi
    35994     5b/pop-to-ebx
    35995     5a/pop-to-edx
    35996     59/pop-to-ecx
    35997     # . epilogue
    35998     89/<- %esp 5/r32/ebp
    35999     5d/pop-to-ebp
    36000     c3/return
    36001
    36002 operand-matches-primitive?:  # s: (addr stmt-var), prim-var: (addr var) -> result/eax: boolean
    36003     # . prologue
    36004     55/push-ebp
    36005     89/<- %ebp 4/r32/esp
    36006     # . save registers
    36007     51/push-ecx
    36008     52/push-edx
    36009     53/push-ebx
    36010     56/push-esi
    36011     57/push-edi
    36012     # ecx = s
    36013     8b/-> *(ebp+8) 1/r32/ecx
    36014     # var var/esi: (addr var) = lookup(s->value)
    36015     (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
    36016     89/<- %esi 0/r32/eax
    36017     # edi = prim-var
    36018     8b/-> *(ebp+0xc) 7/r32/edi
    36019 $operand-matches-primitive?:check-type:
    36020     # if !category-match?(var->type, prim-var->type) return false
    36021     # . var vtype/ebx: (addr type-tree) = lookup(var->type)
    36022     (lookup *(esi+8) *(esi+0xc))  # Var-type Var-type => eax
    36023     89/<- %ebx 0/r32/eax
    36024     # . if s is deref, vtype = vtype->right
    36025     {
    36026       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
    36027       74/jump-if-= break/disp8
    36028 $operand-matches-primitive?:is-deref:
    36029       # . var t/eax: (addr type)
    36030       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
    36031       # . if !t->is-atom? t = t->left
    36032       81 7/subop/compare *eax 0/imm32/false
    36033       {
    36034         75/jump-if-!= break/disp8
    36035         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    36036       }
    36037       # .
    36038       89/<- %ebx 0/r32/eax
    36039     }
    36040     # . var ptype/eax: (addr type-tree) = lookup(prim-var->type)
    36041     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
    36042     (subx-type-category-match? %ebx %eax)  # => eax
    36043     3d/compare-eax-and 0/imm32/false
    36044     0f 84/jump-if-= $operand-matches-primitive?:return-false/disp32
    36045     {
    36046 $operand-matches-primitive?:check-register:
    36047       # if prim-var is in memory and var is in register but dereference, match
    36048       {
    36049         81 7/subop/compare *(edi+0x18) 0/imm32  # Var-register
    36050         0f 85/jump-if-!= break/disp32
    36051         81 7/subop/compare *(esi+0x18) 0/imm32  # Var-register
    36052         74/jump-if-= break/disp8
    36053         81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
    36054         74/jump-if-= break/disp8
    36055 $operand-matches-primitive?:var-deref-match:
    36056         e9/jump $operand-matches-primitive?:return-true/disp32
    36057       }
    36058       # if prim-var is in register and var is in register but dereference, no match
    36059       {
    36060         81 7/subop/compare *(edi+0x18) 0/imm32  # Var-register
    36061         0f 84/jump-if-= break/disp32
    36062         81 7/subop/compare *(esi+0x18) 0/imm32  # Var-register
    36063         0f 84/jump-if-= break/disp32
    36064         81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
    36065         74/jump-if-= break/disp8
    36066 $operand-matches-primitive?:var-deref-no-match:
    36067         e9/jump $operand-matches-primitive?:return-false/disp32
    36068       }
    36069       # return false if var->register doesn't match prim-var->register
    36070       {
    36071         # if register addresses are equal, it's a match
    36072         # var vreg/ebx: (addr array byte) = lookup(var->register)
    36073         (lookup *(esi+0x18) *(esi+0x1c))  # Var-register Var-register => eax
    36074         89/<- %ebx 0/r32/eax
    36075         # var preg/ecx: (addr array byte) = lookup(prim-var->register)
    36076         (lookup *(edi+0x18) *(edi+0x1c))  # Var-register Var-register => eax
    36077         89/<- %ecx 0/r32/eax
    36078         # if (vreg == preg) break
    36079         39/compare %ecx 3/r32/ebx
    36080         74/jump-if-= break/disp8
    36081 $operand-matches-primitive?:var-register-no-match:
    36082         # if either address is 0, return false
    36083         81 7/subop/compare %ebx 0/imm32
    36084         74/jump-if-=  $operand-matches-primitive?:return-false/disp8
    36085         81 7/subop/compare %ecx 0/imm32
    36086         74/jump-if-=  $operand-matches-primitive?:return-false/disp8
    36087         # if prim-var->register is wildcard, it's a match
    36088         (string-equal? %ecx "*")  # Any-register => eax
    36089         3d/compare-eax-and 0/imm32/false
    36090         75/jump-if-!= break/disp8
    36091 $operand-matches-primitive?:wildcard-no-match:
    36092         # if string contents aren't equal, return false
    36093         (string-equal? %ecx %ebx)  # => eax
    36094         3d/compare-eax-and 0/imm32/false
    36095         74/jump-if-= $operand-matches-primitive?:return-false/disp8
    36096       }
    36097     }
    36098 $operand-matches-primitive?:return-true:
    36099     b8/copy-to-eax 1/imm32/true
    36100     eb/jump $operand-matches-primitive?:end/disp8
    36101 $operand-matches-primitive?:return-false:
    36102     b8/copy-to-eax 0/imm32/false
    36103 $operand-matches-primitive?:end:
    36104     # . restore registers
    36105     5f/pop-to-edi
    36106     5e/pop-to-esi
    36107     5b/pop-to-ebx
    36108     5a/pop-to-edx
    36109     59/pop-to-ecx
    36110     # . epilogue
    36111     89/<- %esp 5/r32/ebp
    36112     5d/pop-to-ebp
    36113     c3/return
    36114
    36115 find-matching-function:  # functions: (addr function), stmt: (addr stmt) -> result/eax: (addr function)
    36116     # . prologue
    36117     55/push-ebp
    36118     89/<- %ebp 4/r32/esp
    36119     # . save registers
    36120     51/push-ecx
    36121     # var curr/ecx: (handle function) = functions
    36122     8b/-> *(ebp+8) 1/r32/ecx
    36123     {
    36124       # if (curr == null) break
    36125       81 7/subop/compare %ecx 0/imm32
    36126       74/jump-if-= break/disp8
    36127 #?       (write-buffered Stderr "iter\n")
    36128 #?       (flush Stderr)
    36129       # if match(stmt, curr) return curr
    36130       {
    36131         (mu-stmt-matches-function? *(ebp+0xc) %ecx)  # => eax
    36132         3d/compare-eax-and 0/imm32/false
    36133         74/jump-if-= break/disp8
    36134         89/<- %eax 1/r32/ecx
    36135         eb/jump $find-matching-function:end/disp8
    36136       }
    36137       # curr = curr->next
    36138       (lookup *(ecx+0x20) *(ecx+0x24))  # Function-next Function-next => eax
    36139       89/<- %ecx 0/r32/eax
    36140       #
    36141       eb/jump loop/disp8
    36142     }
    36143     # return null
    36144     b8/copy-to-eax 0/imm32
    36145 $find-matching-function:end:
    36146     # . restore registers
    36147     59/pop-to-ecx
    36148     # . epilogue
    36149     89/<- %esp 5/r32/ebp
    36150     5d/pop-to-ebp
    36151     c3/return
    36152
    36153 # Just compare names; user-defined functions don't support overloading yet.
    36154 mu-stmt-matches-function?:  # stmt: (addr stmt1), function: (addr function) -> result/eax: boolean
    36155     # . prologue
    36156     55/push-ebp
    36157     89/<- %ebp 4/r32/esp
    36158     # . save registers
    36159     51/push-ecx
    36160     # return function->name == stmt->operation
    36161     # ecx = lookup(stmt->operation)
    36162     8b/-> *(ebp+8) 0/r32/eax
    36163     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
    36164     89/<- %ecx 0/r32/eax
    36165     # eax = lookup(function->name)
    36166     8b/-> *(ebp+0xc) 0/r32/eax
    36167     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    36168     (string-equal? %eax %ecx)  # => eax
    36169 $mu-stmt-matches-function?:end:
    36170     # . restore registers
    36171     59/pop-to-ecx
    36172     # . epilogue
    36173     89/<- %esp 5/r32/ebp
    36174     5d/pop-to-ebp
    36175     c3/return
    36176
    36177 # Type-checking happens elsewhere. This method is for selecting between
    36178 # primitives.
    36179 subx-type-category-match?:  # a: (addr type-tree), b: (addr type-tree) -> result/eax: boolean
    36180     # . prologue
    36181     55/push-ebp
    36182     89/<- %ebp 4/r32/esp
    36183     # . save registers
    36184     51/push-ecx
    36185     # var cata/ecx: int = type-category(a)
    36186     (type-category *(ebp+8))  # => eax
    36187     89/<- %ecx 0/r32/eax
    36188     # var catb/eax: int = type-category(b)
    36189     (type-category *(ebp+0xc))  # => eax
    36190     # return cata == catb
    36191     39/compare %eax 1/r32/ecx
    36192     0f 94/set-byte-if-= %al
    36193     25/and-eax-with 0xff/imm32
    36194 $subx-type-category-match?:end:
    36195     # . restore registers
    36196     59/pop-to-ecx
    36197     # . epilogue
    36198     89/<- %esp 5/r32/ebp
    36199     5d/pop-to-ebp
    36200     c3/return
    36201
    36202 type-category:  # a: (addr type-tree) -> result/eax: int
    36203     # . prologue
    36204     55/push-ebp
    36205     89/<- %ebp 4/r32/esp
    36206     # . save registers
    36207     51/push-ecx
    36208     # var lit?/ecx: boolean = literal-type?(a)
    36209     (simple-mu-type? *(ebp+8) 0)  # literal => eax
    36210     89/<- %ecx 0/r32/eax
    36211     # var float?/eax: int = float?(a)
    36212     (simple-mu-type? *(ebp+8) 0xf)  # => eax
    36213     # set bits for lit? and float?
    36214     c1/shift 4/subop/left %ecx 1/imm8
    36215     09/or %eax 1/r32/ecx
    36216 $type-category:end:
    36217     # . restore registers
    36218     59/pop-to-ecx
    36219     # . epilogue
    36220     89/<- %esp 5/r32/ebp
    36221     5d/pop-to-ebp
    36222     c3/return
    36223
    36224 simple-mu-type?:  # a: (addr type-tree), n: type-id -> result/eax: boolean
    36225     # . prologue
    36226     55/push-ebp
    36227     89/<- %ebp 4/r32/esp
    36228     # . save registers
    36229     51/push-ecx
    36230     # ecx = n
    36231     8b/-> *(ebp+0xc) 1/r32/ecx
    36232     # return (a->value == n)
    36233     8b/-> *(ebp+8) 0/r32/eax
    36234     39/compare *(eax+4) 1/r32/ecx  # Type-tree-value
    36235     0f 94/set-byte-if-= %al
    36236     25/and-eax-with 0xff/imm32
    36237 $simple-mu-type?:end:
    36238     # . restore registers
    36239     59/pop-to-ecx
    36240     # . epilogue
    36241     89/<- %esp 5/r32/ebp
    36242     5d/pop-to-ebp
    36243     c3/return
    36244
    36245 mu-addr-type?:  # a: (addr type-tree) -> result/eax: boolean
    36246     # . prologue
    36247     55/push-ebp
    36248     89/<- %ebp 4/r32/esp
    36249     # eax = a
    36250     8b/-> *(ebp+8) 0/r32/eax
    36251     # if (!a->is-atom?) a = a->left
    36252     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
    36253     {
    36254       75/jump-if-!= break/disp8
    36255       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    36256     }
    36257     # return (a->value == addr)
    36258     81 7/subop/compare *(eax+4) 2/imm32/addr  # Type-tree-value
    36259     0f 94/set-byte-if-= %al
    36260     25/and-eax-with 0xff/imm32
    36261 $mu-addr-type?:end:
    36262     # . epilogue
    36263     89/<- %esp 5/r32/ebp
    36264     5d/pop-to-ebp
    36265     c3/return
    36266
    36267 mu-array-type?:  # a: (addr type-tree) -> result/eax: boolean
    36268     # . prologue
    36269     55/push-ebp
    36270     89/<- %ebp 4/r32/esp
    36271     # eax = a
    36272     8b/-> *(ebp+8) 0/r32/eax
    36273     # if (!a->is-atom?) a = a->left
    36274     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
    36275     {
    36276       75/jump-if-!= break/disp8
    36277       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    36278     }
    36279     # return (a->value == array)
    36280     81 7/subop/compare *(eax+4) 3/imm32/array  # Type-tree-value
    36281     0f 94/set-byte-if-= %al
    36282     25/and-eax-with 0xff/imm32
    36283 $mu-array-type?:end:
    36284     # . epilogue
    36285     89/<- %esp 5/r32/ebp
    36286     5d/pop-to-ebp
    36287     c3/return
    36288
    36289 mu-string-type?:  # a: (addr type-tree) -> result/eax: boolean
    36290     # . prologue
    36291     55/push-ebp
    36292     89/<- %ebp 4/r32/esp
    36293     # . save registers
    36294     56/push-esi
    36295     # esi = a
    36296     8b/-> *(ebp+8) 6/r32/esi
    36297     # if (a->is-atom?) return false
    36298     81 7/subop/compare *esi 0/imm32/false  # Type-tree-is-atom
    36299     0f 85/jump-if-!= $mu-string-type?:return-false/disp32
    36300     # if a is not an addr, return false
    36301     (mu-addr-type? %esi)  # => eax
    36302     3d/compare-eax-with 0/imm32/false
    36303     0f 84/jump-if-= $mu-string-type?:end/disp32  # eax changes var
    36304     # if a is not an array, return false
    36305     (lookup *(esi+0xc) *(esi+0x10))  # Type-tree-right Type-tree-right => eax
    36306     (mu-array-type? %eax)  # => eax
    36307     3d/compare-eax-with 0/imm32/false
    36308     74/jump-if-= $mu-string-type?:end/disp8  # eax changes var
    36309     # var p/eax: (addr type-tree) = payload of a
    36310     (lookup *(esi+0xc) *(esi+0x10))  # Type-tree-right Type-tree-right => eax
    36311     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
    36312     # if p is an atom, return false
    36313     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
    36314     75/jump-if-!= $mu-string-type?:return-false/disp8
    36315     # return (p == byte)
    36316     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    36317     (simple-mu-type? %eax 8)  # byte => eax
    36318     eb/jump $mu-string-type?:end/disp8
    36319 $mu-string-type?:return-false:
    36320     b8/copy-to-eax 0/imm32/false
    36321 $mu-string-type?:end:
    36322     # . restore registers
    36323     5e/pop-to-esi
    36324     # . epilogue
    36325     89/<- %esp 5/r32/ebp
    36326     5d/pop-to-ebp
    36327     c3/return
    36328
    36329 mu-stream-type?:  # a: (addr type-tree) -> result/eax: boolean
    36330     # . prologue
    36331     55/push-ebp
    36332     89/<- %ebp 4/r32/esp
    36333     # eax = a
    36334     8b/-> *(ebp+8) 0/r32/eax
    36335     # if (!a->is-atom?) a = a->left
    36336     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
    36337     {
    36338       75/jump-if-!= break/disp8
    36339       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    36340     }
    36341     # return (a->value == stream)
    36342     81 7/subop/compare *(eax+4) 0xb/imm32/stream  # Type-tree-value
    36343     0f 94/set-byte-if-= %al
    36344     25/and-eax-with 0xff/imm32
    36345 $mu-stream-type?:end:
    36346     # . epilogue
    36347     89/<- %esp 5/r32/ebp
    36348     5d/pop-to-ebp
    36349     c3/return
    36350
    36351 test-emit-subx-stmt-primitive:
    36352     # Primitive operation on a variable on the stack.
    36353     #   increment foo
    36354     # =>
    36355     #   ff 0/subop/increment *(ebp-8)
    36356     #
    36357     # There's a variable on the var stack as follows:
    36358     #   name: 'foo'
    36359     #   type: int
    36360     #   stack-offset: -8
    36361     #
    36362     # There's a primitive with this info:
    36363     #   name: 'increment'
    36364     #   inouts: int/mem
    36365     #   value: 'ff 0/subop/increment'
    36366     #
    36367     # . prologue
    36368     55/push-ebp
    36369     89/<- %ebp 4/r32/esp
    36370     # setup
    36371     (clear-stream _test-output-stream)
    36372     (clear-stream $_test-output-buffered-file->buffer)
    36373     # simulate allocated payloads starting with an initial fake alloc-id (0x11)
    36374 $test-emit-subx-stmt-primitive:initialize-type:
    36375     # var type/ecx: (payload type-tree) = int
    36376     68/push 0/imm32/right:null
    36377     68/push 0/imm32/right:null
    36378     68/push 0/imm32/left:unused
    36379     68/push 1/imm32/value:int
    36380     68/push 1/imm32/is-atom?:true
    36381     68/push 0x11/imm32/alloc-id:fake:payload
    36382     89/<- %ecx 4/r32/esp
    36383 $test-emit-subx-stmt-primitive:initialize-var:
    36384     # var var-foo/ecx: (payload var) = var(type)
    36385     68/push 0/imm32/no-register
    36386     68/push 0/imm32/no-register
    36387     68/push -8/imm32/stack-offset
    36388     68/push 1/imm32/block-depth
    36389     51/push-ecx/type
    36390     68/push 0x11/imm32/alloc-id:fake
    36391     68/push 0/imm32/name
    36392     68/push 0/imm32/name
    36393     68/push 0x11/imm32/alloc-id:fake:payload
    36394     89/<- %ecx 4/r32/esp
    36395 $test-emit-subx-stmt-primitive:initialize-var-name:
    36396     # var-foo->name = "foo"
    36397     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
    36398     (copy-array Heap "foo" %eax)
    36399 $test-emit-subx-stmt-primitive:initialize-stmt-var:
    36400     # var operand/ebx: (payload stmt-var) = stmt-var(var-foo)
    36401     68/push 0/imm32/is-deref:false
    36402     68/push 0/imm32/next
    36403     68/push 0/imm32/next
    36404     51/push-ecx/var-foo
    36405     68/push 0x11/imm32/alloc-id:fake
    36406     68/push 0x11/imm32/alloc-id:fake:payload
    36407     89/<- %ebx 4/r32/esp
    36408 $test-emit-subx-stmt-primitive:initialize-stmt:
    36409     # var stmt/esi: (addr statement)
    36410     68/push 0/imm32/no-outputs
    36411     68/push 0/imm32/no-outputs
    36412     53/push-ebx/inouts
    36413     68/push 0x11/imm32/alloc-id:fake
    36414     68/push 0/imm32/operation
    36415     68/push 0/imm32/operation
    36416     68/push 1/imm32/tag
    36417     89/<- %esi 4/r32/esp
    36418 $test-emit-subx-stmt-primitive:initialize-stmt-operation:
    36419     # stmt->operation = "increment"
    36420     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
    36421     (copy-array Heap "increment" %eax)
    36422 $test-emit-subx-stmt-primitive:initialize-primitive:
    36423     # var primitives/ebx: (addr primitive)
    36424     68/push 0/imm32/next
    36425     68/push 0/imm32/next
    36426     68/push 0/imm32/no-x32
    36427     68/push 0/imm32/no-xm32
    36428     68/push 0/imm32/no-disp32
    36429     68/push 0/imm32/no-imm8
    36430     68/push 0/imm32/no-imm32
    36431     68/push 0/imm32/no-r32
    36432     68/push 1/imm32/rm32-is-first-inout
    36433     68/push 0/imm32/subx-name
    36434     68/push 0/imm32/subx-name
    36435     68/push 0/imm32/no-outputs
    36436     68/push 0/imm32/no-outputs
    36437     53/push-ebx/inouts  # hack: reuse stmt-var from call stmt as (list var) in function declaration
    36438     68/push 0x11/imm32/alloc-id:fake
    36439     68/push 0/imm32/name
    36440     68/push 0/imm32/name
    36441     89/<- %ebx 4/r32/esp
    36442 $test-emit-subx-stmt-primitive:initialize-primitive-name:
    36443     # primitives->name = "increment"
    36444     (copy-array Heap "increment" %ebx)  # Primitive-name
    36445 $test-emit-subx-stmt-primitive:initialize-primitive-subx-name:
    36446     # primitives->subx-name = "ff 0/subop/increment"
    36447     8d/copy-address *(ebx+0x18) 0/r32/eax  # Primitive-subx-name
    36448     (copy-array Heap "ff 0/subop/increment" %eax)
    36449     # convert
    36450     c7 0/subop/copy *Curr-block-depth 0/imm32
    36451     (emit-subx-stmt _test-output-buffered-file %esi %ebx 0 Stderr 0)
    36452     (flush _test-output-buffered-file)
    36453 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
    36459     # check output
    36460     (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment *(ebp+0xfffffff8)" "F - test-emit-subx-stmt-primitive")
    36461     # . epilogue
    36462     89/<- %esp 5/r32/ebp
    36463     5d/pop-to-ebp
    36464     c3/return
    36465
    36466 test-emit-subx-stmt-primitive-register:
    36467     # Primitive operation on a variable in a register.
    36468     #   foo <- increment
    36469     # =>
    36470     #   ff 0/subop/increment %eax  # sub-optimal, but should suffice
    36471     #
    36472     # There's a variable on the var stack as follows:
    36473     #   name: 'foo'
    36474     #   type: int
    36475     #   register: 'eax'
    36476     #
    36477     # There's a primitive with this info:
    36478     #   name: 'increment'
    36479     #   out: int/reg
    36480     #   value: 'ff 0/subop/increment'
    36481     #
    36482     # . prologue
    36483     55/push-ebp
    36484     89/<- %ebp 4/r32/esp
    36485     # setup
    36486     (clear-stream _test-output-stream)
    36487     (clear-stream $_test-output-buffered-file->buffer)
    36488 $test-emit-subx-stmt-primitive-register:initialize-type:
    36489     # var type/ecx: (payload type-tree) = int
    36490     68/push 0/imm32/right:null
    36491     68/push 0/imm32/right:null
    36492     68/push 0/imm32/left:unused
    36493     68/push 1/imm32/value:int
    36494     68/push 1/imm32/is-atom?:true
    36495     68/push 0x11/imm32/alloc-id:fake:payload
    36496     89/<- %ecx 4/r32/esp
    36497 $test-emit-subx-stmt-primitive-register:initialize-var:
    36498     # var var-foo/ecx: (payload var)
    36499     68/push 0/imm32/register
    36500     68/push 0/imm32/register
    36501     68/push 0/imm32/no-stack-offset
    36502     68/push 1/imm32/block-depth
    36503     51/push-ecx
    36504     68/push 0x11/imm32/alloc-id:fake
    36505     68/push 0/imm32/name
    36506     68/push 0/imm32/name
    36507     68/push 0x11/imm32/alloc-id:fake:payload
    36508     89/<- %ecx 4/r32/esp
    36509 $test-emit-subx-stmt-primitive-register:initialize-var-name:
    36510     # var-foo->name = "foo"
    36511     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
    36512     (copy-array Heap "foo" %eax)
    36513 $test-emit-subx-stmt-primitive-register:initialize-var-register:
    36514     # var-foo->register = "eax"
    36515     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
    36516     (copy-array Heap "eax" %eax)
    36517 $test-emit-subx-stmt-primitive-register:initialize-stmt-var:
    36518     # var operand/ebx: (payload stmt-var)
    36519     68/push 0/imm32/is-deref:false
    36520     68/push 0/imm32/next
    36521     68/push 0/imm32/next
    36522     51/push-ecx/var-foo
    36523     68/push 0x11/imm32/alloc-id:fake
    36524     68/push 0x11/imm32/alloc-id:fake:payload
    36525     89/<- %ebx 4/r32/esp
    36526 $test-emit-subx-stmt-primitive-register:initialize-stmt:
    36527     # var stmt/esi: (addr statement)
    36528     53/push-ebx/outputs
    36529     68/push 0x11/imm32/alloc-id:fake
    36530     68/push 0/imm32/no-inouts
    36531     68/push 0/imm32/no-inouts
    36532     68/push 0/imm32/operation
    36533     68/push 0/imm32/operation
    36534     68/push 1/imm32
    36535     89/<- %esi 4/r32/esp
    36536 $test-emit-subx-stmt-primitive-register:initialize-stmt-operation:
    36537     # stmt->operation = "increment"
    36538     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
    36539     (copy-array Heap "increment" %eax)
    36540 $test-emit-subx-stmt-primitive-register:initialize-formal-var:
    36541     # var formal-var/ebx: (payload var)
    36542     68/push 0/imm32/register
    36543     68/push 0/imm32/register
    36544     68/push 0/imm32/no-stack-offset
    36545     68/push 1/imm32/block-depth
    36546     ff 6/subop/push *(ecx+0x10)  # Var-type + payload alloc id + handle alloc id
    36547     68/push 0x11/imm32/alloc-id:fake
    36548     68/push 0/imm32/name
    36549     68/push 0/imm32/name
    36550     68/push 0x11/imm32/alloc-id:fake:payload
    36551     89/<- %ebx 4/r32/esp
    36552 $test-emit-subx-stmt-primitive-register:initialize-formal-var-name:
    36553     # formal-var->name = "dummy"
    36554     8d/copy-address *(ebx+4) 0/r32/eax  # Var-name + 4
    36555     (copy-array Heap "dummy" %eax)
    36556 $test-emit-subx-stmt-primitive-register:initialize-formal-register:
    36557     # formal-var->register = "*"
    36558     8d/copy-address *(ebx+0x1c) 0/r32/eax  # Var-register + 4
    36559     (copy-array Heap "*" %eax)  # Any-register
    36560 $test-emit-subx-stmt-primitive-register:initialize-var-list:
    36561     # var formal-outputs/ebx: (payload list var)
    36562     68/push 0/imm32/next
    36563     68/push 0/imm32/next
    36564     53/push-ebx/formal-var
    36565     68/push 0x11/imm32/alloc-id:fake
    36566     68/push 0x11/imm32/alloc-id:fake:payload
    36567     89/<- %ebx 4/r32/esp
    36568 $test-emit-subx-stmt-primitive-register:initialize-primitive:
    36569     # var primitives/ebx: (addr primitive)
    36570     68/push 0/imm32/next
    36571     68/push 0/imm32/next
    36572     68/push 0/imm32/no-x32
    36573     68/push 0/imm32/no-xm32
    36574     68/push 0/imm32/no-disp32
    36575     68/push 0/imm32/no-imm8
    36576     68/push 0/imm32/no-imm32
    36577     68/push 0/imm32/no-r32
    36578     68/push 3/imm32/rm32-is-first-output
    36579     68/push 0/imm32/subx-name
    36580     68/push 0/imm32/subx-name
    36581     53/push-ebx/outputs
    36582     68/push 0x11/imm32/alloc-id:fake
    36583     68/push 0/imm32/no-inouts
    36584     68/push 0/imm32/no-inouts
    36585     68/push 0/imm32/name
    36586     68/push 0/imm32/name
    36587     89/<- %ebx 4/r32/esp
    36588 $test-emit-subx-stmt-primitive-register:initialize-primitive-name:
    36589     # primitives->name = "increment"
    36590     (copy-array Heap "increment" %ebx)  # Primitive-name
    36591 $test-emit-subx-stmt-primitive-register:initialize-primitive-subx-name:
    36592     # primitives->subx-name = "ff 0/subop/increment"
    36593     8d/copy-address *(ebx+0x18) 0/r32/eax  # Primitive-subx-name
    36594     (copy-array Heap "ff 0/subop/increment" %eax)
    36595     # convert
    36596     c7 0/subop/copy *Curr-block-depth 0/imm32
    36597     (emit-subx-stmt _test-output-buffered-file %esi %ebx 0 Stderr 0)
    36598     (flush _test-output-buffered-file)
    36599 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
    36605     # check output
    36606     (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-stmt-primitive-register")
    36607     # . epilogue
    36608     89/<- %esp 5/r32/ebp
    36609     5d/pop-to-ebp
    36610     c3/return
    36611
    36612 test-emit-subx-stmt-select-primitive:
    36613     # Select the right primitive between overloads.
    36614     #   foo <- increment
    36615     # =>
    36616     #   ff 0/subop/increment %eax  # sub-optimal, but should suffice
    36617     #
    36618     # There's a variable on the var stack as follows:
    36619     #   name: 'foo'
    36620     #   type: int
    36621     #   register: 'eax'
    36622     #
    36623     # There's two primitives, as follows:
    36624     #   - name: 'increment'
    36625     #     out: int/reg
    36626     #     value: 'ff 0/subop/increment'
    36627     #   - name: 'increment'
    36628     #     inout: int/mem
    36629     #     value: 'ff 0/subop/increment'
    36630     #
    36631     # . prologue
    36632     55/push-ebp
    36633     89/<- %ebp 4/r32/esp
    36634     # setup
    36635     (clear-stream _test-output-stream)
    36636     (clear-stream $_test-output-buffered-file->buffer)
    36637 $test-emit-subx-stmt-select-primitive:initialize-type:
    36638     # var type/ecx: (payload type-tree) = int
    36639     68/push 0/imm32/right:null
    36640     68/push 0/imm32/right:null
    36641     68/push 0/imm32/left:unused
    36642     68/push 1/imm32/value:int
    36643     68/push 1/imm32/is-atom?:true
    36644     68/push 0x11/imm32/alloc-id:fake:payload
    36645     89/<- %ecx 4/r32/esp
    36646 $test-emit-subx-stmt-select-primitive:initialize-var:
    36647     # var var-foo/ecx: (payload var)
    36648     68/push 0/imm32/register
    36649     68/push 0/imm32/register
    36650     68/push 0/imm32/no-stack-offset
    36651     68/push 1/imm32/block-depth
    36652     51/push-ecx
    36653     68/push 0x11/imm32/alloc-id:fake
    36654     68/push 0/imm32/name
    36655     68/push 0/imm32/name
    36656     68/push 0x11/imm32/alloc-id:fake:payload
    36657     89/<- %ecx 4/r32/esp
    36658 $test-emit-subx-stmt-select-primitive:initialize-var-name:
    36659     # var-foo->name = "foo"
    36660     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
    36661     (copy-array Heap "foo" %eax)
    36662 $test-emit-subx-stmt-select-primitive:initialize-var-register:
    36663     # var-foo->register = "eax"
    36664     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
    36665     (copy-array Heap "eax" %eax)
    36666 $test-emit-subx-stmt-select-primitive:initialize-stmt-var:
    36667     # var operand/ebx: (payload stmt-var)
    36668     68/push 0/imm32/is-deref:false
    36669     68/push 0/imm32/next
    36670     68/push 0/imm32/next
    36671     51/push-ecx/var-foo
    36672     68/push 0x11/imm32/alloc-id:fake
    36673     68/push 0x11/imm32/alloc-id:fake:payload
    36674     89/<- %ebx 4/r32/esp
    36675 $test-emit-subx-stmt-select-primitive:initialize-stmt:
    36676     # var stmt/esi: (addr statement)
    36677     53/push-ebx/outputs
    36678     68/push 0x11/imm32/alloc-id:fake
    36679     68/push 0/imm32/no-inouts
    36680     68/push 0/imm32/no-inouts
    36681     68/push 0/imm32/operation
    36682     68/push 0/imm32/operation
    36683     68/push 1/imm32
    36684     89/<- %esi 4/r32/esp
    36685 $test-emit-subx-stmt-select-primitive:initialize-stmt-operation:
    36686     # stmt->operation = "increment"
    36687     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
    36688     (copy-array Heap "increment" %eax)
    36689 $test-emit-subx-stmt-select-primitive:initialize-formal-var:
    36690     # var formal-var/ebx: (payload var)
    36691     68/push 0/imm32/register
    36692     68/push 0/imm32/register
    36693     68/push 0/imm32/no-stack-offset
    36694     68/push 1/imm32/block-depth
    36695     ff 6/subop/push *(ecx+0x10)  # Var-type + payload alloc id + handle alloc id
    36696     68/push 0x11/imm32/alloc-id:fake
    36697     68/push 0/imm32/name
    36698     68/push 0/imm32/name
    36699     68/push 0x11/imm32/alloc-id:fake:payload
    36700     89/<- %ebx 4/r32/esp
    36701 $test-emit-subx-stmt-select-primitive:initialize-formal-var-name:
    36702     # formal-var->name = "dummy"
    36703     8d/copy-address *(ebx+4) 0/r32/eax  # Var-name + 4
    36704     (copy-array Heap "dummy" %eax)
    36705 $test-emit-subx-stmt-select-primitive:initialize-formal-register:
    36706     # formal-var->register = "*"
    36707     8d/copy-address *(ebx+0x1c) 0/r32/eax  # Var-register + 4
    36708     (copy-array Heap "*" %eax)  # Any-register
    36709 $test-emit-subx-stmt-select-primitive:initialize-var-list:
    36710     # var formal-outputs/ebx: (payload list var)
    36711     68/push 0/imm32/next
    36712     68/push 0/imm32/next
    36713     53/push-ebx/formal-var
    36714     68/push 0x11/imm32/alloc-id:fake
    36715     68/push 0x11/imm32/alloc-id:fake:payload
    36716     89/<- %ebx 4/r32/esp
    36717 $test-emit-subx-stmt-select-primitive:initialize-primitive2:
    36718     # var primitive2/edi: (payload primitive)
    36719     68/push 0/imm32/next
    36720     68/push 0/imm32/next
    36721     68/push 0/imm32/no-x32
    36722     68/push 0/imm32/no-xm32
    36723     68/push 0/imm32/no-disp32
    36724     68/push 0/imm32/no-imm8
    36725     68/push 0/imm32/no-imm32
    36726     68/push 0/imm32/no-r32
    36727     68/push 3/imm32/rm32-is-first-output
    36728     68/push 0/imm32/subx-name
    36729     68/push 0/imm32/subx-name
    36730     53/push-ebx/outputs
    36731     68/push 0x11/imm32/alloc-id:fake
    36732     68/push 0/imm32/no-inouts
    36733     68/push 0/imm32/no-inouts
    36734     68/push 0/imm32/name
    36735     68/push 0/imm32/name
    36736     68/push 0x11/imm32/alloc-id:fake:payload
    36737     89/<- %edi 4/r32/esp
    36738 $test-emit-subx-stmt-select-primitive:initialize-primitive2-name:
    36739     # primitives->name = "increment"
    36740     8d/copy-address *(edi+4) 0/r32/eax  # Primitive-name + 4
    36741     (copy-array Heap "increment" %eax)
    36742 $test-emit-subx-stmt-select-primitive:initialize-primitive2-subx-name:
    36743     # primitives->subx-name = "ff 0/subop/increment"
    36744     8d/copy-address *(edi+0x1c) 0/r32/eax  # Primitive-subx-name + 4
    36745     (copy-array Heap "ff 0/subop/increment" %eax)
    36746 $test-emit-subx-stmt-select-primitive:initialize-primitive:
    36747     # var primitives/ebx: (addr primitive)
    36748     57/push-edi
    36749     68/push 0x11/imm32/alloc-id:fake
    36750     68/push 0/imm32/no-x32
    36751     68/push 0/imm32/no-xm32
    36752     68/push 0/imm32/no-disp32
    36753     68/push 0/imm32/no-imm8
    36754     68/push 0/imm32/no-imm32
    36755     68/push 0/imm32/no-r32
    36756     68/push 1/imm32/rm32-is-first-inout
    36757     68/push 0/imm32/subx-name
    36758     68/push 0/imm32/subx-name
    36759     68/push 0/imm32/no-outputs
    36760     68/push 0/imm32/no-outputs
    36761     53/push-ebx/inouts  # hack: reuse stmt-var from call stmt as (list var) in function declaration
    36762     68/push 0x11/imm32/alloc-id:fake
    36763     68/push 0/imm32/name
    36764     68/push 0/imm32/name
    36765     89/<- %ebx 4/r32/esp
    36766 $test-emit-subx-stmt-select-primitive:initialize-primitive-name:
    36767     # primitives->name = "increment"
    36768     (copy-array Heap "increment" %ebx)  # Primitive-name
    36769 $test-emit-subx-stmt-select-primitive:initialize-primitive-subx-name:
    36770     # primitives->subx-name = "ff 0/subop/increment"
    36771     8d/copy-address *(ebx+0x18) 0/r32/eax  # Primitive-subx-name
    36772     (copy-array Heap "ff 0/subop/increment" %eax)
    36773     # convert
    36774     c7 0/subop/copy *Curr-block-depth 0/imm32
    36775     (emit-subx-stmt _test-output-buffered-file %esi %ebx 0 Stderr 0)
    36776     (flush _test-output-buffered-file)
    36777 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
    36783     # check output
    36784     (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-stmt-select-primitive")
    36785     # . epilogue
    36786     89/<- %esp 5/r32/ebp
    36787     5d/pop-to-ebp
    36788     c3/return
    36789
    36790 test-emit-subx-stmt-select-primitive-2:
    36791     # Select the right primitive between overloads.
    36792     #   increment foo
    36793     # =>
    36794     #   ff 0/subop/increment %eax  # sub-optimal, but should suffice
    36795     #
    36796     # There's a variable on the var stack as follows:
    36797     #   name: 'foo'
    36798     #   type: int
    36799     #   register: 'eax'
    36800     #
    36801     # There's two primitives, as follows:
    36802     #   - name: 'increment'
    36803     #     out: int/reg
    36804     #     value: 'ff 0/subop/increment'
    36805     #   - name: 'increment'
    36806     #     inout: int/mem
    36807     #     value: 'ff 0/subop/increment'
    36808     #
    36809     # . prologue
    36810     55/push-ebp
    36811     89/<- %ebp 4/r32/esp
    36812     # setup
    36813     (clear-stream _test-output-stream)
    36814     (clear-stream $_test-output-buffered-file->buffer)
    36815 $test-emit-subx-stmt-select-primitive-2:initialize-type:
    36816     # var type/ecx: (payload type-tree) = int
    36817     68/push 0/imm32/right:null
    36818     68/push 0/imm32/right:null
    36819     68/push 0/imm32/left:unused
    36820     68/push 1/imm32/value:int
    36821     68/push 1/imm32/is-atom?:true
    36822     68/push 0x11/imm32/alloc-id:fake:payload
    36823     89/<- %ecx 4/r32/esp
    36824 $test-emit-subx-stmt-select-primitive-2:initialize-var:
    36825     # var var-foo/ecx: (payload var)
    36826     68/push 0/imm32/register
    36827     68/push 0/imm32/register
    36828     68/push 0/imm32/no-stack-offset
    36829     68/push 1/imm32/block-depth
    36830     51/push-ecx
    36831     68/push 0x11/imm32/alloc-id:fake
    36832     68/push 0/imm32/name
    36833     68/push 0/imm32/name
    36834     68/push 0x11/imm32/alloc-id:fake:payload
    36835     89/<- %ecx 4/r32/esp
    36836 $test-emit-subx-stmt-select-primitive-2:initialize-var-name:
    36837     # var-foo->name = "foo"
    36838     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
    36839     (copy-array Heap "foo" %eax)
    36840 $test-emit-subx-stmt-select-primitive-2:initialize-var-register:
    36841     # var-foo->register = "eax"
    36842     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
    36843     (copy-array Heap "eax" %eax)
    36844 $test-emit-subx-stmt-select-primitive-2:initialize-stmt-var:
    36845     # var operand/ebx: (payload stmt-var)
    36846     68/push 0/imm32/is-deref:false
    36847     68/push 0/imm32/next
    36848     68/push 0/imm32/next
    36849     51/push-ecx/var-foo
    36850     68/push 0x11/imm32/alloc-id:fake
    36851     68/push 0x11/imm32/alloc-id:fake:payload
    36852     89/<- %ebx 4/r32/esp
    36853 $test-emit-subx-stmt-select-primitive-2:initialize-stmt:
    36854     # var stmt/esi: (addr statement)
    36855     68/push 0/imm32/no-outputs
    36856     68/push 0/imm32/no-outputs
    36857     53/push-ebx/inouts
    36858     68/push 0x11/imm32/alloc-id:fake
    36859     68/push 0/imm32/operation
    36860     68/push 0/imm32/operation
    36861     68/push 1/imm32
    36862     89/<- %esi 4/r32/esp
    36863 $test-emit-subx-stmt-select-primitive-2:initialize-stmt-operation:
    36864     # stmt->operation = "increment"
    36865     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
    36866     (copy-array Heap "increment" %eax)
    36867 $test-emit-subx-stmt-select-primitive-2:initialize-formal-var:
    36868     # var formal-var/ebx: (payload var)
    36869     68/push 0/imm32/register
    36870     68/push 0/imm32/register
    36871     68/push 0/imm32/no-stack-offset
    36872     68/push 1/imm32/block-depth
    36873     ff 6/subop/push *(ecx+0x10)  # Var-type + payload alloc id + handle alloc id
    36874     68/push 0x11/imm32/alloc-id:fake
    36875     68/push 0/imm32/name
    36876     68/push 0/imm32/name
    36877     68/push 0x11/imm32/alloc-id:fake:payload
    36878     89/<- %ebx 4/r32/esp
    36879 $test-emit-subx-stmt-select-primitive-2:initialize-formal-var-name:
    36880     # formal-var->name = "dummy"
    36881     8d/copy-address *(ebx+4) 0/r32/eax  # Var-name + 4
    36882     (copy-array Heap "dummy" %eax)
    36883 $test-emit-subx-stmt-select-primitive-2:initialize-formal-register:
    36884     # formal-var->register = "*"
    36885     8d/copy-address *(ebx+0x1c) 0/r32/eax  # Var-register + 4
    36886     (copy-array Heap "*" %eax)  # Any-register
    36887 $test-emit-subx-stmt-select-primitive-2:initialize-var-list:
    36888     # var formal-outputs/ebx: (payload list stmt-var)
    36889     68/push 0/imm32/next
    36890     68/push 0/imm32/next
    36891     53/push-ebx/formal-var
    36892     68/push 0x11/imm32/alloc-id:fake
    36893     68/push 0x11/imm32/alloc-id:fake:payload
    36894     89/<- %ebx 4/r32/esp
    36895 $test-emit-subx-stmt-select-primitive-2:initialize-primitive2:
    36896     # var primitive2/edi: (payload primitive)
    36897     68/push 0/imm32/next
    36898     68/push 0/imm32/next
    36899     68/push 0/imm32/no-x32
    36900     68/push 0/imm32/no-xm32
    36901     68/push 0/imm32/no-disp32
    36902     68/push 0/imm32/no-imm8
    36903     68/push 0/imm32/no-imm32
    36904     68/push 0/imm32/no-r32
    36905     68/push 3/imm32/rm32-is-first-output
    36906     68/push 0/imm32/subx-name
    36907     68/push 0/imm32/subx-name
    36908     53/push-ebx/outputs
    36909     68/push 0x11/imm32/alloc-id:fake
    36910     68/push 0/imm32/no-inouts
    36911     68/push 0/imm32/no-inouts
    36912     68/push 0/imm32/name
    36913     68/push 0/imm32/name
    36914     68/push 0x11/imm32/alloc-id:fake:payload
    36915     89/<- %edi 4/r32/esp
    36916 $test-emit-subx-stmt-select-primitive-2:initialize-primitive2-name:
    36917     # primitives->name = "increment"
    36918     8d/copy-address *(edi+4) 0/r32/eax  # Primitive-name + 4
    36919     (copy-array Heap "increment" %eax)
    36920 $test-emit-subx-stmt-select-primitive-2:initialize-primitive2-subx-name:
    36921     # primitives->subx-name = "ff 0/subop/increment"
    36922     8d/copy-address *(edi+0x1c) 0/r32/eax  # Primitive-subx-name + 4
    36923     (copy-array Heap "ff 0/subop/increment" %eax)
    36924 $test-emit-subx-stmt-select-primitive-2:initialize-primitive:
    36925     # var primitives/ebx: (addr primitive)
    36926     57/push-edi
    36927     68/push 0x11/imm32/alloc-id:fake
    36928     68/push 0/imm32/no-x32
    36929     68/push 0/imm32/no-xm32
    36930     68/push 0/imm32/no-disp32
    36931     68/push 0/imm32/no-imm8
    36932     68/push 0/imm32/no-imm32
    36933     68/push 0/imm32/no-r32
    36934     68/push 1/imm32/rm32-is-first-inout
    36935     68/push 0/imm32/subx-name
    36936     68/push 0/imm32/subx-name
    36937     68/push 0/imm32/no-outputs
    36938     68/push 0/imm32/no-outputs
    36939     53/push-ebx/inouts  # hack: reuse stmt-var from call stmt as (list var) in function declaration
    36940     68/push 0x11/imm32/alloc-id:fake
    36941     68/push 0/imm32/name
    36942     68/push 0/imm32/name
    36943     89/<- %ebx 4/r32/esp
    36944 $test-emit-subx-stmt-select-primitive-2:initialize-primitive-name:
    36945     # primitives->name = "increment"
    36946     (copy-array Heap "increment" %ebx)  # Primitive-name
    36947 $test-emit-subx-stmt-select-primitive-2:initialize-primitive-subx-name:
    36948     # primitives->subx-name = "ff 0/subop/increment"
    36949     8d/copy-address *(ebx+0x18) 0/r32/eax  # Primitive-subx-name
    36950     (copy-array Heap "ff 0/subop/increment" %eax)
    36951     # convert
    36952     c7 0/subop/copy *Curr-block-depth 0/imm32
    36953     (emit-subx-stmt _test-output-buffered-file %esi %ebx 0 Stderr 0)
    36954     (flush _test-output-buffered-file)
    36955 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
    36961     # check output
    36962     (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-stmt-select-primitive-2")
    36963     # . epilogue
    36964     89/<- %esp 5/r32/ebp
    36965     5d/pop-to-ebp
    36966     c3/return
    36967
    36968 test-increment-register:
    36969     # Select the right register between overloads.
    36970     #   foo <- increment
    36971     # =>
    36972     #   50/increment-eax
    36973     #
    36974     # There's a variable on the var stack as follows:
    36975     #   name: 'foo'
    36976     #   type: int
    36977     #   register: 'eax'
    36978     #
    36979     # Primitives are the global definitions.
    36980     #
    36981     # . prologue
    36982     55/push-ebp
    36983     89/<- %ebp 4/r32/esp
    36984     # setup
    36985     (clear-stream _test-output-stream)
    36986     (clear-stream $_test-output-buffered-file->buffer)
    36987 $test-increment-register:initialize-type:
    36988     # var type/ecx: (payload type-tree) = int
    36989     68/push 0/imm32/right:null
    36990     68/push 0/imm32/right:null
    36991     68/push 0/imm32/left:unused
    36992     68/push 1/imm32/value:int
    36993     68/push 1/imm32/is-atom?:true
    36994     68/push 0x11/imm32/alloc-id:fake:payload
    36995     89/<- %ecx 4/r32/esp
    36996 $test-increment-register:initialize-var:
    36997     # var var-foo/ecx: (payload var)
    36998     68/push 0/imm32/register
    36999     68/push 0/imm32/register
    37000     68/push 0/imm32/no-stack-offset
    37001     68/push 1/imm32/block-depth
    37002     51/push-ecx
    37003     68/push 0x11/imm32/alloc-id:fake
    37004     68/push 0/imm32/name
    37005     68/push 0/imm32/name
    37006     68/push 0x11/imm32/alloc-id:fake:payload
    37007     89/<- %ecx 4/r32/esp
    37008 $test-increment-register:initialize-var-name:
    37009     # var-foo->name = "foo"
    37010     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
    37011     (copy-array Heap "foo" %eax)
    37012 $test-increment-register:initialize-var-register:
    37013     # var-foo->register = "eax"
    37014     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
    37015     (copy-array Heap "eax" %eax)
    37016 $test-increment-register:initialize-stmt-var:
    37017     # var operand/ebx: (payload stmt-var)
    37018     68/push 0/imm32/is-deref:false
    37019     68/push 0/imm32/next
    37020     68/push 0/imm32/next
    37021     51/push-ecx/var-foo
    37022     68/push 0x11/imm32/alloc-id:fake
    37023     68/push 0x11/imm32/alloc-id:fake:payload
    37024     89/<- %ebx 4/r32/esp
    37025 $test-increment-register:initialize-stmt:
    37026     # var stmt/esi: (addr statement)
    37027     53/push-ebx/outputs
    37028     68/push 0x11/imm32/alloc-id:fake
    37029     68/push 0/imm32/no-inouts
    37030     68/push 0/imm32/no-inouts
    37031     68/push 0/imm32/operation
    37032     68/push 0/imm32/operation
    37033     68/push 1/imm32
    37034     89/<- %esi 4/r32/esp
    37035 $test-increment-register:initialize-stmt-operation:
    37036     # stmt->operation = "increment"
    37037     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
    37038     (copy-array Heap "increment" %eax)
    37039     # convert
    37040     c7 0/subop/copy *Curr-block-depth 0/imm32
    37041     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
    37042     (flush _test-output-buffered-file)
    37043 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
    37049     # check output
    37050     (check-next-stream-line-equal _test-output-stream "40/increment-eax" "F - test-increment-register")
    37051     # . epilogue
    37052     89/<- %esp 5/r32/ebp
    37053     5d/pop-to-ebp
    37054     c3/return
    37055
    37056 test-add-reg-to-reg:
    37057     #   var1/reg <- add var2/reg
    37058     # =>
    37059     #   01/add-to %var1 var2
    37060     #
    37061     # . prologue
    37062     55/push-ebp
    37063     89/<- %ebp 4/r32/esp
    37064     # setup
    37065     (clear-stream _test-output-stream)
    37066     (clear-stream $_test-output-buffered-file->buffer)
    37067 $test-add-reg-to-reg:initialize-type:
    37068     # var type/ecx: (payload type-tree) = int
    37069     68/push 0/imm32/right:null
    37070     68/push 0/imm32/right:null
    37071     68/push 0/imm32/left:unused
    37072     68/push 1/imm32/value:int
    37073     68/push 1/imm32/is-atom?:true
    37074     68/push 0x11/imm32/alloc-id:fake:payload
    37075     89/<- %ecx 4/r32/esp
    37076 $test-add-reg-to-reg:initialize-var1:
    37077     # var var1/ecx: (payload var)
    37078     68/push 0/imm32/register
    37079     68/push 0/imm32/register
    37080     68/push 0/imm32/no-stack-offset
    37081     68/push 1/imm32/block-depth
    37082     51/push-ecx
    37083     68/push 0x11/imm32/alloc-id:fake
    37084     68/push 0/imm32/name
    37085     68/push 0/imm32/name
    37086     68/push 0x11/imm32/alloc-id:fake:payload
    37087     89/<- %ecx 4/r32/esp
    37088 $test-add-reg-to-reg:initialize-var1-name:
    37089     # var1->name = "var1"
    37090     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
    37091     (copy-array Heap "var1" %eax)
    37092 $test-add-reg-to-reg:initialize-var1-register:
    37093     # var1->register = "eax"
    37094     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
    37095     (copy-array Heap "eax" %eax)
    37096 $test-add-reg-to-reg:initialize-var2:
    37097     # var var2/edx: (payload var)
    37098     68/push 0/imm32/register
    37099     68/push 0/imm32/register
    37100     68/push 0/imm32/no-stack-offset
    37101     68/push 1/imm32/block-depth
    37102     ff 6/subop/push *(ecx+0x10)
    37103     68/push 0x11/imm32/alloc-id:fake
    37104     68/push 0/imm32/name
    37105     68/push 0/imm32/name
    37106     68/push 0x11/imm32/alloc-id:fake:payload
    37107     89/<- %edx 4/r32/esp
    37108 $test-add-reg-to-reg:initialize-var2-name:
    37109     # var2->name = "var2"
    37110     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
    37111     (copy-array Heap "var2" %eax)
    37112 $test-add-reg-to-reg:initialize-var2-register:
    37113     # var2->register = "ecx"
    37114     8d/copy-address *(edx+0x1c) 0/r32/eax  # Var-register + 4
    37115     (copy-array Heap "ecx" %eax)
    37116 $test-add-reg-to-reg:initialize-inouts:
    37117     # var inouts/esi: (payload stmt-var) = [var2]
    37118     68/push 0/imm32/is-deref:false
    37119     68/push 0/imm32/next
    37120     68/push 0/imm32/next
    37121     52/push-edx/var2
    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-reg-to-reg:initialize-outputs:
    37126     # var outputs/edi: (payload stmt-var) = [var1]
    37127     68/push 0/imm32/is-deref:false
    37128     68/push 0/imm32/next
    37129     68/push 0/imm32/next
    37130     51/push-ecx/var1
    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-reg-to-reg: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-reg-to-reg: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 "01/add-to %eax 0x00000001/r32" "F - test-add-reg-to-reg")
    37162     # . epilogue
    37163     89/<- %esp 5/r32/ebp
    37164     5d/pop-to-ebp
    37165     c3/return
    37166
    37167 test-add-reg-to-mem:
    37168     #   add-to var1 var2/reg
    37169     # =>
    37170     #   01/add-to *(ebp+__) var2
    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-reg-to-mem:initialize-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-reg-to-mem:initialize-var1:
    37188     # var var1/ecx: (payload var)
    37189     68/push 0/imm32/register
    37190     68/push 0/imm32/register
    37191     68/push 8/imm32/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-reg-to-mem:initialize-var1-name:
    37200     # var1->name = "var1"
    37201     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
    37202     (copy-array Heap "var1" %eax)
    37203 $test-add-reg-to-mem:initialize-var2:
    37204     # var var2/edx: (payload var)
    37205     68/push 0/imm32/register
    37206     68/push 0/imm32/register
    37207     68/push 0/imm32/no-stack-offset
    37208     68/push 1/imm32/block-depth
    37209     ff 6/subop/push *(ecx+0x10)
    37210     68/push 0x11/imm32/alloc-id:fake
    37211     68/push 0/imm32/name
    37212     68/push 0/imm32/name
    37213     68/push 0x11/imm32/alloc-id:fake:payload
    37214     89/<- %edx 4/r32/esp
    37215 $test-add-reg-to-mem:initialize-var2-name:
    37216     # var2->name = "var2"
    37217     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
    37218     (copy-array Heap "var2" %eax)
    37219 $test-add-reg-to-mem:initialize-var2-register:
    37220     # var2->register = "ecx"
    37221     8d/copy-address *(edx+0x1c) 0/r32/eax  # Var-register + 4
    37222     (copy-array Heap "ecx" %eax)
    37223 $test-add-reg-to-mem:initialize-inouts:
    37224     # var inouts/esi: (payload stmt-var) = [var2]
    37225     68/push 0/imm32/is-deref:false
    37226     68/push 0/imm32/next
    37227     68/push 0/imm32/next
    37228     52/push-edx/var2
    37229     68/push 0x11/imm32/alloc-id:fake
    37230     68/push 0x11/imm32/alloc-id:fake:payload
    37231     89/<- %esi 4/r32/esp
    37232     # inouts = [var1, var2]
    37233     68/push 0/imm32/is-deref:false
    37234     56/push-esi/next
    37235     68/push 0x11/imm32/alloc-id:fake
    37236     51/push-ecx/var1
    37237     68/push 0x11/imm32/alloc-id:fake
    37238     68/push 0x11/imm32/alloc-id:fake:payload
    37239     89/<- %esi 4/r32/esp
    37240 $test-add-reg-to-mem:initialize-stmt:
    37241     # var stmt/esi: (addr statement)
    37242     68/push 0/imm32/next
    37243     68/push 0/imm32/next
    37244     68/push 0/imm32/outputs
    37245     68/push 0/imm32/outputs
    37246     56/push-esi/inouts
    37247     68/push 0x11/imm32/alloc-id:fake
    37248     68/push 0/imm32/operation
    37249     68/push 0/imm32/operation
    37250     68/push 1/imm32/tag:stmt1
    37251     89/<- %esi 4/r32/esp
    37252 $test-add-reg-to-mem:initialize-stmt-operation:
    37253     # stmt->operation = "add-to"
    37254     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
    37255     (copy-array Heap "add-to" %eax)
    37256     # convert
    37257     c7 0/subop/copy *Curr-block-depth 0/imm32
    37258     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
    37259     (flush _test-output-buffered-file)
    37260 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
    37266     # check output
    37267     (check-next-stream-line-equal _test-output-stream "01/add-to *(ebp+0x00000008) 0x00000001/r32" "F - test-add-reg-to-mem")
    37268     # . epilogue
    37269     89/<- %esp 5/r32/ebp
    37270     5d/pop-to-ebp
    37271     c3/return
    37272
    37273 test-add-mem-to-reg:
    37274     #   var1/reg <- add var2
    37275     # =>
    37276     #   03/add *(ebp+__) var1
    37277     #
    37278     # . prologue
    37279     55/push-ebp
    37280     89/<- %ebp 4/r32/esp
    37281     # setup
    37282     (clear-stream _test-output-stream)
    37283     (clear-stream $_test-output-buffered-file->buffer)
    37284 $test-add-mem-to-reg:initialize-type:
    37285     # var type/ecx: (payload type-tree) = int
    37286     68/push 0/imm32/right:null
    37287     68/push 0/imm32/right:null
    37288     68/push 0/imm32/left:unused
    37289     68/push 1/imm32/value:int
    37290     68/push 1/imm32/is-atom?:true
    37291     68/push 0x11/imm32/alloc-id:fake:payload
    37292     89/<- %ecx 4/r32/esp
    37293 $test-add-mem-to-reg:initialize-var:
    37294     # var var1/ecx: (payload var)
    37295     68/push 0/imm32/register
    37296     68/push 0/imm32/register
    37297     68/push 0/imm32/no-stack-offset
    37298     68/push 1/imm32/block-depth
    37299     51/push-ecx
    37300     68/push 0x11/imm32/alloc-id:fake
    37301     68/push 0/imm32/name
    37302     68/push 0/imm32/name
    37303     68/push 0x11/imm32/alloc-id:fake:payload
    37304     89/<- %ecx 4/r32/esp
    37305 $test-add-mem-to-reg:initialize-var-name:
    37306     # var1->name = "foo"
    37307     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
    37308     (copy-array Heap "var1" %eax)
    37309 $test-add-mem-to-reg:initialize-var-register:
    37310     # var1->register = "eax"
    37311     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
    37312     (copy-array Heap "eax" %eax)
    37313 $test-add-mem-to-reg:initialize-var2:
    37314     # var var2/edx: (payload var)
    37315     68/push 0/imm32/register
    37316     68/push 0/imm32/register
    37317     68/push 8/imm32/stack-offset
    37318     68/push 1/imm32/block-depth
    37319     ff 6/subop/push *(ecx+0x10)
    37320     68/push 0x11/imm32/alloc-id:fake
    37321     68/push 0/imm32/name
    37322     68/push 0/imm32/name
    37323     68/push 0x11/imm32/alloc-id:fake:payload
    37324     89/<- %edx 4/r32/esp
    37325 $test-add-mem-to-reg:initialize-var2-name:
    37326     # var2->name = "var2"
    37327     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
    37328     (copy-array Heap "var2" %eax)
    37329 $test-add-mem-to-reg:initialize-inouts:
    37330     # var inouts/esi: (payload stmt-var) = [var2]
    37331     68/push 0/imm32/is-deref:false
    37332     68/push 0/imm32/next
    37333     68/push 0/imm32/next
    37334     52/push-edx/var2
    37335     68/push 0x11/imm32/alloc-id:fake
    37336     68/push 0x11/imm32/alloc-id:fake:payload
    37337     89/<- %esi 4/r32/esp
    37338 $test-add-mem-to-reg:initialize-outputs:
    37339     # var outputs/edi: (payload stmt-var) = [var1]
    37340     68/push 0/imm32/is-deref:false
    37341     68/push 0/imm32/next
    37342     68/push 0/imm32/next
    37343     51/push-ecx/var1
    37344     68/push 0x11/imm32/alloc-id:fake
    37345     68/push 0x11/imm32/alloc-id:fake:payload
    37346     89/<- %edi 4/r32/esp
    37347 $test-add-mem-to-reg:initialize-stmt:
    37348     # var stmt/esi: (addr statement)
    37349     68/push 0/imm32/next
    37350     68/push 0/imm32/next
    37351     57/push-edi/outputs
    37352     68/push 0x11/imm32/alloc-id:fake
    37353     56/push-esi/inouts
    37354     68/push 0x11/imm32/alloc-id:fake
    37355     68/push 0/imm32/operation
    37356     68/push 0/imm32/operation
    37357     68/push 1/imm32/tag:stmt1
    37358     89/<- %esi 4/r32/esp
    37359 $test-add-mem-to-reg:initialize-stmt-operation:
    37360     # stmt->operation = "add"
    37361     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
    37362     (copy-array Heap "add" %eax)
    37363     # convert
    37364     c7 0/subop/copy *Curr-block-depth 0/imm32
    37365     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
    37366     (flush _test-output-buffered-file)
    37367 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
    37373     # check output
    37374     (check-next-stream-line-equal _test-output-stream "03/add *(ebp+0x00000008) 0x00000000/r32" "F - test-add-mem-to-reg")
    37375     # . epilogue
    37376     89/<- %esp 5/r32/ebp
    37377     5d/pop-to-ebp
    37378     c3/return
    37379
    37380 test-add-literal-to-eax:
    37381     #   var1/eax <- add 0x34
    37382     # =>
    37383     #   05/add-to-eax 0x34/imm32
    37384     #
    37385     # . prologue
    37386     55/push-ebp
    37387     89/<- %ebp 4/r32/esp
    37388     # setup
    37389     (clear-stream _test-output-stream)
    37390     (clear-stream $_test-output-buffered-file->buffer)
    37391 $test-add-literal-to-eax:initialize-var-type:
    37392     # var type/ecx: (payload type-tree) = int
    37393     68/push 0/imm32/right:null
    37394     68/push 0/imm32/right:null
    37395     68/push 0/imm32/left:unused
    37396     68/push 1/imm32/value:int
    37397     68/push 1/imm32/is-atom?:true
    37398     68/push 0x11/imm32/alloc-id:fake:payload
    37399     89/<- %ecx 4/r32/esp
    37400 $test-add-literal-to-eax:initialize-var:
    37401     # var v/ecx: (payload var)
    37402     68/push 0/imm32/register
    37403     68/push 0/imm32/register
    37404     68/push 0/imm32/no-stack-offset
    37405     68/push 1/imm32/block-depth
    37406     51/push-ecx
    37407     68/push 0x11/imm32/alloc-id:fake
    37408     68/push 0/imm32/name
    37409     68/push 0/imm32/name
    37410     68/push 0x11/imm32/alloc-id:fake:payload
    37411     89/<- %ecx 4/r32/esp
    37412 $test-add-literal-to-eax:initialize-var-name:
    37413     # v->name = "v"
    37414     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
    37415     (copy-array Heap "v" %eax)
    37416 $test-add-literal-to-eax:initialize-var-register:
    37417     # v->register = "eax"
    37418     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
    37419     (copy-array Heap "eax" %eax)
    37420 $test-add-literal-to-eax:initialize-literal-type:
    37421     # var type/edx: (payload type-tree) = literal
    37422     68/push 0/imm32/right:null
    37423     68/push 0/imm32/right:null
    37424     68/push 0/imm32/left:unused
    37425     68/push 0/imm32/value:literal
    37426     68/push 1/imm32/is-atom?:true
    37427     68/push 0x11/imm32/alloc-id:fake:payload
    37428     89/<- %edx 4/r32/esp
    37429 $test-add-literal-to-eax:initialize-literal:
    37430     # var l/edx: (payload var)
    37431     68/push 0/imm32/register
    37432     68/push 0/imm32/register
    37433     68/push 0/imm32/no-stack-offset
    37434     68/push 1/imm32/block-depth
    37435     52/push-edx
    37436     68/push 0x11/imm32/alloc-id:fake
    37437     68/push 0/imm32/name
    37438     68/push 0/imm32/name
    37439     68/push 0x11/imm32/alloc-id:fake:payload
    37440     89/<- %edx 4/r32/esp
    37441 $test-add-literal-to-eax:initialize-literal-value:
    37442     # l->name = "0x34"
    37443     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
    37444     (copy-array Heap "0x34" %eax)
    37445 $test-add-literal-to-eax:initialize-inouts:
    37446     # var inouts/esi: (payload stmt-var) = [l]
    37447     68/push 0/imm32/is-deref:false
    37448     68/push 0/imm32/next
    37449     68/push 0/imm32/next
    37450     52/push-edx/l
    37451     68/push 0x11/imm32/alloc-id:fake
    37452     68/push 0x11/imm32/alloc-id:fake:payload
    37453     89/<- %esi 4/r32/esp
    37454 $test-add-literal-to-eax:initialize-outputs:
    37455     # var outputs/edi: (payload stmt-var) = [v]
    37456     68/push 0/imm32/is-deref:false
    37457     68/push 0/imm32/next
    37458     68/push 0/imm32/next
    37459     51/push-ecx/v
    37460     68/push 0x11/imm32/alloc-id:fake
    37461     68/push 0x11/imm32/alloc-id:fake:payload
    37462     89/<- %edi 4/r32/esp
    37463 $test-add-literal-to-eax:initialize-stmt:
    37464     # var stmt/esi: (addr statement)
    37465     68/push 0/imm32/next
    37466     68/push 0/imm32/next
    37467     57/push-edi/outputs
    37468     68/push 0x11/imm32/alloc-id:fake
    37469     56/push-esi/inouts
    37470     68/push 0x11/imm32/alloc-id:fake
    37471     68/push 0/imm32/operation
    37472     68/push 0/imm32/operation
    37473     68/push 1/imm32/tag:stmt1
    37474     89/<- %esi 4/r32/esp
    37475 $test-add-literal-to-eax:initialize-stmt-operation:
    37476     # stmt->operation = "add"
    37477     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
    37478     (copy-array Heap "add" %eax)
    37479     # convert
    37480     c7 0/subop/copy *Curr-block-depth 0/imm32
    37481     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
    37482     (flush _test-output-buffered-file)
    37483 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
    37489     # check output
    37490     (check-next-stream-line-equal _test-output-stream "05/add-to-eax 0x34/imm32" "F - test-add-literal-to-eax")
    37491     # . epilogue
    37492     89/<- %esp 5/r32/ebp
    37493     5d/pop-to-ebp
    37494     c3/return
    37495
    37496 test-add-literal-to-reg:
    37497     #   var1/ecx <- add 0x34
    37498     # =>
    37499     #   81 0/subop/add %ecx 0x34/imm32
    37500     #
    37501     # . prologue
    37502     55/push-ebp
    37503     89/<- %ebp 4/r32/esp
    37504     # setup
    37505     (clear-stream _test-output-stream)
    37506     (clear-stream $_test-output-buffered-file->buffer)
    37507 $test-add-literal-to-reg:initialize-var-type:
    37508     # var type/ecx: (payload type-tree) = int
    37509     68/push 0/imm32/right:null
    37510     68/push 0/imm32/right:null
    37511     68/push 0/imm32/left:unused
    37512     68/push 1/imm32/value:int
    37513     68/push 1/imm32/is-atom?:true
    37514     68/push 0x11/imm32/alloc-id:fake:payload
    37515     89/<- %ecx 4/r32/esp
    37516 $test-add-literal-to-reg:initialize-var:
    37517     # var v/ecx: (payload var)
    37518     68/push 0/imm32/register
    37519     68/push 0/imm32/register
    37520     68/push 0/imm32/no-stack-offset
    37521     68/push 1/imm32/block-depth
    37522     51/push-ecx
    37523     68/push 0x11/imm32/alloc-id:fake
    37524     68/push 0/imm32/name
    37525     68/push 0/imm32/name
    37526     68/push 0x11/imm32/alloc-id:fake:payload
    37527     89/<- %ecx 4/r32/esp
    37528 $test-add-literal-to-reg:initialize-var-name:
    37529     # v->name = "v"
    37530     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
    37531     (copy-array Heap "v" %eax)
    37532 $test-add-literal-to-reg:initialize-var-register:
    37533     # v->register = "ecx"
    37534     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
    37535     (copy-array Heap "ecx" %eax)
    37536 $test-add-literal-to-reg:initialize-literal-type:
    37537     # var type/edx: (payload type-tree) = literal
    37538     68/push 0/imm32/right:null
    37539     68/push 0/imm32/right:null
    37540     68/push 0/imm32/left:unused
    37541     68/push 0/imm32/value:literal
    37542     68/push 1/imm32/is-atom?:true
    37543     68/push 0x11/imm32/alloc-id:fake:payload
    37544     89/<- %edx 4/r32/esp
    37545 $test-add-literal-to-reg:initialize-literal:
    37546     # var l/edx: (payload var)
    37547     68/push 0/imm32/register
    37548     68/push 0/imm32/register
    37549     68/push 0/imm32/no-stack-offset
    37550     68/push 1/imm32/block-depth
    37551     52/push-edx
    37552     68/push 0x11/imm32/alloc-id:fake
    37553     68/push 0/imm32/name
    37554     68/push 0/imm32/name
    37555     68/push 0x11/imm32/alloc-id:fake:payload
    37556     89/<- %edx 4/r32/esp
    37557 $test-add-literal-to-reg:initialize-literal-value:
    37558     # l->name = "0x34"
    37559     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
    37560     (copy-array Heap "0x34" %eax)
    37561 $test-add-literal-to-reg:initialize-inouts:
    37562     # var inouts/esi: (payload stmt-var) = [l]
    37563     68/push 0/imm32/is-deref:false
    37564     68/push 0/imm32/next
    37565     68/push 0/imm32/next
    37566     52/push-edx/l
    37567     68/push 0x11/imm32/alloc-id:fake
    37568     68/push 0x11/imm32/alloc-id:fake:payload
    37569     89/<- %esi 4/r32/esp
    37570 $test-add-literal-to-reg:initialize-outputs:
    37571     # var outputs/edi: (payload stmt-var) = [v]
    37572     68/push 0/imm32/is-deref:false
    37573     68/push 0/imm32/next
    37574     68/push 0/imm32/next
    37575     51/push-ecx/v
    37576     68/push 0x11/imm32/alloc-id:fake
    37577     68/push 0x11/imm32/alloc-id:fake:payload
    37578     89/<- %edi 4/r32/esp
    37579 $test-add-literal-to-reg:initialize-stmt:
    37580     # var stmt/esi: (addr statement)
    37581     68/push 0/imm32/next
    37582     68/push 0/imm32/next
    37583     57/push-edi/outputs
    37584     68/push 0x11/imm32/alloc-id:fake
    37585     56/push-esi/inouts
    37586     68/push 0x11/imm32/alloc-id:fake
    37587     68/push 0/imm32/operation
    37588     68/push 0/imm32/operation
    37589     68/push 1/imm32/tag:stmt1
    37590     89/<- %esi 4/r32/esp
    37591 $test-add-literal-to-reg:initialize-stmt-operation:
    37592     # stmt->operation = "add"
    37593     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
    37594     (copy-array Heap "add" %eax)
    37595     # convert
    37596     c7 0/subop/copy *Curr-block-depth 0/imm32
    37597     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
    37598     (flush _test-output-buffered-file)
    37599 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
    37605     # check output
    37606     (check-next-stream-line-equal _test-output-stream "81 0/subop/add %ecx 0x34/imm32" "F - test-add-literal-to-reg")
    37607     # . epilogue
    37608     89/<- %esp 5/r32/ebp
    37609     5d/pop-to-ebp
    37610     c3/return
    37611
    37612 test-add-literal-to-mem:
    37613     #   add-to var1, 0x34
    37614     # =>
    37615     #   81 0/subop/add %eax 0x34/imm32
    37616     #
    37617     # . prologue
    37618     55/push-ebp
    37619     89/<- %ebp 4/r32/esp
    37620     # setup
    37621     (clear-stream _test-output-stream)
    37622     (clear-stream $_test-output-buffered-file->buffer)
    37623 $test-add-literal-to-mem:initialize-type:
    37624     # var type/ecx: (payload type-tree) = int
    37625     68/push 0/imm32/right:null
    37626     68/push 0/imm32/right:null
    37627     68/push 0/imm32/left:unused
    37628     68/push 1/imm32/value:int
    37629     68/push 1/imm32/is-atom?:true
    37630     68/push 0x11/imm32/alloc-id:fake:payload
    37631     89/<- %ecx 4/r32/esp
    37632 $test-add-literal-to-mem:initialize-var1:
    37633     # var var1/ecx: (payload var)
    37634     68/push 0/imm32/register
    37635     68/push 0/imm32/register
    37636     68/push 8/imm32/stack-offset
    37637     68/push 1/imm32/block-depth
    37638     51/push-ecx
    37639     68/push 0x11/imm32/alloc-id:fake
    37640     68/push 0/imm32/name
    37641     68/push 0/imm32/name
    37642     68/push 0x11/imm32/alloc-id:fake:payload
    37643     89/<- %ecx 4/r32/esp
    37644 $test-add-literal-to-mem:initialize-var1-name:
    37645     # var1->name = "var1"
    37646     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
    37647     (copy-array Heap "var1" %eax)
    37648 $test-add-literal-to-mem:initialize-literal-type:
    37649     # var type/edx: (payload type-tree) = literal
    37650     68/push 0/imm32/right:null
    37651     68/push 0/imm32/right:null
    37652     68/push 0/imm32/left:unused
    37653     68/push 0/imm32/value:literal
    37654     68/push 1/imm32/is-atom?:true
    37655     68/push 0x11/imm32/alloc-id:fake:payload
    37656     89/<- %edx 4/r32/esp
    37657 $test-add-literal-to-mem:initialize-literal:
    37658     # var l/edx: (payload var)
    37659     68/push 0/imm32/register
    37660     68/push 0/imm32/register
    37661     68/push 0/imm32/no-stack-offset
    37662     68/push 1/imm32/block-depth
    37663     52/push-edx
    37664     68/push 0x11/imm32/alloc-id:fake
    37665     68/push 0/imm32/name
    37666     68/push 0/imm32/name
    37667     68/push 0x11/imm32/alloc-id:fake:payload
    37668     89/<- %edx 4/r32/esp
    37669 $test-add-literal-to-mem:initialize-literal-value:
    37670     # l->name = "0x34"
    37671     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
    37672     (copy-array Heap "0x34" %eax)
    37673 $test-add-literal-to-mem:initialize-inouts:
    37674     # var inouts/esi: (payload stmt-var) = [l]
    37675     68/push 0/imm32/is-deref:false
    37676     68/push 0/imm32/next
    37677     68/push 0/imm32/next
    37678     52/push-edx/l
    37679     68/push 0x11/imm32/alloc-id:fake
    37680     68/push 0x11/imm32/alloc-id:fake:payload
    37681     89/<- %esi 4/r32/esp
    37682     # var inouts = (handle stmt-var) = [var1, var2]
    37683     68/push 0/imm32/is-deref:false
    37684     56/push-esi/next
    37685     68/push 0x11/imm32/alloc-id:fake
    37686     51/push-ecx/var1
    37687     68/push 0x11/imm32/alloc-id:fake
    37688     68/push 0x11/imm32/alloc-id:fake:payload
    37689     89/<- %esi 4/r32/esp
    37690 $test-add-literal-to-mem:initialize-stmt:
    37691     # var stmt/esi: (addr statement)
    37692     68/push 0/imm32/next
    37693     68/push 0/imm32/next
    37694     68/push 0/imm32/outputs
    37695     68/push 0/imm32/outputs
    37696     56/push-esi/inouts
    37697     68/push 0x11/imm32/alloc-id:fake
    37698     68/push 0/imm32/operation
    37699     68/push 0/imm32/operation
    37700     68/push 1/imm32/tag:stmt1
    37701     89/<- %esi 4/r32/esp
    37702 $test-add-literal-to-mem:initialize-stmt-operation:
    37703     # stmt->operation = "add-to"
    37704     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
    37705     (copy-array Heap "add-to" %eax)
    37706     # convert
    37707     c7 0/subop/copy *Curr-block-depth 0/imm32
    37708     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
    37709     (flush _test-output-buffered-file)
    37710 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
    37716     # check output
    37717     (check-next-stream-line-equal _test-output-stream "81 0/subop/add *(ebp+0x00000008) 0x34/imm32" "F - test-add-literal-to-mem")
    37718     # . epilogue
    37719     89/<- %esp 5/r32/ebp
    37720     5d/pop-to-ebp
    37721     c3/return
    37722
    37723 test-shift-reg-by-literal:
    37724     #   var1/ecx <- shift-left 2
    37725     # =>
    37726     #   c1/shift 4/subop/left %ecx 2/imm8
    37727     #
    37728     # . prologue
    37729     55/push-ebp
    37730     89/<- %ebp 4/r32/esp
    37731     # setup
    37732     (clear-stream _test-output-stream)
    37733     (clear-stream $_test-output-buffered-file->buffer)
    37734 $test-shift-reg-by-literal:initialize-var-type:
    37735     # var type/ecx: (payload type-tree) = int
    37736     68/push 0/imm32/right:null
    37737     68/push 0/imm32/right:null
    37738     68/push 0/imm32/left:unused
    37739     68/push 1/imm32/value:int
    37740     68/push 1/imm32/is-atom?:true
    37741     68/push 0x11/imm32/alloc-id:fake:payload
    37742     89/<- %ecx 4/r32/esp
    37743 $test-shift-reg-by-literal:initialize-var:
    37744     # var v/ecx: (payload var)
    37745     68/push 0/imm32/register
    37746     68/push 0/imm32/register
    37747     68/push 0/imm32/no-stack-offset
    37748     68/push 1/imm32/block-depth
    37749     51/push-ecx
    37750     68/push 0x11/imm32/alloc-id:fake
    37751     68/push 0/imm32/name
    37752     68/push 0/imm32/name
    37753     68/push 0x11/imm32/alloc-id:fake:payload
    37754     89/<- %ecx 4/r32/esp
    37755 $test-shift-reg-by-literal:initialize-var-name:
    37756     # v->name = "v"
    37757     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
    37758     (copy-array Heap "v" %eax)
    37759 $test-shift-reg-by-literal:initialize-var-register:
    37760     # v->register = "ecx"
    37761     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
    37762     (copy-array Heap "ecx" %eax)
    37763 $test-shift-reg-by-literal:initialize-literal-type:
    37764     # var type/edx: (payload type-tree) = literal
    37765     68/push 0/imm32/right:null
    37766     68/push 0/imm32/right:null
    37767     68/push 0/imm32/left:unused
    37768     68/push 0/imm32/value:literal
    37769     68/push 1/imm32/is-atom?:true
    37770     68/push 0x11/imm32/alloc-id:fake:payload
    37771     89/<- %edx 4/r32/esp
    37772 $test-shift-reg-by-literal:initialize-literal:
    37773     # var l/edx: (payload var)
    37774     68/push 0/imm32/register
    37775     68/push 0/imm32/register
    37776     68/push 0/imm32/no-stack-offset
    37777     68/push 1/imm32/block-depth
    37778     52/push-edx
    37779     68/push 0x11/imm32/alloc-id:fake
    37780     68/push 0/imm32/name
    37781     68/push 0/imm32/name
    37782     68/push 0x11/imm32/alloc-id:fake:payload
    37783     89/<- %edx 4/r32/esp
    37784 $test-shift-reg-by-literal:initialize-literal-value:
    37785     # l->name = "2"
    37786     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
    37787     (copy-array Heap "2" %eax)
    37788 $test-shift-reg-by-literal:initialize-inouts:
    37789     # var inouts/esi: (payload stmt-var) = [l]
    37790     68/push 0/imm32/is-deref:false
    37791     68/push 0/imm32/next
    37792     68/push 0/imm32/next
    37793     52/push-edx/l
    37794     68/push 0x11/imm32/alloc-id:fake
    37795     68/push 0x11/imm32/alloc-id:fake:payload
    37796     89/<- %esi 4/r32/esp
    37797 $test-shift-reg-by-literal:initialize-outputs:
    37798     # var outputs/edi: (payload stmt-var) = [v]
    37799     68/push 0/imm32/is-deref:false
    37800     68/push 0/imm32/next
    37801     68/push 0/imm32/next
    37802     51/push-ecx/v
    37803     68/push 0x11/imm32/alloc-id:fake
    37804     68/push 0x11/imm32/alloc-id:fake:payload
    37805     89/<- %edi 4/r32/esp
    37806 $test-shift-reg-by-literal:initialize-stmt:
    37807     # var stmt/esi: (addr statement)
    37808     68/push 0/imm32/next
    37809     68/push 0/imm32/next
    37810     57/push-edi/outputs
    37811     68/push 0x11/imm32/alloc-id:fake
    37812     56/push-esi/inouts
    37813     68/push 0x11/imm32/alloc-id:fake
    37814     68/push 0/imm32/operation
    37815     68/push 0/imm32/operation
    37816     68/push 1/imm32/tag:stmt1
    37817     89/<- %esi 4/r32/esp
    37818 $test-shift-reg-by-literal:initialize-stmt-operation:
    37819     # stmt->operation = "shift-left"
    37820     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
    37821     (copy-array Heap "shift-left" %eax)
    37822     # convert
    37823     c7 0/subop/copy *Curr-block-depth 0/imm32
    37824     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
    37825     (flush _test-output-buffered-file)
    37826 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
    37832     # check output
    37833     (check-next-stream-line-equal _test-output-stream "c1/shift 4/subop/left %ecx 2/imm8" "F - test-shift-reg-by-literal")
    37834     # . epilogue
    37835     89/<- %esp 5/r32/ebp
    37836     5d/pop-to-ebp
    37837     c3/return
    37838
    37839 test-shift-mem-by-literal:
    37840     #   shift-left var 3
    37841     # =>
    37842     #   c1/shift 4/subop/left *(ebp+8) 3/imm8
    37843     #
    37844     # . prologue
    37845     55/push-ebp
    37846     89/<- %ebp 4/r32/esp
    37847     # setup
    37848     (clear-stream _test-output-stream)
    37849     (clear-stream $_test-output-buffered-file->buffer)
    37850 $test-shift-mem-by-literal:initialize-type:
    37851     # var type/ecx: (payload type-tree) = int
    37852     68/push 0/imm32/right:null
    37853     68/push 0/imm32/right:null
    37854     68/push 0/imm32/left:unused
    37855     68/push 1/imm32/value:int
    37856     68/push 1/imm32/is-atom?:true
    37857     68/push 0x11/imm32/alloc-id:fake:payload
    37858     89/<- %ecx 4/r32/esp
    37859 $test-shift-mem-by-literal:initialize-var1:
    37860     # var var1/ecx: (payload var)
    37861     68/push 0/imm32/register
    37862     68/push 0/imm32/register
    37863     68/push 8/imm32/stack-offset
    37864     68/push 1/imm32/block-depth
    37865     51/push-ecx
    37866     68/push 0x11/imm32/alloc-id:fake
    37867     68/push 0/imm32/name
    37868     68/push 0/imm32/name
    37869     68/push 0x11/imm32/alloc-id:fake:payload
    37870     89/<- %ecx 4/r32/esp
    37871 $test-shift-mem-by-literal:initialize-var1-name:
    37872     # var1->name = "var1"
    37873     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
    37874     (copy-array Heap "var1" %eax)
    37875 $test-shift-mem-by-literal:initialize-literal-type:
    37876     # var type/edx: (payload type-tree) = literal
    37877     68/push 0/imm32/right:null
    37878     68/push 0/imm32/right:null
    37879     68/push 0/imm32/left:unused
    37880     68/push 0/imm32/value:literal
    37881     68/push 1/imm32/is-atom?:true
    37882     68/push 0x11/imm32/alloc-id:fake:payload
    37883     89/<- %edx 4/r32/esp
    37884 $test-shift-mem-by-literal:initialize-literal:
    37885     # var l/edx: (payload var)
    37886     68/push 0/imm32/register
    37887     68/push 0/imm32/register
    37888     68/push 0/imm32/no-stack-offset
    37889     68/push 1/imm32/block-depth
    37890     52/push-edx
    37891     68/push 0x11/imm32/alloc-id:fake
    37892     68/push 0/imm32/name
    37893     68/push 0/imm32/name
    37894     68/push 0x11/imm32/alloc-id:fake:payload
    37895     89/<- %edx 4/r32/esp
    37896 $test-shift-mem-by-literal:initialize-literal-value:
    37897     # l->name = "3"
    37898     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
    37899     (copy-array Heap "3" %eax)
    37900 $test-shift-mem-by-literal:initialize-inouts:
    37901     # var inouts/esi: (payload stmt-var) = [l]
    37902     68/push 0/imm32/is-deref:false
    37903     68/push 0/imm32/next
    37904     68/push 0/imm32/next
    37905     52/push-edx/l
    37906     68/push 0x11/imm32/alloc-id:fake
    37907     68/push 0x11/imm32/alloc-id:fake:payload
    37908     89/<- %esi 4/r32/esp
    37909     # var inouts = (handle stmt-var) = [var1, var2]
    37910     68/push 0/imm32/is-deref:false
    37911     56/push-esi/next
    37912     68/push 0x11/imm32/alloc-id:fake
    37913     51/push-ecx/var1
    37914     68/push 0x11/imm32/alloc-id:fake
    37915     68/push 0x11/imm32/alloc-id:fake:payload
    37916     89/<- %esi 4/r32/esp
    37917 $test-shift-mem-by-literal:initialize-stmt:
    37918     # var stmt/esi: (addr statement)
    37919     68/push 0/imm32/next
    37920     68/push 0/imm32/next
    37921     68/push 0/imm32/outputs
    37922     68/push 0/imm32/outputs
    37923     56/push-esi/inouts
    37924     68/push 0x11/imm32/alloc-id:fake
    37925     68/push 0/imm32/operation
    37926     68/push 0/imm32/operation
    37927     68/push 1/imm32/tag:stmt1
    37928     89/<- %esi 4/r32/esp
    37929 $test-shift-mem-by-literal:initialize-stmt-operation:
    37930     # stmt->operation = "shift-left"
    37931     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
    37932     (copy-array Heap "shift-left" %eax)
    37933     # convert
    37934     c7 0/subop/copy *Curr-block-depth 0/imm32
    37935     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
    37936     (flush _test-output-buffered-file)
    37937 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
    37943     # check output
    37944     (check-next-stream-line-equal _test-output-stream "c1/shift 4/subop/left *(ebp+0x00000008) 3/imm8" "F - test-shift-mem-by-literal")
    37945     # . epilogue
    37946     89/<- %esp 5/r32/ebp
    37947     5d/pop-to-ebp
    37948     c3/return
    37949
    37950 test-compare-reg-with-reg:
    37951     #   compare var1/ecx, var2/eax
    37952     # =>
    37953     #   39/compare %ecx 0/r32/eax
    37954     #
    37955     # . prologue
    37956     55/push-ebp
    37957     89/<- %ebp 4/r32/esp
    37958     # setup
    37959     (clear-stream _test-output-stream)
    37960     (clear-stream $_test-output-buffered-file->buffer)
    37961 $test-compare-reg-with-reg:initialize-type:
    37962     # var type/ecx: (payload type-tree) = int
    37963     68/push 0/imm32/right:null
    37964     68/push 0/imm32/right:null
    37965     68/push 0/imm32/left:unused
    37966     68/push 1/imm32/value:int
    37967     68/push 1/imm32/is-atom?:true
    37968     68/push 0x11/imm32/alloc-id:fake:payload
    37969     89/<- %ecx 4/r32/esp
    37970 $test-compare-reg-with-reg:initialize-var1:
    37971     # var var1/ecx: (payload var)
    37972     68/push 0/imm32/register
    37973     68/push 0/imm32/register
    37974     68/push 0/imm32/no-stack-offset
    37975     68/push 1/imm32/block-depth
    37976     51/push-ecx
    37977     68/push 0x11/imm32/alloc-id:fake
    37978     68/push 0/imm32/name
    37979     68/push 0/imm32/name
    37980     68/push 0x11/imm32/alloc-id:fake:payload
    37981     89/<- %ecx 4/r32/esp
    37982 $test-compare-reg-with-reg:initialize-var1-name:
    37983     # var1->name = "var1"
    37984     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
    37985     (copy-array Heap "var1" %eax)
    37986 $test-compare-reg-with-reg:initialize-var1-register:
    37987     # var1->register = "ecx"
    37988     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
    37989     (copy-array Heap "ecx" %eax)
    37990 $test-compare-reg-with-reg:initialize-var2:
    37991     # var var2/edx: (payload var)
    37992     68/push 0/imm32/register
    37993     68/push 0/imm32/register
    37994     68/push 0/imm32/no-stack-offset
    37995     68/push 1/imm32/block-depth
    37996     ff 6/subop/push *(ecx+0x10)
    37997     68/push 0x11/imm32/alloc-id:fake
    37998     68/push 0/imm32/name
    37999     68/push 0/imm32/name
    38000     68/push 0x11/imm32/alloc-id:fake:payload
    38001     89/<- %edx 4/r32/esp
    38002 $test-compare-reg-with-reg:initialize-var2-name:
    38003     # var2->name = "var2"
    38004     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
    38005     (copy-array Heap "var2" %eax)
    38006 $test-compare-reg-with-reg:initialize-var2-register:
    38007     # var2->register = "eax"
    38008     8d/copy-address *(edx+0x1c) 0/r32/eax  # Var-register + 4
    38009     (copy-array Heap "eax" %eax)
    38010 $test-compare-reg-with-reg:initialize-inouts:
    38011     # var inouts/esi: (payload stmt-var) = [var2]
    38012     68/push 0/imm32/is-deref:false
    38013     68/push 0/imm32/next
    38014     68/push 0/imm32/next
    38015     52/push-edx/var2
    38016     68/push 0x11/imm32/alloc-id:fake
    38017     68/push 0x11/imm32/alloc-id:fake:payload
    38018     89/<- %esi 4/r32/esp
    38019     # inouts = [var1, var2]
    38020     68/push 0/imm32/is-deref:false
    38021     56/push-esi/next
    38022     68/push 0x11/imm32/alloc-id:fake
    38023     51/push-ecx/var1
    38024     68/push 0x11/imm32/alloc-id:fake
    38025     68/push 0x11/imm32/alloc-id:fake:payload
    38026     89/<- %esi 4/r32/esp
    38027 $test-compare-reg-with-reg:initialize-stmt:
    38028     # var stmt/esi: (addr statement)
    38029     68/push 0/imm32/next
    38030     68/push 0/imm32/next
    38031     68/push 0/imm32/outputs
    38032     68/push 0/imm32/outputs
    38033     56/push-esi/inouts
    38034     68/push 0x11/imm32/alloc-id:fake
    38035     68/push 0/imm32/operation
    38036     68/push 0/imm32/operation
    38037     68/push 1/imm32/tag:stmt1
    38038     89/<- %esi 4/r32/esp
    38039 $test-compare-reg-with-reg:initialize-stmt-operation:
    38040     # stmt->operation = "compare"
    38041     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
    38042     (copy-array Heap "compare" %eax)
    38043     # convert
    38044     c7 0/subop/copy *Curr-block-depth 0/imm32
    38045     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
    38046     (flush _test-output-buffered-file)
    38047 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
    38053     # check output
    38054     (check-next-stream-line-equal _test-output-stream "39/compare-> %ecx 0x00000000/r32" "F - test-compare-reg-with-reg")
    38055     # . epilogue
    38056     89/<- %esp 5/r32/ebp
    38057     5d/pop-to-ebp
    38058     c3/return
    38059
    38060 test-compare-mem-with-reg:
    38061     #   compare var1, var2/eax
    38062     # =>
    38063     #   39/compare *(ebp+___) 0/r32/eax
    38064     #
    38065     # . prologue
    38066     55/push-ebp
    38067     89/<- %ebp 4/r32/esp
    38068     # setup
    38069     (clear-stream _test-output-stream)
    38070     (clear-stream $_test-output-buffered-file->buffer)
    38071 $test-compare-mem-with-reg:initialize-type:
    38072     # var type/ecx: (payload type-tree) = int
    38073     68/push 0/imm32/right:null
    38074     68/push 0/imm32/right:null
    38075     68/push 0/imm32/left:unused
    38076     68/push 1/imm32/value:int
    38077     68/push 1/imm32/is-atom?:true
    38078     68/push 0x11/imm32/alloc-id:fake:payload
    38079     89/<- %ecx 4/r32/esp
    38080 $test-compare-mem-with-reg:initialize-var1:
    38081     # var var1/ecx: (payload var)
    38082     68/push 0/imm32/register
    38083     68/push 0/imm32/register
    38084     68/push 8/imm32/stack-offset
    38085     68/push 1/imm32/block-depth
    38086     51/push-ecx
    38087     68/push 0x11/imm32/alloc-id:fake
    38088     68/push 0/imm32/name
    38089     68/push 0/imm32/name
    38090     68/push 0x11/imm32/alloc-id:fake:payload
    38091     89/<- %ecx 4/r32/esp
    38092 $test-compare-mem-with-reg:initialize-var1-name:
    38093     # var1->name = "var1"
    38094     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
    38095     (copy-array Heap "var1" %eax)
    38096 $test-compare-mem-with-reg:initialize-var2:
    38097     # var var2/edx: (payload var)
    38098     68/push 0/imm32/register
    38099     68/push 0/imm32/register
    38100     68/push 0/imm32/no-stack-offset
    38101     68/push 1/imm32/block-depth
    38102     ff 6/subop/push *(ecx+0x10)
    38103     68/push 0x11/imm32/alloc-id:fake
    38104     68/push 0/imm32/name
    38105     68/push 0/imm32/name
    38106     68/push 0x11/imm32/alloc-id:fake:payload
    38107     89/<- %edx 4/r32/esp
    38108 $test-compare-mem-with-reg:initialize-var2-name:
    38109     # var2->name = "var2"
    38110     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
    38111     (copy-array Heap "var2" %eax)
    38112 $test-compare-mem-with-reg:initialize-var2-register:
    38113     # var2->register = "eax"
    38114     8d/copy-address *(edx+0x1c) 0/r32/eax  # Var-register + 4
    38115     (copy-array Heap "eax" %eax)
    38116 $test-compare-mem-with-reg:initialize-inouts:
    38117     # var inouts/esi: (payload stmt-var) = [var2]
    38118     68/push 0/imm32/is-deref:false
    38119     68/push 0/imm32/next
    38120     68/push 0/imm32/next
    38121     52/push-edx/var2
    38122     68/push 0x11/imm32/alloc-id:fake
    38123     68/push 0x11/imm32/alloc-id:fake:payload
    38124     89/<- %esi 4/r32/esp
    38125     # inouts = [var1, var2]
    38126     68/push 0/imm32/is-deref:false
    38127     56/push-esi/next
    38128     68/push 0x11/imm32/alloc-id:fake
    38129     51/push-ecx/var1
    38130     68/push 0x11/imm32/alloc-id:fake
    38131     68/push 0x11/imm32/alloc-id:fake:payload
    38132     89/<- %esi 4/r32/esp
    38133 $test-compare-mem-with-reg:initialize-stmt:
    38134     # var stmt/esi: (addr statement)
    38135     68/push 0/imm32/next
    38136     68/push 0/imm32/next
    38137     68/push 0/imm32/outputs
    38138     68/push 0/imm32/outputs
    38139     56/push-esi/inouts
    38140     68/push 0x11/imm32/alloc-id:fake
    38141     68/push 0/imm32/operation
    38142     68/push 0/imm32/operation
    38143     68/push 1/imm32/tag:stmt1
    38144     89/<- %esi 4/r32/esp
    38145 $test-compare-mem-with-reg:initialize-stmt-operation:
    38146     # stmt->operation = "compare"
    38147     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
    38148     (copy-array Heap "compare" %eax)
    38149     # convert
    38150     c7 0/subop/copy *Curr-block-depth 0/imm32
    38151     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
    38152     (flush _test-output-buffered-file)
    38153 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
    38159     # check output
    38160     (check-next-stream-line-equal _test-output-stream "39/compare-> *(ebp+0x00000008) 0x00000000/r32" "F - test-compare-mem-with-reg")
    38161     # . epilogue
    38162     89/<- %esp 5/r32/ebp
    38163     5d/pop-to-ebp
    38164     c3/return
    38165
    38166 test-compare-reg-with-mem:
    38167     #   compare var1/eax, var2
    38168     # =>
    38169     #   3b/compare<- *(ebp+___) 0/r32/eax
    38170     #
    38171     # . prologue
    38172     55/push-ebp
    38173     89/<- %ebp 4/r32/esp
    38174     # setup
    38175     (clear-stream _test-output-stream)
    38176     (clear-stream $_test-output-buffered-file->buffer)
    38177 $test-compare-reg-with-mem:initialize-type:
    38178     # var type/ecx: (payload type-tree) = int
    38179     68/push 0/imm32/right:null
    38180     68/push 0/imm32/right:null
    38181     68/push 0/imm32/left:unused
    38182     68/push 1/imm32/value:int
    38183     68/push 1/imm32/is-atom?:true
    38184     68/push 0x11/imm32/alloc-id:fake:payload
    38185     89/<- %ecx 4/r32/esp
    38186 $test-compare-reg-with-mem:initialize-var1:
    38187     # var var1/ecx: (payload var)
    38188     68/push 0/imm32/register
    38189     68/push 0/imm32/register
    38190     68/push 0/imm32/no-stack-offset
    38191     68/push 1/imm32/block-depth
    38192     51/push-ecx
    38193     68/push 0x11/imm32/alloc-id:fake
    38194     68/push 0/imm32/name
    38195     68/push 0/imm32/name
    38196     68/push 0x11/imm32/alloc-id:fake:payload
    38197     89/<- %ecx 4/r32/esp
    38198 $test-compare-reg-with-mem:initialize-var1-name:
    38199     # var1->name = "var1"
    38200     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
    38201     (copy-array Heap "var1" %eax)
    38202 $test-compare-reg-with-mem:initialize-var1-register:
    38203     # var1->register = "eax"
    38204     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
    38205     (copy-array Heap "eax" %eax)
    38206 $test-compare-reg-with-mem:initialize-var2:
    38207     # var var2/edx: (payload var)
    38208     68/push 0/imm32/register
    38209     68/push 0/imm32/register
    38210     68/push 8/imm32/stack-offset
    38211     68/push 1/imm32/block-depth
    38212     ff 6/subop/push *(ecx+0x10)
    38213     68/push 0x11/imm32/alloc-id:fake
    38214     68/push 0/imm32/name
    38215     68/push 0/imm32/name
    38216     68/push 0x11/imm32/alloc-id:fake:payload
    38217     89/<- %edx 4/r32/esp
    38218 $test-compare-reg-with-mem:initialize-var2-name:
    38219     # var2->name = "var2"
    38220     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
    38221     (copy-array Heap "var2" %eax)
    38222 $test-compare-reg-with-mem:initialize-inouts:
    38223     # var inouts/esi: (payload stmt-var) = [var2]
    38224     68/push 0/imm32/is-deref:false
    38225     68/push 0/imm32/next
    38226     68/push 0/imm32/next
    38227     52/push-edx/var2
    38228     68/push 0x11/imm32/alloc-id:fake
    38229     68/push 0x11/imm32/alloc-id:fake:payload
    38230     89/<- %esi 4/r32/esp
    38231     # inouts = [var1, var2]
    38232     68/push 0/imm32/is-deref:false
    38233     56/push-esi/next
    38234     68/push 0x11/imm32/alloc-id:fake
    38235     51/push-ecx/var1
    38236     68/push 0x11/imm32/alloc-id:fake
    38237     68/push 0x11/imm32/alloc-id:fake:payload
    38238     89/<- %esi 4/r32/esp
    38239 $test-compare-reg-with-mem:initialize-stmt:
    38240     # var stmt/esi: (addr statement)
    38241     68/push 0/imm32/next
    38242     68/push 0/imm32/next
    38243     68/push 0/imm32/outputs
    38244     68/push 0/imm32/outputs
    38245     56/push-esi/inouts
    38246     68/push 0x11/imm32/alloc-id:fake
    38247     68/push 0/imm32/operation
    38248     68/push 0/imm32/operation
    38249     68/push 1/imm32/tag:stmt1
    38250     89/<- %esi 4/r32/esp
    38251 $test-compare-reg-with-mem:initialize-stmt-operation:
    38252     # stmt->operation = "compare"
    38253     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
    38254     (copy-array Heap "compare" %eax)
    38255     # convert
    38256     c7 0/subop/copy *Curr-block-depth 0/imm32
    38257     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
    38258     (flush _test-output-buffered-file)
    38259 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
    38265     # check output
    38266     (check-next-stream-line-equal _test-output-stream "3b/compare<- *(ebp+0x00000008) 0x00000000/r32" "F - test-compare-reg-with-mem")
    38267     # . epilogue
    38268     89/<- %esp 5/r32/ebp
    38269     5d/pop-to-ebp
    38270     c3/return
    38271
    38272 test-compare-mem-with-literal:
    38273     #   compare var1, 0x34
    38274     # =>
    38275     #   81 7/subop/compare *(ebp+___) 0x34/imm32
    38276     #
    38277     # . prologue
    38278     55/push-ebp
    38279     89/<- %ebp 4/r32/esp
    38280     # setup
    38281     (clear-stream _test-output-stream)
    38282     (clear-stream $_test-output-buffered-file->buffer)
    38283 $test-compare-mem-with-literal:initialize-type:
    38284     # var type/ecx: (payload type-tree) = int
    38285     68/push 0/imm32/right:null
    38286     68/push 0/imm32/right:null
    38287     68/push 0/imm32/left:unused
    38288     68/push 1/imm32/value:int
    38289     68/push 1/imm32/is-atom?:true
    38290     68/push 0x11/imm32/alloc-id:fake:payload
    38291     89/<- %ecx 4/r32/esp
    38292 $test-compare-mem-with-literal:initialize-var1:
    38293     # var var1/ecx: (payload var)
    38294     68/push 0/imm32/register
    38295     68/push 0/imm32/register
    38296     68/push 8/imm32/stack-offset
    38297     68/push 1/imm32/block-depth
    38298     51/push-ecx
    38299     68/push 0x11/imm32/alloc-id:fake
    38300     68/push 0/imm32/name
    38301     68/push 0/imm32/name
    38302     68/push 0x11/imm32/alloc-id:fake:payload
    38303     89/<- %ecx 4/r32/esp
    38304 $test-compare-mem-with-literal:initialize-var1-name:
    38305     # var1->name = "var1"
    38306     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
    38307     (copy-array Heap "var1" %eax)
    38308 $test-compare-mem-with-literal:initialize-literal-type:
    38309     # var type/edx: (payload type-tree) = literal
    38310     68/push 0/imm32/right:null
    38311     68/push 0/imm32/right:null
    38312     68/push 0/imm32/left:unused
    38313     68/push 0/imm32/value:literal
    38314     68/push 1/imm32/is-atom?:true
    38315     68/push 0x11/imm32/alloc-id:fake:payload
    38316     89/<- %edx 4/r32/esp
    38317 $test-compare-mem-with-literal:initialize-literal:
    38318     # var l/edx: (payload var)
    38319     68/push 0/imm32/register
    38320     68/push 0/imm32/register
    38321     68/push 0/imm32/no-stack-offset
    38322     68/push 1/imm32/block-depth
    38323     52/push-edx
    38324     68/push 0x11/imm32/alloc-id:fake
    38325     68/push 0/imm32/name
    38326     68/push 0/imm32/name
    38327     68/push 0x11/imm32/alloc-id:fake:payload
    38328     89/<- %edx 4/r32/esp
    38329 $test-compare-mem-with-literal:initialize-literal-value:
    38330     # l->name = "0x34"
    38331     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
    38332     (copy-array Heap "0x34" %eax)
    38333 $test-compare-mem-with-literal:initialize-inouts:
    38334     # var inouts/esi: (payload stmt-var) = [l]
    38335     68/push 0/imm32/is-deref:false
    38336     68/push 0/imm32/next
    38337     68/push 0/imm32/next
    38338     52/push-edx/l
    38339     68/push 0x11/imm32/alloc-id:fake
    38340     68/push 0x11/imm32/alloc-id:fake:payload
    38341     89/<- %esi 4/r32/esp
    38342     # var inouts = (handle stmt-var) = [var1, var2]
    38343     68/push 0/imm32/is-deref:false
    38344     56/push-esi/next
    38345     68/push 0x11/imm32/alloc-id:fake
    38346     51/push-ecx/var1
    38347     68/push 0x11/imm32/alloc-id:fake
    38348     68/push 0x11/imm32/alloc-id:fake:payload
    38349     89/<- %esi 4/r32/esp
    38350 $test-compare-mem-with-literal:initialize-stmt:
    38351     # var stmt/esi: (addr statement)
    38352     68/push 0/imm32/next
    38353     68/push 0/imm32/next
    38354     68/push 0/imm32/outputs
    38355     68/push 0/imm32/outputs
    38356     56/push-esi/inouts
    38357     68/push 0x11/imm32/alloc-id:fake
    38358     68/push 0/imm32/operation
    38359     68/push 0/imm32/operation
    38360     68/push 1/imm32/tag:stmt1
    38361     89/<- %esi 4/r32/esp
    38362 $test-compare-mem-with-literal:initialize-stmt-operation:
    38363     # stmt->operation = "compare"
    38364     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
    38365     (copy-array Heap "compare" %eax)
    38366     # convert
    38367     c7 0/subop/copy *Curr-block-depth 0/imm32
    38368     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
    38369     (flush _test-output-buffered-file)
    38370 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
    38376     # check output
    38377     (check-next-stream-line-equal _test-output-stream "81 7/subop/compare *(ebp+0x00000008) 0x34/imm32" "F - test-compare-mem-with-literal")
    38378     # . epilogue
    38379     89/<- %esp 5/r32/ebp
    38380     5d/pop-to-ebp
    38381     c3/return
    38382
    38383 test-compare-eax-with-literal:
    38384     #   compare var1/eax 0x34
    38385     # =>
    38386     #   3d/compare-eax-with 0x34/imm32
    38387     #
    38388     # . prologue
    38389     55/push-ebp
    38390     89/<- %ebp 4/r32/esp
    38391     # setup
    38392     (clear-stream _test-output-stream)
    38393     (clear-stream $_test-output-buffered-file->buffer)
    38394 $test-compare-eax-with-literal:initialize-type:
    38395     # var type/ecx: (payload type-tree) = int
    38396     68/push 0/imm32/right:null
    38397     68/push 0/imm32/right:null
    38398     68/push 0/imm32/left:unused
    38399     68/push 1/imm32/value:int
    38400     68/push 1/imm32/is-atom?:true
    38401     68/push 0x11/imm32/alloc-id:fake:payload
    38402     89/<- %ecx 4/r32/esp
    38403 $test-compare-eax-with-literal:initialize-var1:
    38404     # var var1/ecx: (payload var)
    38405     68/push 0/imm32/register
    38406     68/push 0/imm32/register
    38407     68/push 0/imm32/no-stack-offset
    38408     68/push 1/imm32/block-depth
    38409     51/push-ecx
    38410     68/push 0x11/imm32/alloc-id:fake
    38411     68/push 0/imm32/name
    38412     68/push 0/imm32/name
    38413     68/push 0x11/imm32/alloc-id:fake:payload
    38414     89/<- %ecx 4/r32/esp
    38415 $test-compare-eax-with-literal:initialize-var1-name:
    38416     # var1->name = "var1"
    38417     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
    38418     (copy-array Heap "var1" %eax)
    38419 $test-compare-eax-with-literal:initialize-var1-register:
    38420     # v->register = "eax"
    38421     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
    38422     (copy-array Heap "eax" %eax)
    38423 $test-compare-eax-with-literal:initialize-literal-type:
    38424     # var type/edx: (payload type-tree) = literal
    38425     68/push 0/imm32/right:null
    38426     68/push 0/imm32/right:null
    38427     68/push 0/imm32/left:unused
    38428     68/push 0/imm32/value:literal
    38429     68/push 1/imm32/is-atom?:true
    38430     68/push 0x11/imm32/alloc-id:fake:payload
    38431     89/<- %edx 4/r32/esp
    38432 $test-compare-eax-with-literal:initialize-literal:
    38433     # var l/edx: (payload var)
    38434     68/push 0/imm32/register
    38435     68/push 0/imm32/register
    38436     68/push 0/imm32/no-stack-offset
    38437     68/push 1/imm32/block-depth
    38438     52/push-edx
    38439     68/push 0x11/imm32/alloc-id:fake
    38440     68/push 0/imm32/name
    38441     68/push 0/imm32/name
    38442     68/push 0x11/imm32/alloc-id:fake:payload
    38443     89/<- %edx 4/r32/esp
    38444 $test-compare-eax-with-literal:initialize-literal-value:
    38445     # l->name = "0x34"
    38446     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
    38447     (copy-array Heap "0x34" %eax)
    38448 $test-compare-eax-with-literal:initialize-inouts:
    38449     # var inouts/esi: (payload stmt-var) = [l]
    38450     68/push 0/imm32/is-deref:false
    38451     68/push 0/imm32/next
    38452     68/push 0/imm32/next
    38453     52/push-edx/l
    38454     68/push 0x11/imm32/alloc-id:fake
    38455     68/push 0x11/imm32/alloc-id:fake:payload
    38456     89/<- %esi 4/r32/esp
    38457     # var inouts = (handle stmt-var) = [var1, var2]
    38458     68/push 0/imm32/is-deref:false
    38459     56/push-esi/next
    38460     68/push 0x11/imm32/alloc-id:fake
    38461     51/push-ecx/var1
    38462     68/push 0x11/imm32/alloc-id:fake
    38463     68/push 0x11/imm32/alloc-id:fake:payload
    38464     89/<- %esi 4/r32/esp
    38465 $test-compare-eax-with-literal:initialize-stmt:
    38466     # var stmt/esi: (addr statement)
    38467     68/push 0/imm32/next
    38468     68/push 0/imm32/next
    38469     68/push 0/imm32/outputs
    38470     68/push 0/imm32/outputs
    38471     56/push-esi/inouts
    38472     68/push 0x11/imm32/alloc-id:fake
    38473     68/push 0/imm32/operation
    38474     68/push 0/imm32/operation
    38475     68/push 1/imm32/tag:stmt1
    38476     89/<- %esi 4/r32/esp
    38477 $test-compare-eax-with-literal:initialize-stmt-operation:
    38478     # stmt->operation = "compare"
    38479     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
    38480     (copy-array Heap "compare" %eax)
    38481     # convert
    38482     c7 0/subop/copy *Curr-block-depth 0/imm32
    38483     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
    38484     (flush _test-output-buffered-file)
    38485 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
    38491     # check output
    38492     (check-next-stream-line-equal _test-output-stream "3d/compare-eax-with 0x34/imm32" "F - test-compare-eax-with-literal")
    38493     # . epilogue
    38494     89/<- %esp 5/r32/ebp
    38495     5d/pop-to-ebp
    38496     c3/return
    38497
    38498 test-compare-reg-with-literal:
    38499     #   compare var1/ecx 0x34
    38500     # =>
    38501     #   81 7/subop/compare %ecx 0x34/imm32
    38502     #
    38503     # . prologue
    38504     55/push-ebp
    38505     89/<- %ebp 4/r32/esp
    38506     # setup
    38507     (clear-stream _test-output-stream)
    38508     (clear-stream $_test-output-buffered-file->buffer)
    38509 $test-compare-reg-with-literal:initialize-type:
    38510     # var type/ecx: (payload type-tree) = int
    38511     68/push 0/imm32/right:null
    38512     68/push 0/imm32/right:null
    38513     68/push 0/imm32/left:unused
    38514     68/push 1/imm32/value:int
    38515     68/push 1/imm32/is-atom?:true
    38516     68/push 0x11/imm32/alloc-id:fake:payload
    38517     89/<- %ecx 4/r32/esp
    38518 $test-compare-reg-with-literal:initialize-var1:
    38519     # var var1/ecx: (payload var)
    38520     68/push 0/imm32/register
    38521     68/push 0/imm32/register
    38522     68/push 0/imm32/no-stack-offset
    38523     68/push 1/imm32/block-depth
    38524     51/push-ecx
    38525     68/push 0x11/imm32/alloc-id:fake
    38526     68/push 0/imm32/name
    38527     68/push 0/imm32/name
    38528     68/push 0x11/imm32/alloc-id:fake:payload
    38529     89/<- %ecx 4/r32/esp
    38530 $test-compare-reg-with-literal:initialize-var1-name:
    38531     # var1->name = "var1"
    38532     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
    38533     (copy-array Heap "var1" %eax)
    38534 $test-compare-reg-with-literal:initialize-var1-register:
    38535     # v->register = "ecx"
    38536     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
    38537     (copy-array Heap "ecx" %eax)
    38538 $test-compare-reg-with-literal:initialize-literal-type:
    38539     # var type/edx: (payload type-tree) = literal
    38540     68/push 0/imm32/right:null
    38541     68/push 0/imm32/right:null
    38542     68/push 0/imm32/left:unused
    38543     68/push 0/imm32/value:literal
    38544     68/push 1/imm32/is-atom?:true
    38545     68/push 0x11/imm32/alloc-id:fake:payload
    38546     89/<- %edx 4/r32/esp
    38547 $test-compare-reg-with-literal:initialize-literal:
    38548     # var l/edx: (payload var)
    38549     68/push 0/imm32/register
    38550     68/push 0/imm32/register
    38551     68/push 0/imm32/no-stack-offset
    38552     68/push 1/imm32/block-depth
    38553     52/push-edx
    38554     68/push 0x11/imm32/alloc-id:fake
    38555     68/push 0/imm32/name
    38556     68/push 0/imm32/name
    38557     68/push 0x11/imm32/alloc-id:fake:payload
    38558     89/<- %edx 4/r32/esp
    38559 $test-compare-reg-with-literal:initialize-literal-value:
    38560     # l->name = "0x34"
    38561     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
    38562     (copy-array Heap "0x34" %eax)
    38563 $test-compare-reg-with-literal:initialize-inouts:
    38564     # var inouts/esi: (payload stmt-var) = [l]
    38565     68/push 0/imm32/is-deref:false
    38566     68/push 0/imm32/next
    38567     68/push 0/imm32/next
    38568     52/push-edx/l
    38569     68/push 0x11/imm32/alloc-id:fake
    38570     68/push 0x11/imm32/alloc-id:fake:payload
    38571     89/<- %esi 4/r32/esp
    38572     # var inouts = (handle stmt-var) = [var1, var2]
    38573     68/push 0/imm32/is-deref:false
    38574     56/push-esi/next
    38575     68/push 0x11/imm32/alloc-id:fake
    38576     51/push-ecx/var1
    38577     68/push 0x11/imm32/alloc-id:fake
    38578     68/push 0x11/imm32/alloc-id:fake:payload
    38579     89/<- %esi 4/r32/esp
    38580 $test-compare-reg-with-literal:initialize-stmt:
    38581     # var stmt/esi: (addr statement)
    38582     68/push 0/imm32/next
    38583     68/push 0/imm32/next
    38584     68/push 0/imm32/outputs
    38585     68/push 0/imm32/outputs
    38586     56/push-esi/inouts
    38587     68/push 0x11/imm32/alloc-id:fake
    38588     68/push 0/imm32/operation
    38589     68/push 0/imm32/operation
    38590     68/push 1/imm32/tag:stmt1
    38591     89/<- %esi 4/r32/esp
    38592 $test-compare-reg-with-literal:initialize-stmt-operation:
    38593     # stmt->operation = "compare"
    38594     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
    38595     (copy-array Heap "compare" %eax)
    38596     # convert
    38597     c7 0/subop/copy *Curr-block-depth 0/imm32
    38598     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
    38599     (flush _test-output-buffered-file)
    38600 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
    38606     # check output
    38607     (check-next-stream-line-equal _test-output-stream "81 7/subop/compare %ecx 0x34/imm32" "F - test-compare-reg-with-literal")
    38608     # . epilogue
    38609     89/<- %esp 5/r32/ebp
    38610     5d/pop-to-ebp
    38611     c3/return
    38612
    38613 test-emit-subx-stmt-function-call:
    38614     # Call a function on a variable on the stack.
    38615     #   f foo
    38616     # =>
    38617     #   (f *(ebp-8))
    38618     # (Changing the function name supports overloading in general, but here it
    38619     # just serves to help disambiguate things.)
    38620     #
    38621     # There's a variable on the var stack as follows:
    38622     #   name: 'foo'
    38623     #   type: int
    38624     #   stack-offset: -8
    38625     #
    38626     # There's nothing in primitives.
    38627     #
    38628     # We don't perform any checking here on the type of 'f'.
    38629     #
    38630     # . prologue
    38631     55/push-ebp
    38632     89/<- %ebp 4/r32/esp
    38633     # setup
    38634     (clear-stream _test-output-stream)
    38635     (clear-stream $_test-output-buffered-file->buffer)
    38636 $test-emit-subx-function-call:initialize-type:
    38637     # var type/ecx: (payload type-tree) = int
    38638     68/push 0/imm32/right:null
    38639     68/push 0/imm32/right:null
    38640     68/push 0/imm32/left:unused
    38641     68/push 1/imm32/value:int
    38642     68/push 1/imm32/is-atom?:true
    38643     68/push 0x11/imm32/alloc-id:fake:payload
    38644     89/<- %ecx 4/r32/esp
    38645 $test-emit-subx-function-call:initialize-var:
    38646     # var var-foo/ecx: (payload var) = var(type)
    38647     68/push 0/imm32/no-register
    38648     68/push 0/imm32/no-register
    38649     68/push -8/imm32/stack-offset
    38650     68/push 1/imm32/block-depth
    38651     51/push-ecx/type
    38652     68/push 0x11/imm32/alloc-id:fake
    38653     68/push 0/imm32/name
    38654     68/push 0/imm32/name
    38655     68/push 0x11/imm32/alloc-id:fake:payload
    38656     89/<- %ecx 4/r32/esp
    38657 $test-emit-subx-function-call:initialize-var-name:
    38658     # var-foo->name = "foo"
    38659     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
    38660     (copy-array Heap "foo" %eax)
    38661 $test-emit-subx-function-call:initialize-stmt-var:
    38662     # var operand/ebx: (payload stmt-var) = stmt-var(var-foo)
    38663     68/push 0/imm32/is-deref:false
    38664     68/push 0/imm32/next
    38665     68/push 0/imm32/next
    38666     51/push-ecx/var-foo
    38667     68/push 0x11/imm32/alloc-id:fake
    38668     68/push 0x11/imm32/alloc-id:fake:payload
    38669     89/<- %ebx 4/r32/esp
    38670 $test-emit-subx-function-call:initialize-stmt:
    38671     # var stmt/esi: (addr statement)
    38672     68/push 0/imm32/no-outputs
    38673     68/push 0/imm32/no-outputs
    38674     53/push-ebx/inouts
    38675     68/push 0x11/imm32/alloc-id:fake
    38676     68/push 0/imm32/operation
    38677     68/push 0/imm32/operation
    38678     68/push 1/imm32/tag
    38679     89/<- %esi 4/r32/esp
    38680 $test-emit-subx-function-call:initialize-stmt-operation:
    38681     # stmt->operation = "f"
    38682     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
    38683     (copy-array Heap "f" %eax)
    38684     # convert
    38685     c7 0/subop/copy *Curr-block-depth 0/imm32
    38686     (emit-subx-stmt _test-output-buffered-file %esi 0 0 Stderr 0)
    38687     (flush _test-output-buffered-file)
    38688 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
    38694     # check output
    38695     (check-next-stream-line-equal _test-output-stream "(f *(ebp+0xfffffff8))" "F - test-emit-subx-stmt-function-call")
    38696     # . epilogue
    38697     89/<- %esp 5/r32/ebp
    38698     5d/pop-to-ebp
    38699     c3/return
    38700
    38701 test-emit-subx-stmt-function-call-with-literal-arg:
    38702     # Call a function on a literal.
    38703     #   f 0x34
    38704     # =>
    38705     #   (f2 0x34)
    38706     #
    38707     # . prologue
    38708     55/push-ebp
    38709     89/<- %ebp 4/r32/esp
    38710     # setup
    38711     (clear-stream _test-output-stream)
    38712     (clear-stream $_test-output-buffered-file->buffer)
    38713 $test-emit-subx-function-call-with-literal-arg:initialize-type:
    38714     # var type/ecx: (payload type-tree) = int
    38715     68/push 0/imm32/right:null
    38716     68/push 0/imm32/right:null
    38717     68/push 0/imm32/left:unused
    38718     68/push 0/imm32/value:literal
    38719     68/push 1/imm32/is-atom?:true
    38720     68/push 0x11/imm32/alloc-id:fake:payload
    38721     89/<- %ecx 4/r32/esp
    38722 $test-emit-subx-function-call-with-literal-arg:initialize-var:
    38723     # var var-foo/ecx: (payload var) = var(lit)
    38724     68/push 0/imm32/no-register
    38725     68/push 0/imm32/no-register
    38726     68/push 0/imm32/no-stack-offset
    38727     68/push 1/imm32/block-depth
    38728     51/push-ecx/type
    38729     68/push 0x11/imm32/alloc-id:fake
    38730     68/push 0/imm32/name
    38731     68/push 0/imm32/name
    38732     68/push 0x11/imm32/alloc-id:fake:payload
    38733     89/<- %ecx 4/r32/esp
    38734 $test-emit-subx-function-call-with-literal-arg:initialize-var-name:
    38735     # var-foo->name = "0x34"
    38736     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
    38737     (copy-array Heap "0x34" %eax)
    38738 $test-emit-subx-function-call-with-literal-arg:initialize-stmt-var:
    38739     # var operand/ebx: (payload stmt-var) = stmt-var(var-foo)
    38740     68/push 0/imm32/is-deref:false
    38741     68/push 0/imm32/next
    38742     68/push 0/imm32/next
    38743     51/push-ecx/var-foo
    38744     68/push 0x11/imm32/alloc-id:fake
    38745     68/push 0x11/imm32/alloc-id:fake:payload
    38746     89/<- %ebx 4/r32/esp
    38747 $test-emit-subx-function-call-with-literal-arg:initialize-stmt:
    38748     # var stmt/esi: (addr statement)
    38749     68/push 0/imm32/no-outputs
    38750     68/push 0/imm32/no-outputs
    38751     53/push-ebx/inouts
    38752     68/push 0x11/imm32/alloc-id:fake
    38753     68/push 0/imm32/operation
    38754     68/push 0/imm32/operation
    38755     68/push 1/imm32/tag
    38756     89/<- %esi 4/r32/esp
    38757 $test-emit-subx-function-call-with-literal-arg:initialize-stmt-operation:
    38758     # stmt->operation = "f"
    38759     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
    38760     (copy-array Heap "f" %eax)
    38761     # convert
    38762     c7 0/subop/copy *Curr-block-depth 0/imm32
    38763     (emit-subx-stmt _test-output-buffered-file %esi 0 %ebx 0 Stderr 0)
    38764     (flush _test-output-buffered-file)
    38765 +--  6 lines: #?     # dump _test-output-stream -----------------------------------------------------------------------------------------------------------------------------------------
    38771     # check output
    38772     (check-next-stream-line-equal _test-output-stream "(f 0x34)" "F - test-emit-subx-stmt-function-call-with-literal-arg")
    38773     # . epilogue
    38774     89/<- %esp 5/r32/ebp
    38775     5d/pop-to-ebp
    38776     c3/return
    38777
    38778 emit-indent:  # out: (addr buffered-file), n: int
    38779     # . prologue
    38780     55/push-ebp
    38781     89/<- %ebp 4/r32/esp
    38782     # . save registers
    38783     50/push-eax
    38784     # var i/eax: int = n
    38785     8b/-> *(ebp+0xc) 0/r32/eax
    38786     {
    38787       # if (i <= 0) break
    38788       3d/compare-eax-with 0/imm32
    38789       7e/jump-if-<= break/disp8
    38790       (write-buffered *(ebp+8) "  ")
    38791       48/decrement-eax
    38792       eb/jump loop/disp8
    38793     }
    38794 $emit-indent:end:
    38795     # . restore registers
    38796     58/pop-to-eax
    38797     # . epilogue
    38798     89/<- %esp 5/r32/ebp
    38799     5d/pop-to-ebp
    38800     c3/return
    38801
    38802 emit-subx-prologue:  # out: (addr buffered-file)
    38803     # . prologue
    38804     55/push-ebp
    38805     89/<- %ebp 4/r32/esp
    38806     #
    38807     (write-buffered *(ebp+8) "  # . prologue\n")
    38808     (write-buffered *(ebp+8) "  55/push-ebp\n")
    38809     (write-buffered *(ebp+8) "  89/<- %ebp 4/r32/esp\n")
    38810 $emit-subx-prologue:end:
    38811     # . epilogue
    38812     89/<- %esp 5/r32/ebp
    38813     5d/pop-to-ebp
    38814     c3/return
    38815
    38816 emit-subx-epilogue:  # out: (addr buffered-file)
    38817     # . prologue
    38818     55/push-ebp
    38819     89/<- %ebp 4/r32/esp
    38820     #
    38821     (write-buffered *(ebp+8) "  # . epilogue\n")
    38822     (write-buffered *(ebp+8) "  89/<- %esp 5/r32/ebp\n")
    38823     (write-buffered *(ebp+8) "  5d/pop-to-ebp\n")
    38824     (write-buffered *(ebp+8) "  c3/return\n")
    38825 $emit-subx-epilogue:end:
    38826     # . epilogue
    38827     89/<- %esp 5/r32/ebp
    38828     5d/pop-to-ebp
    38829     c3/return