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-literal-string-arg-and-type-parameter-in-signature:
     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 "  string-func \"abc\"\n")
     2279     (write _test-input-stream "}\n")
     2280     (write _test-input-stream "sig string-func in: (addr array _)\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-null-addr:
     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 foo {\n")
     2301     (write _test-input-stream "  bar 0\n")
     2302     (write _test-input-stream "}\n")
     2303     (write _test-input-stream "sig bar in: (addr int)\n")
     2304     # convert
     2305     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     2306     # no errors
     2307     # not bothering checking output
     2308     # . epilogue
     2309     89/<- %esp 5/r32/ebp
     2310     5d/pop-to-ebp
     2311     c3/return
     2312
     2313 test-convert-function-call-with-signature:
     2314     # . prologue
     2315     55/push-ebp
     2316     89/<- %ebp 4/r32/esp
     2317     # setup
     2318     (clear-stream _test-input-stream)
     2319     (clear-stream $_test-input-buffered-file->buffer)
     2320     (clear-stream _test-output-stream)
     2321     (clear-stream $_test-output-buffered-file->buffer)
     2322     #
     2323     (write _test-input-stream "fn main -> _/ebx: int {\n")
     2324     (write _test-input-stream "  var result/eax: int <- do-add 3 4\n")
     2325     (write _test-input-stream "  return result\n")
     2326     (write _test-input-stream "}\n")
     2327     (write _test-input-stream "sig do-add a: int, b: int -> _/eax: int\n")
     2328     # convert
     2329     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     2330     (flush _test-output-buffered-file)
     2331 +--  6 lines: #?     # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------
     2337     # check output
     2338     (check-next-stream-line-equal _test-output-stream "main:"                   "F - test-convert-function-call-with-signature/0")
     2339     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-signature/1")
     2340     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-signature/2")
     2341     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call-with-signature/3")
     2342     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-signature/4")
     2343     (check-next-stream-line-equal _test-output-stream "$main:0x00000001:loop:"  "F - test-convert-function-call-with-signature/5")
     2344     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-call-with-literal-arg/6")
     2345     (check-next-stream-line-equal _test-output-stream "    (do-add 3 4)"        "F - test-convert-function-call-with-signature/6")
     2346     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000003/r32" "F - test-convert-function-call-with-literal-arg/8")
     2347     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax" "F - test-convert-function-with-local-var-in-reg/9")
     2348     (check-next-stream-line-equal _test-output-stream "    e9/jump $main:0x00000001:break/disp32"  "F - test-convert-function-call-with-literal-arg/10")
     2349     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-signature/7")
     2350     (check-next-stream-line-equal _test-output-stream "$main:0x00000001:break:" "F - test-convert-function-call-with-signature/8")
     2351     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-signature/9")
     2352     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call-with-signature/10")
     2353     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-signature/11")
     2354     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-signature/12")
     2355     # . epilogue
     2356     89/<- %esp 5/r32/ebp
     2357     5d/pop-to-ebp
     2358     c3/return
     2359
     2360 test-convert-function-with-local-var-in-mem:
     2361     # . prologue
     2362     55/push-ebp
     2363     89/<- %ebp 4/r32/esp
     2364     # setup
     2365     (clear-stream _test-input-stream)
     2366     (clear-stream $_test-input-buffered-file->buffer)
     2367     (clear-stream _test-output-stream)
     2368     (clear-stream $_test-output-buffered-file->buffer)
     2369     #
     2370     (write _test-input-stream "fn foo {\n")
     2371     (write _test-input-stream "  var x: int\n")
     2372     (write _test-input-stream "  increment x\n")
     2373     (write _test-input-stream "}\n")
     2374     # convert
     2375     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     2376     (flush _test-output-buffered-file)
     2377 +--  6 lines: #?     # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------
     2383     # check output
     2384     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-in-mem/0")
     2385     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-in-mem/1")
     2386     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-in-mem/2")
     2387     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-in-mem/3")
     2388     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-in-mem/4")
     2389     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-in-mem/5")
     2390     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-with-local-var-in-mem/6")
     2391     (check-next-stream-line-equal _test-output-stream "    ff 0/subop/increment *(ebp+0xfffffffc)"  "F - test-convert-function-with-local-var-in-mem/7")
     2392     (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")
     2393     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-in-mem/9")
     2394     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-in-mem/10")
     2395     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-in-mem/11")
     2396     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-in-mem/12")
     2397     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-in-mem/13")
     2398     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-in-mem/14")
     2399     # . epilogue
     2400     89/<- %esp 5/r32/ebp
     2401     5d/pop-to-ebp
     2402     c3/return
     2403
     2404 test-convert-invalid-literal:
     2405     # . prologue
     2406     55/push-ebp
     2407     89/<- %ebp 4/r32/esp
     2408     # setup
     2409     (clear-stream _test-input-stream)
     2410     (clear-stream $_test-input-buffered-file->buffer)
     2411     (clear-stream _test-output-stream)
     2412     (clear-stream $_test-output-buffered-file->buffer)
     2413     (clear-stream _test-error-stream)
     2414     (clear-stream $_test-error-buffered-file->buffer)
     2415     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     2416     68/push 0/imm32
     2417     68/push 0/imm32
     2418     89/<- %edx 4/r32/esp
     2419     (tailor-exit-descriptor %edx 0x10)
     2420     #
     2421     (write _test-input-stream "fn foo {\n")
     2422     (write _test-input-stream "  increment 1n\n")
     2423     (write _test-input-stream "}\n")
     2424     # convert
     2425     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     2426     # registers except esp clobbered at this point
     2427     # restore ed
     2428     89/<- %edx 4/r32/esp
     2429     (flush _test-output-buffered-file)
     2430     (flush _test-error-buffered-file)
     2431 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
     2437     # check output
     2438     (check-stream-equal _test-output-stream  ""  "F - test-convert-invalid-literal: output should be empty")
     2439     (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")
     2440     # check that stop(1) was called
     2441     (check-ints-equal *(edx+4) 2 "F - test-convert-invalid-literal: exit status")
     2442     # don't restore from ebp
     2443     81 0/subop/add %esp 8/imm32
     2444     # . epilogue
     2445     5d/pop-to-ebp
     2446     c3/return
     2447
     2448 test-convert-valid-literal-with-metadata:
     2449     # . prologue
     2450     55/push-ebp
     2451     89/<- %ebp 4/r32/esp
     2452     # setup
     2453     (clear-stream _test-input-stream)
     2454     (clear-stream $_test-input-buffered-file->buffer)
     2455     (clear-stream _test-output-stream)
     2456     (clear-stream $_test-output-buffered-file->buffer)
     2457     #
     2458     (write _test-input-stream "fn foo {\n")
     2459     (write _test-input-stream "  var x/eax: int <- copy 1/abc\n")
     2460     (write _test-input-stream "}\n")
     2461     # convert
     2462     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     2463     (flush _test-output-buffered-file)
     2464 +--  6 lines: #?     # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------
     2470     # no errors
     2471     # . epilogue
     2472     89/<- %esp 5/r32/ebp
     2473     5d/pop-to-ebp
     2474     c3/return
     2475
     2476 test-local-var-in-mem-has-no-initializer:
     2477     # . prologue
     2478     55/push-ebp
     2479     89/<- %ebp 4/r32/esp
     2480     # setup
     2481     (clear-stream _test-input-stream)
     2482     (clear-stream $_test-input-buffered-file->buffer)
     2483     (clear-stream _test-output-stream)
     2484     (clear-stream $_test-output-buffered-file->buffer)
     2485     (clear-stream _test-error-stream)
     2486     (clear-stream $_test-error-buffered-file->buffer)
     2487     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     2488     68/push 0/imm32
     2489     68/push 0/imm32
     2490     89/<- %edx 4/r32/esp
     2491     (tailor-exit-descriptor %edx 0x10)
     2492     #
     2493     (write _test-input-stream "fn foo {\n")
     2494     (write _test-input-stream "  var x: int <- copy 0\n")
     2495     (write _test-input-stream "  increment x\n")
     2496     (write _test-input-stream "}\n")
     2497     # convert
     2498     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     2499     # registers except esp clobbered at this point
     2500     # restore ed
     2501     89/<- %edx 4/r32/esp
     2502     (flush _test-output-buffered-file)
     2503     (flush _test-error-buffered-file)
     2504 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
     2510     # check output
     2511     (check-stream-equal _test-output-stream  ""  "F - test-var-in-mem-has-no-initializer: output should be empty")
     2512     (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")
     2513     # check that stop(1) was called
     2514     (check-ints-equal *(edx+4) 2 "F - test-var-in-mem-has-no-initializer: exit status")
     2515     # don't restore from ebp
     2516     81 0/subop/add %esp 8/imm32
     2517     # . epilogue
     2518     5d/pop-to-ebp
     2519     c3/return
     2520
     2521 test-convert-function-with-local-var-with-compound-type-in-mem:
     2522     # . prologue
     2523     55/push-ebp
     2524     89/<- %ebp 4/r32/esp
     2525     # setup
     2526     (clear-stream _test-input-stream)
     2527     (clear-stream $_test-input-buffered-file->buffer)
     2528     (clear-stream _test-output-stream)
     2529     (clear-stream $_test-output-buffered-file->buffer)
     2530     #
     2531     (write _test-input-stream "fn foo {\n")
     2532     (write _test-input-stream "  var x: (addr int)\n")
     2533     (write _test-input-stream "  copy-to x, 0\n")
     2534     (write _test-input-stream "}\n")
     2535     # convert
     2536     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     2537     (flush _test-output-buffered-file)
     2538 +--  6 lines: #?     # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------
     2544     # check output
     2545     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-with-compound-type-in-mem/0")
     2546     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-with-compound-type-in-mem/1")
     2547     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-with-compound-type-in-mem/2")
     2548     (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")
     2549     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-with-compound-type-in-mem/4")
     2550     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-with-compound-type-in-mem/5")
     2551     (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")
     2552     (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")
     2553     (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")
     2554     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-with-compound-type-in-mem/9")
     2555     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-with-compound-type-in-mem/10")
     2556     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-with-compound-type-in-mem/11")
     2557     (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")
     2558     (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")
     2559     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-with-compound-type-in-mem/14")
     2560     # . epilogue
     2561     89/<- %esp 5/r32/ebp
     2562     5d/pop-to-ebp
     2563     c3/return
     2564
     2565 test-convert-function-with-local-var-in-reg:
     2566     # . prologue
     2567     55/push-ebp
     2568     89/<- %ebp 4/r32/esp
     2569     # setup
     2570     (clear-stream _test-input-stream)
     2571     (clear-stream $_test-input-buffered-file->buffer)
     2572     (clear-stream _test-output-stream)
     2573     (clear-stream $_test-output-buffered-file->buffer)
     2574     #
     2575     (write _test-input-stream "fn foo {\n")
     2576     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
     2577     (write _test-input-stream "  x <- increment\n")
     2578     (write _test-input-stream "}\n")
     2579     # convert
     2580     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     2581     (flush _test-output-buffered-file)
     2582 +--  6 lines: #?     # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------
     2588     # check output
     2589     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-in-reg/0")
     2590     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-in-reg/1")
     2591     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-in-reg/2")
     2592     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-in-reg/3")
     2593     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-in-reg/4")
     2594     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-in-reg/5")
     2595     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-local-var-in-reg/6")
     2596     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-convert-function-with-local-var-in-reg/7")
     2597     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-convert-function-with-local-var-in-reg/8")
     2598     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-function-with-local-var-in-reg/9")
     2599     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-in-reg/10")
     2600     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-in-reg/11")
     2601     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-in-reg/12")
     2602     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-in-reg/13")
     2603     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-in-reg/14")
     2604     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-in-reg/15")
     2605     # . epilogue
     2606     89/<- %esp 5/r32/ebp
     2607     5d/pop-to-ebp
     2608     c3/return
     2609
     2610 test-convert-function-with-local-var-in-same-reg:
     2611     # . prologue
     2612     55/push-ebp
     2613     89/<- %ebp 4/r32/esp
     2614     # setup
     2615     (clear-stream _test-input-stream)
     2616     (clear-stream $_test-input-buffered-file->buffer)
     2617     (clear-stream _test-output-stream)
     2618     (clear-stream $_test-output-buffered-file->buffer)
     2619     #
     2620     (write _test-input-stream "fn foo {\n")
     2621     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
     2622     (write _test-input-stream "  var y/ecx: int <- copy x\n")
     2623     (write _test-input-stream "}\n")
     2624     # convert
     2625     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     2626     (flush _test-output-buffered-file)
     2627 +--  6 lines: #?     # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------
     2633     # check output
     2634     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-in-same-reg/0")
     2635     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-in-same-reg/1")
     2636     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-in-same-reg/2")
     2637     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-in-same-reg/3")
     2638     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-in-same-reg/4")
     2639     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-in-same-reg/5")
     2640     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-local-var-in-same-reg/6")
     2641     (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")
     2642     # optimization: skip the second copy
     2643     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-function-with-local-var-in-same-reg/8")
     2644     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-in-same-reg/9")
     2645     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-in-same-reg/10")
     2646     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-in-same-reg/11")
     2647     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-in-same-reg/12")
     2648     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-in-same-reg/13")
     2649     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-in-same-reg/14")
     2650     # . epilogue
     2651     89/<- %esp 5/r32/ebp
     2652     5d/pop-to-ebp
     2653     c3/return
     2654
     2655 test-convert-function-with-local-var-in-same-reg-dereferenced:
     2656     # . prologue
     2657     55/push-ebp
     2658     89/<- %ebp 4/r32/esp
     2659     # setup
     2660     (clear-stream _test-input-stream)
     2661     (clear-stream $_test-input-buffered-file->buffer)
     2662     (clear-stream _test-output-stream)
     2663     (clear-stream $_test-output-buffered-file->buffer)
     2664     #
     2665     (write _test-input-stream "fn foo {\n")
     2666     (write _test-input-stream "  var x/ecx: (addr int) <- copy 0\n")
     2667     (write _test-input-stream "  var y/ecx: int <- copy *x\n")
     2668     (write _test-input-stream "}\n")
     2669     # convert
     2670     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     2671     (flush _test-output-buffered-file)
     2672 +--  6 lines: #?     # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------
     2678     # check output
     2679     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-in-same-reg-dereferenced/0")
     2680     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-in-same-reg-dereferenced/1")
     2681     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-in-same-reg-dereferenced/2")
     2682     (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")
     2683     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-in-same-reg-dereferenced/4")
     2684     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-in-same-reg-dereferenced/5")
     2685     (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")
     2686     (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")
     2687     (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
     2688     (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")
     2689     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-in-same-reg-dereferenced/10")
     2690     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-in-same-reg-dereferenced/11")
     2691     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-in-same-reg-dereferenced/12")
     2692     (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")
     2693     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-in-same-reg-dereferenced/14")
     2694     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-in-same-reg-dereferenced/15")
     2695     # . epilogue
     2696     89/<- %esp 5/r32/ebp
     2697     5d/pop-to-ebp
     2698     c3/return
     2699
     2700 test-float-var-in-wrong-register:
     2701     # . prologue
     2702     55/push-ebp
     2703     89/<- %ebp 4/r32/esp
     2704     # setup
     2705     (clear-stream _test-input-stream)
     2706     (clear-stream $_test-input-buffered-file->buffer)
     2707     (clear-stream _test-output-stream)
     2708     (clear-stream $_test-output-buffered-file->buffer)
     2709     (clear-stream _test-error-stream)
     2710     (clear-stream $_test-error-buffered-file->buffer)
     2711     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     2712     68/push 0/imm32
     2713     68/push 0/imm32
     2714     89/<- %edx 4/r32/esp
     2715     (tailor-exit-descriptor %edx 0x10)
     2716     #
     2717     (write _test-input-stream "fn foo {\n")
     2718     (write _test-input-stream "  var x/eax: int <- copy 0\n")
     2719     (write _test-input-stream "  var y/eax: float <- convert x\n")
     2720     (write _test-input-stream "}\n")
     2721     # convert
     2722     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     2723     # registers except esp clobbered at this point
     2724     # restore ed
     2725     89/<- %edx 4/r32/esp
     2726     (flush _test-output-buffered-file)
     2727     (flush _test-error-buffered-file)
     2728 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
     2734     # check output
     2735     (check-stream-equal _test-output-stream  ""  "F - test-float-var-in-wrong-register: output should be empty")
     2736     (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")
     2737     # check that stop(1) was called
     2738     (check-ints-equal *(edx+4) 2 "F - test-float-var-in-wrong-register: exit status")
     2739     # don't restore from ebp
     2740     81 0/subop/add %esp 8/imm32
     2741     # . epilogue
     2742     5d/pop-to-ebp
     2743     c3/return
     2744
     2745 test-non-float-var-in-wrong-register:
     2746     # . prologue
     2747     55/push-ebp
     2748     89/<- %ebp 4/r32/esp
     2749     # setup
     2750     (clear-stream _test-input-stream)
     2751     (clear-stream $_test-input-buffered-file->buffer)
     2752     (clear-stream _test-output-stream)
     2753     (clear-stream $_test-output-buffered-file->buffer)
     2754     (clear-stream _test-error-stream)
     2755     (clear-stream $_test-error-buffered-file->buffer)
     2756     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     2757     68/push 0/imm32
     2758     68/push 0/imm32
     2759     89/<- %edx 4/r32/esp
     2760     (tailor-exit-descriptor %edx 0x10)
     2761     #
     2762     (write _test-input-stream "fn foo {\n")
     2763     (write _test-input-stream "  var x/xmm5: int <- copy 0\n")
     2764     (write _test-input-stream "}\n")
     2765     # convert
     2766     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     2767     # registers except esp clobbered at this point
     2768     # restore ed
     2769     89/<- %edx 4/r32/esp
     2770     (flush _test-output-buffered-file)
     2771     (flush _test-error-buffered-file)
     2772 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
     2778     # check output
     2779     (check-stream-equal _test-output-stream  ""  "F - test-non-float-var-in-wrong-register: output should be empty")
     2780     (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")
     2781     # check that stop(1) was called
     2782     (check-ints-equal *(edx+4) 2 "F - test-non-float-var-in-wrong-register: exit status")
     2783     # don't restore from ebp
     2784     81 0/subop/add %esp 8/imm32
     2785     # . epilogue
     2786     5d/pop-to-ebp
     2787     c3/return
     2788
     2789 test-convert-function-with-allocate:
     2790     # . prologue
     2791     55/push-ebp
     2792     89/<- %ebp 4/r32/esp
     2793     # setup
     2794     (clear-stream _test-input-stream)
     2795     (clear-stream $_test-input-buffered-file->buffer)
     2796     (clear-stream _test-output-stream)
     2797     (clear-stream $_test-output-buffered-file->buffer)
     2798     #
     2799     (write _test-input-stream "fn foo {\n")
     2800     (write _test-input-stream "  var x/ecx: (addr handle int) <- copy 0\n")
     2801     (write _test-input-stream "  allocate x\n")
     2802     (write _test-input-stream "}\n")
     2803     # convert
     2804     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     2805     (flush _test-output-buffered-file)
     2806 +--  6 lines: #?     # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------
     2812     # check output
     2813     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-allocate/0")
     2814     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-allocate/1")
     2815     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-allocate/2")
     2816     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-allocate/3")
     2817     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-allocate/4")
     2818     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-allocate/5")
     2819     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-allocate/6")
     2820     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"  "F - test-convert-function-with-allocate/7")
     2821     (check-next-stream-line-equal _test-output-stream "    (allocate Heap 0x00000004 %ecx)"  "F - test-convert-function-with-allocate/8")  # 4 = size-of(int)
     2822     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-function-with-allocate/9")
     2823     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-allocate/10")
     2824     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-allocate/11")
     2825     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-allocate/12")
     2826     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-allocate/13")
     2827     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-allocate/14")
     2828     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-allocate/15")
     2829     # . epilogue
     2830     89/<- %esp 5/r32/ebp
     2831     5d/pop-to-ebp
     2832     c3/return
     2833
     2834 test-initializer-in-hex:
     2835     # . prologue
     2836     55/push-ebp
     2837     89/<- %ebp 4/r32/esp
     2838     # setup
     2839     (clear-stream _test-input-stream)
     2840     (clear-stream $_test-input-buffered-file->buffer)
     2841     (clear-stream _test-output-stream)
     2842     (clear-stream $_test-output-buffered-file->buffer)
     2843     (clear-stream _test-error-stream)
     2844     (clear-stream $_test-error-buffered-file->buffer)
     2845     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     2846     68/push 0/imm32
     2847     68/push 0/imm32
     2848     89/<- %edx 4/r32/esp
     2849     (tailor-exit-descriptor %edx 0x10)
     2850     #
     2851     (write _test-input-stream "fn foo {\n")
     2852     (write _test-input-stream "  var x/ecx: int <- copy 10\n")
     2853     (write _test-input-stream "}\n")
     2854     # convert
     2855     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     2856     # registers except esp clobbered at this point
     2857     # restore ed
     2858     89/<- %edx 4/r32/esp
     2859     (flush _test-output-buffered-file)
     2860     (flush _test-error-buffered-file)
     2861 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
     2867     # check output
     2868     (check-stream-equal _test-output-stream  ""  "F - test-initializer-in-hex: output should be empty")
     2869     (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")
     2870     # check that stop(1) was called
     2871     (check-ints-equal *(edx+4) 2 "F - test-initializer-in-hex: exit status")
     2872     # don't restore from ebp
     2873     81 0/subop/add %esp 8/imm32
     2874     # . epilogue
     2875     5d/pop-to-ebp
     2876     c3/return
     2877
     2878 test-convert-function-with-second-local-var-in-same-reg:
     2879     # . prologue
     2880     55/push-ebp
     2881     89/<- %ebp 4/r32/esp
     2882     # setup
     2883     (clear-stream _test-input-stream)
     2884     (clear-stream $_test-input-buffered-file->buffer)
     2885     (clear-stream _test-output-stream)
     2886     (clear-stream $_test-output-buffered-file->buffer)
     2887     #
     2888     (write _test-input-stream "fn foo {\n")
     2889     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
     2890     (write _test-input-stream "  var y/ecx: int <- copy 4\n")
     2891     (write _test-input-stream "  y <- increment\n")
     2892     (write _test-input-stream "}\n")
     2893     # convert
     2894     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     2895     (flush _test-output-buffered-file)
     2896 +--  6 lines: #?     # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------
     2902     # check output
     2903     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-second-local-var-in-same-reg/0")
     2904     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-second-local-var-in-same-reg/1")
     2905     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-second-local-var-in-same-reg/2")
     2906     (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")
     2907     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-second-local-var-in-same-reg/4")
     2908     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-second-local-var-in-same-reg/5")
     2909     (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")
     2910     (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")
     2911     (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")
     2912     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-convert-function-with-second-local-var-in-same-reg/9")
     2913     (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")
     2914     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-second-local-var-in-same-reg/11")
     2915     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-second-local-var-in-same-reg/12")
     2916     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-second-local-var-in-same-reg/13")
     2917     (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")
     2918     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-second-local-var-in-same-reg/15")
     2919     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-second-local-var-in-same-reg/16")
     2920     # . epilogue
     2921     89/<- %esp 5/r32/ebp
     2922     5d/pop-to-ebp
     2923     c3/return
     2924
     2925 test-read-clobbered-reg-var:
     2926     # . prologue
     2927     55/push-ebp
     2928     89/<- %ebp 4/r32/esp
     2929     # setup
     2930     (clear-stream _test-input-stream)
     2931     (clear-stream $_test-input-buffered-file->buffer)
     2932     (clear-stream _test-output-stream)
     2933     (clear-stream $_test-output-buffered-file->buffer)
     2934     (clear-stream _test-error-stream)
     2935     (clear-stream $_test-error-buffered-file->buffer)
     2936     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)  # bytes of args in call to convert-mu
     2937     68/push 0/imm32
     2938     68/push 0/imm32
     2939     89/<- %edx 4/r32/esp
     2940     (tailor-exit-descriptor %edx 0x10)
     2941     #
     2942     (write _test-input-stream "fn foo {\n")
     2943     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
     2944     (write _test-input-stream "  var y/ecx: int <- copy 4\n")
     2945     (write _test-input-stream "  x <- increment\n")
     2946     (write _test-input-stream "}\n")
     2947     # convert
     2948     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     2949     # registers except esp clobbered at this point
     2950     # restore ed
     2951     89/<- %edx 4/r32/esp
     2952     (flush _test-output-buffered-file)
     2953     (flush _test-error-buffered-file)
     2954 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
     2960     # check output
     2961     (check-stream-equal _test-output-stream  ""  "F - test-read-clobbered-reg-var: output should be empty")
     2962     (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")
     2963     # check that stop(1) was called
     2964     (check-ints-equal *(edx+4) 2 "F - test-read-clobbered-reg-var: exit status")
     2965     # don't restore from ebp
     2966     81 0/subop/add %esp 8/imm32
     2967     # . epilogue
     2968     5d/pop-to-ebp
     2969     c3/return
     2970
     2971 test-overlapping-int-fp-registers:
     2972     # . prologue
     2973     55/push-ebp
     2974     89/<- %ebp 4/r32/esp
     2975     # setup
     2976     (clear-stream _test-input-stream)
     2977     (clear-stream $_test-input-buffered-file->buffer)
     2978     (clear-stream _test-output-stream)
     2979     (clear-stream $_test-output-buffered-file->buffer)
     2980     (clear-stream _test-error-stream)
     2981     (clear-stream $_test-error-buffered-file->buffer)
     2982     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)  # bytes of args in call to convert-mu
     2983     68/push 0/imm32
     2984     68/push 0/imm32
     2985     89/<- %edx 4/r32/esp
     2986     (tailor-exit-descriptor %edx 0x10)
     2987     #
     2988     (write _test-input-stream "fn foo {\n")
     2989     (write _test-input-stream "  var x/eax: int <- copy 3\n")
     2990     (write _test-input-stream "  var y/xmm0: float <- convert x\n")
     2991     (write _test-input-stream "  x <- increment\n")
     2992     (write _test-input-stream "}\n")
     2993     # convert
     2994     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     2995     # registers except esp clobbered at this point
     2996     # restore ed
     2997     89/<- %edx 4/r32/esp
     2998     (flush _test-output-buffered-file)
     2999     (flush _test-error-buffered-file)
     3000 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
     3006     # no errors
     3007     (check-next-stream-line-equal _test-error-stream  ""  "F - test-overlapping-int-fp-registers: error message")
     3008     # don't bother checking the generated code
     3009     # don't restore from ebp
     3010     81 0/subop/add %esp 8/imm32
     3011     # . epilogue
     3012     5d/pop-to-ebp
     3013     c3/return
     3014
     3015 test-convert-function-call:
     3016     # . prologue
     3017     55/push-ebp
     3018     89/<- %ebp 4/r32/esp
     3019     # setup
     3020     (clear-stream _test-input-stream)
     3021     (clear-stream $_test-input-buffered-file->buffer)
     3022     (clear-stream _test-output-stream)
     3023     (clear-stream $_test-output-buffered-file->buffer)
     3024     #
     3025     (write _test-input-stream "fn main -> _/ebx: int {\n")
     3026     (write _test-input-stream "  var result/ebx: int <- foo\n")
     3027     (write _test-input-stream "  return result\n")
     3028     (write _test-input-stream "}\n")
     3029     (write _test-input-stream "fn foo -> _/ebx: int {\n")
     3030     (write _test-input-stream "  var result/ebx: int <- copy 3\n")
     3031     (write _test-input-stream "  return result\n")
     3032     (write _test-input-stream "}\n")
     3033     # convert
     3034     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     3035     (flush _test-output-buffered-file)
     3036 +--  6 lines: #?     # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------
     3042     # check output
     3043     (check-next-stream-line-equal _test-output-stream "main:"                   "F - test-convert-function-call/0")
     3044     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call/1")
     3045     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call/2")
     3046     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call/3")
     3047     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call/4")
     3048     (check-next-stream-line-equal _test-output-stream "$main:0x00000001:loop:"  "F - test-convert-function-call/5")
     3049     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ebx"  "F - test-convert-function-call-with-literal-arg/6")
     3050     (check-next-stream-line-equal _test-output-stream "    (foo)"               "F - test-convert-function-call/6")
     3051     (check-next-stream-line-equal _test-output-stream "    8b/-> %ebx 0x00000003/r32" "F - test-convert-function-call-with-literal-arg/8")
     3052     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-function-call-with-literal-arg/27")
     3053     (check-next-stream-line-equal _test-output-stream "    e9/jump $main:0x00000001:break/disp32"  "F - test-convert-function-call-with-literal-arg/10")
     3054     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call/7")
     3055     (check-next-stream-line-equal _test-output-stream "$main:0x00000001:break:" "F - test-convert-function-call/8")
     3056     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call/9")
     3057     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call/10")
     3058     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call/11")
     3059     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call/12")
     3060     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-call/13")
     3061     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call/14")
     3062     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call/15")
     3063     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call/16")
     3064     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call/17")
     3065     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"  "F - test-convert-function-call/18")
     3066     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ebx"  "F - test-convert-function-call-with-literal-arg/6")
     3067     (check-next-stream-line-equal _test-output-stream "    bb/copy-to-ebx 3/imm32"  "F - test-convert-function-call/19")
     3068     (check-next-stream-line-equal _test-output-stream "    8b/-> %ebx 0x00000003/r32" "F - test-convert-function-call-with-literal-arg/8")
     3069     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-function-call-with-literal-arg/27")
     3070     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000002:break/disp32"  "F - test-convert-function-call-with-literal-arg/10")
     3071     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call/20")
     3072     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-call/21")
     3073     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call/22")
     3074     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call/23")
     3075     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call/24")
     3076     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call/25")
     3077     # . epilogue
     3078     89/<- %esp 5/r32/ebp
     3079     5d/pop-to-ebp
     3080     c3/return
     3081
     3082 test-convert-function-call-with-inout-with-compound-type:
     3083     # . prologue
     3084     55/push-ebp
     3085     89/<- %ebp 4/r32/esp
     3086     # setup
     3087     (clear-stream _test-input-stream)
     3088     (clear-stream $_test-input-buffered-file->buffer)
     3089     (clear-stream _test-output-stream)
     3090     (clear-stream $_test-output-buffered-file->buffer)
     3091     #
     3092     (write _test-input-stream "fn f {\n")
     3093     (write _test-input-stream "  var x: (addr int)\n")
     3094     (write _test-input-stream "  g x\n")
     3095     (write _test-input-stream "}\n")
     3096     (write _test-input-stream "fn g a: (addr int) {\n")
     3097     (write _test-input-stream "}\n")
     3098     # convert
     3099     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     3100     (flush _test-output-buffered-file)
     3101 +--  6 lines: #?     # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------
     3107     # check output
     3108     (check-next-stream-line-equal _test-output-stream "f:"                      "F - test-convert-function-call-with-inout-with-compound-type/0")
     3109     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-inout-with-compound-type/1")
     3110     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-inout-with-compound-type/2")
     3111     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call-with-inout-with-compound-type/3")
     3112     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-inout-with-compound-type/4")
     3113     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:loop:"     "F - test-convert-function-call-with-inout-with-compound-type/5")
     3114     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-call-with-inout-with-compound-type/6")
     3115     (check-next-stream-line-equal _test-output-stream "    (g *(ebp+0xfffffffc))"  "F - test-convert-function-call-with-inout-with-compound-type/7")
     3116     (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")
     3117     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-inout-with-compound-type/9")
     3118     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:break:"    "F - test-convert-function-call-with-inout-with-compound-type/10")
     3119     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-inout-with-compound-type/11")
     3120     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call-with-inout-with-compound-type/12")
     3121     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-inout-with-compound-type/13")
     3122     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-inout-with-compound-type/14")
     3123     (check-next-stream-line-equal _test-output-stream "g:"                      "F - test-convert-function-call-with-inout-with-compound-type/15")
     3124     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-inout-with-compound-type/16")
     3125     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-inout-with-compound-type/17")
     3126     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call-with-inout-with-compound-type/18")
     3127     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-inout-with-compound-type/19")
     3128     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-call-with-inout-with-compound-type/20")
     3129     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-inout-with-compound-type/21")
     3130     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-inout-with-compound-type/22")
     3131     # . epilogue
     3132     89/<- %esp 5/r32/ebp
     3133     5d/pop-to-ebp
     3134     c3/return
     3135
     3136 test-convert-function-call-with-inout-with-type-parameter:
     3137     # . prologue
     3138     55/push-ebp
     3139     89/<- %ebp 4/r32/esp
     3140     # setup
     3141     (clear-stream _test-input-stream)
     3142     (clear-stream $_test-input-buffered-file->buffer)
     3143     (clear-stream _test-output-stream)
     3144     (clear-stream $_test-output-buffered-file->buffer)
     3145     (clear-stream _test-error-stream)
     3146     (clear-stream $_test-error-buffered-file->buffer)
     3147     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     3148     68/push 0/imm32
     3149     68/push 0/imm32
     3150     89/<- %edx 4/r32/esp
     3151     (tailor-exit-descriptor %edx 0x10)
     3152     #
     3153     (write _test-input-stream "fn f {\n")
     3154     (write _test-input-stream "  var x: (addr int)\n")
     3155     (write _test-input-stream "  g x\n")
     3156     (write _test-input-stream "}\n")
     3157     (write _test-input-stream "fn g a: (addr _) {\n")
     3158     (write _test-input-stream "}\n")
     3159     # convert
     3160     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     3161     # registers except esp clobbered at this point
     3162     # restore ed
     3163     89/<- %edx 4/r32/esp
     3164     (flush _test-output-buffered-file)
     3165     (flush _test-error-buffered-file)
     3166 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
     3172     # no error; types matched
     3173     (check-stream-equal _test-error-stream  ""  "F - test-convert-function-call-with-inout-with-type-parameter: error stream should be empty")
     3174     # don't bother checking the generated code; that's in the test 'test-local-clobbered-by-fn-output' below
     3175     # don't restore from ebp
     3176     81 0/subop/add %esp 8/imm32
     3177     # . epilogue
     3178     5d/pop-to-ebp
     3179     c3/return
     3180
     3181 test-convert-function-call-with-incorrect-inout-type:
     3182     # . prologue
     3183     55/push-ebp
     3184     89/<- %ebp 4/r32/esp
     3185     # setup
     3186     (clear-stream _test-input-stream)
     3187     (clear-stream $_test-input-buffered-file->buffer)
     3188     (clear-stream _test-output-stream)
     3189     (clear-stream $_test-output-buffered-file->buffer)
     3190     (clear-stream _test-error-stream)
     3191     (clear-stream $_test-error-buffered-file->buffer)
     3192     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     3193     68/push 0/imm32
     3194     68/push 0/imm32
     3195     89/<- %edx 4/r32/esp
     3196     (tailor-exit-descriptor %edx 0x10)
     3197     #
     3198     (write _test-input-stream "fn f {\n")
     3199     (write _test-input-stream "  var x: int\n")
     3200     (write _test-input-stream "  g x\n")
     3201     (write _test-input-stream "}\n")
     3202     (write _test-input-stream "fn g a: foo {\n")
     3203     (write _test-input-stream "}\n")
     3204     # convert
     3205     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     3206     # registers except esp clobbered at this point
     3207     # restore ed
     3208     89/<- %edx 4/r32/esp
     3209     (flush _test-output-buffered-file)
     3210     (flush _test-error-buffered-file)
     3211 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
     3217     # check output
     3218     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-incorrect-inout-type: output should be empty")
     3219     (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")
     3220     # check that stop(1) was called
     3221     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-incorrect-inout-type: exit status")
     3222     # don't restore from ebp
     3223     81 0/subop/add %esp 8/imm32
     3224     5d/pop-to-ebp
     3225     c3/return
     3226
     3227 test-convert-function-call-with-inout-with-incorrect-compound-type:
     3228     # . prologue
     3229     55/push-ebp
     3230     89/<- %ebp 4/r32/esp
     3231     # setup
     3232     (clear-stream _test-input-stream)
     3233     (clear-stream $_test-input-buffered-file->buffer)
     3234     (clear-stream _test-output-stream)
     3235     (clear-stream $_test-output-buffered-file->buffer)
     3236     (clear-stream _test-error-stream)
     3237     (clear-stream $_test-error-buffered-file->buffer)
     3238     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     3239     68/push 0/imm32
     3240     68/push 0/imm32
     3241     89/<- %edx 4/r32/esp
     3242     (tailor-exit-descriptor %edx 0x10)
     3243     #
     3244     (write _test-input-stream "fn f {\n")
     3245     (write _test-input-stream "  var x: (addr int)\n")
     3246     (write _test-input-stream "  g x\n")
     3247     (write _test-input-stream "}\n")
     3248     (write _test-input-stream "fn g a: (addr bool) {\n")
     3249     (write _test-input-stream "}\n")
     3250     # convert
     3251     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     3252     # registers except esp clobbered at this point
     3253     # restore ed
     3254     89/<- %edx 4/r32/esp
     3255     (flush _test-output-buffered-file)
     3256     (flush _test-error-buffered-file)
     3257 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
     3263     # check output
     3264     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-inout-with-incorrect-compound-type: output should be empty")
     3265     (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")
     3266     # don't restore from ebp
     3267     81 0/subop/add %esp 8/imm32
     3268     # . epilogue
     3269     5d/pop-to-ebp
     3270     c3/return
     3271
     3272 test-convert-function-call-with-inout-with-multiple-type-parameters:
     3273     # . prologue
     3274     55/push-ebp
     3275     89/<- %ebp 4/r32/esp
     3276     # setup
     3277     (clear-stream _test-input-stream)
     3278     (clear-stream $_test-input-buffered-file->buffer)
     3279     (clear-stream _test-output-stream)
     3280     (clear-stream $_test-output-buffered-file->buffer)
     3281     (clear-stream _test-error-stream)
     3282     (clear-stream $_test-error-buffered-file->buffer)
     3283     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     3284     68/push 0/imm32
     3285     68/push 0/imm32
     3286     89/<- %edx 4/r32/esp
     3287     (tailor-exit-descriptor %edx 0x10)
     3288     #
     3289     (write _test-input-stream "fn f {\n")
     3290     (write _test-input-stream "  var x: (addr int)\n")
     3291     (write _test-input-stream "  var y: (addr int)\n")
     3292     (write _test-input-stream "  g x, y\n")
     3293     (write _test-input-stream "}\n")
     3294     (write _test-input-stream "fn g a: (addr _), b: (addr _) {\n")
     3295     (write _test-input-stream "}\n")
     3296     # convert
     3297     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     3298     # registers except esp clobbered at this point
     3299     # restore ed
     3300     89/<- %edx 4/r32/esp
     3301     (flush _test-output-buffered-file)
     3302     (flush _test-error-buffered-file)
     3303 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
     3309     # no errors
     3310     (check-stream-equal _test-error-stream  ""  "F - test-convert-function-call-with-inout-with-multiple-type-parameters: error stream should be empty")
     3311     # don't bother checking the generated code
     3312     # don't restore from ebp
     3313     81 0/subop/add %esp 8/imm32
     3314     # . epilogue
     3315     5d/pop-to-ebp
     3316     c3/return
     3317
     3318 test-type-parameter-matches-rest-of-type:
     3319     # . prologue
     3320     55/push-ebp
     3321     89/<- %ebp 4/r32/esp
     3322     # setup
     3323     (clear-stream _test-input-stream)
     3324     (clear-stream $_test-input-buffered-file->buffer)
     3325     (clear-stream _test-output-stream)
     3326     (clear-stream $_test-output-buffered-file->buffer)
     3327     (clear-stream _test-error-stream)
     3328     (clear-stream $_test-error-buffered-file->buffer)
     3329     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     3330     68/push 0/imm32
     3331     68/push 0/imm32
     3332     89/<- %edx 4/r32/esp
     3333     (tailor-exit-descriptor %edx 0x10)
     3334     #
     3335     (write _test-input-stream "fn f {\n")
     3336     (write _test-input-stream "  var x: (addr array int)\n")
     3337     (write _test-input-stream "  g x\n")
     3338     (write _test-input-stream "}\n")
     3339     (write _test-input-stream "fn g a: (addr _) {\n")
     3340     (write _test-input-stream "}\n")
     3341     # convert
     3342     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     3343     # registers except esp clobbered at this point
     3344     # restore ed
     3345     89/<- %edx 4/r32/esp
     3346     (flush _test-output-buffered-file)
     3347     (flush _test-error-buffered-file)
     3348 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
     3354     # no errors
     3355     (check-stream-equal _test-error-stream  ""  "F - test-type-parameter-matches-rest-of-type: error stream should be empty")
     3356     # don't bother checking the generated code
     3357     # don't restore from ebp
     3358     81 0/subop/add %esp 8/imm32
     3359     # . epilogue
     3360     5d/pop-to-ebp
     3361     c3/return
     3362
     3363 test-convert-function-call-with-inout-with-incompatible-type-parameters:
     3364     # . prologue
     3365     55/push-ebp
     3366     89/<- %ebp 4/r32/esp
     3367     # setup
     3368     (clear-stream _test-input-stream)
     3369     (clear-stream $_test-input-buffered-file->buffer)
     3370     (clear-stream _test-output-stream)
     3371     (clear-stream $_test-output-buffered-file->buffer)
     3372     (clear-stream _test-error-stream)
     3373     (clear-stream $_test-error-buffered-file->buffer)
     3374     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     3375     68/push 0/imm32
     3376     68/push 0/imm32
     3377     89/<- %edx 4/r32/esp
     3378     (tailor-exit-descriptor %edx 0x10)
     3379     #
     3380     (write _test-input-stream "fn f {\n")
     3381     (write _test-input-stream "  var x: (addr int)\n")
     3382     (write _test-input-stream "  var y: (addr boolean)\n")
     3383     (write _test-input-stream "  g x, y\n")
     3384     (write _test-input-stream "}\n")
     3385     (write _test-input-stream "fn g a: (addr _T), b: (addr _T) {\n")
     3386     (write _test-input-stream "}\n")
     3387     # convert
     3388     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     3389     # registers except esp clobbered at this point
     3390     # restore ed
     3391     89/<- %edx 4/r32/esp
     3392     (flush _test-output-buffered-file)
     3393     (flush _test-error-buffered-file)
     3394 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
     3400     # check output
     3401     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-inout-with-incompatible-type-parameters: output should be empty")
     3402     (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")
     3403     # don't restore from ebp
     3404     81 0/subop/add %esp 8/imm32
     3405     # . epilogue
     3406     5d/pop-to-ebp
     3407     c3/return
     3408
     3409 test-convert-function-call-with-too-few-inouts:
     3410     # . prologue
     3411     55/push-ebp
     3412     89/<- %ebp 4/r32/esp
     3413     # setup
     3414     (clear-stream _test-input-stream)
     3415     (clear-stream $_test-input-buffered-file->buffer)
     3416     (clear-stream _test-output-stream)
     3417     (clear-stream $_test-output-buffered-file->buffer)
     3418     (clear-stream _test-error-stream)
     3419     (clear-stream $_test-error-buffered-file->buffer)
     3420     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     3421     68/push 0/imm32
     3422     68/push 0/imm32
     3423     89/<- %edx 4/r32/esp
     3424     (tailor-exit-descriptor %edx 0x10)
     3425     #
     3426     (write _test-input-stream "fn f {\n")
     3427     (write _test-input-stream "  g\n")
     3428     (write _test-input-stream "}\n")
     3429     (write _test-input-stream "fn g a: int {\n")
     3430     (write _test-input-stream "}\n")
     3431     # convert
     3432     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     3433     # registers except esp clobbered at this point
     3434     # restore ed
     3435     89/<- %edx 4/r32/esp
     3436     (flush _test-output-buffered-file)
     3437     (flush _test-error-buffered-file)
     3438 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
     3444     # check output
     3445     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-too-few-inouts: output should be empty")
     3446     (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")
     3447     # check that stop(1) was called
     3448     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-too-few-inouts: exit status")
     3449     # don't restore from ebp
     3450     81 0/subop/add %esp 8/imm32
     3451     5d/pop-to-ebp
     3452     c3/return
     3453
     3454 test-convert-function-call-with-too-many-inouts:
     3455     # . prologue
     3456     55/push-ebp
     3457     89/<- %ebp 4/r32/esp
     3458     # setup
     3459     (clear-stream _test-input-stream)
     3460     (clear-stream $_test-input-buffered-file->buffer)
     3461     (clear-stream _test-output-stream)
     3462     (clear-stream $_test-output-buffered-file->buffer)
     3463     (clear-stream _test-error-stream)
     3464     (clear-stream $_test-error-buffered-file->buffer)
     3465     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     3466     68/push 0/imm32
     3467     68/push 0/imm32
     3468     89/<- %edx 4/r32/esp
     3469     (tailor-exit-descriptor %edx 0x10)
     3470     #
     3471     (write _test-input-stream "fn f {\n")
     3472     (write _test-input-stream "  var x: int\n")
     3473     (write _test-input-stream "  g x\n")
     3474     (write _test-input-stream "}\n")
     3475     (write _test-input-stream "fn g {\n")
     3476     (write _test-input-stream "}\n")
     3477     # convert
     3478     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     3479     # registers except esp clobbered at this point
     3480     # restore ed
     3481     89/<- %edx 4/r32/esp
     3482     (flush _test-output-buffered-file)
     3483     (flush _test-error-buffered-file)
     3484 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
     3490     # check output
     3491     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-too-many-inouts: output should be empty")
     3492     (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")
     3493     # check that stop(1) was called
     3494     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-too-many-inouts: exit status")
     3495     # don't restore from ebp
     3496     81 0/subop/add %esp 8/imm32
     3497     5d/pop-to-ebp
     3498     c3/return
     3499
     3500 test-convert-function-call-with-incorrect-output-type:
     3501     # . prologue
     3502     55/push-ebp
     3503     89/<- %ebp 4/r32/esp
     3504     # setup
     3505     (clear-stream _test-input-stream)
     3506     (clear-stream $_test-input-buffered-file->buffer)
     3507     (clear-stream _test-output-stream)
     3508     (clear-stream $_test-output-buffered-file->buffer)
     3509     (clear-stream _test-error-stream)
     3510     (clear-stream $_test-error-buffered-file->buffer)
     3511     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     3512     68/push 0/imm32
     3513     68/push 0/imm32
     3514     89/<- %edx 4/r32/esp
     3515     (tailor-exit-descriptor %edx 0x10)
     3516     #
     3517     (write _test-input-stream "fn f {\n")
     3518     (write _test-input-stream "  var x/eax: int <- g\n")
     3519     (write _test-input-stream "}\n")
     3520     (write _test-input-stream "fn g -> _/eax: foo {\n")
     3521     (write _test-input-stream "}\n")
     3522     # convert
     3523     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     3524     # registers except esp clobbered at this point
     3525     # restore ed
     3526     89/<- %edx 4/r32/esp
     3527     (flush _test-output-buffered-file)
     3528     (flush _test-error-buffered-file)
     3529 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
     3535     # check output
     3536     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-incorrect-output-type: output should be empty")
     3537     (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")
     3538     # check that stop(1) was called
     3539     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-incorrect-output-type: exit status")
     3540     # don't restore from ebp
     3541     81 0/subop/add %esp 8/imm32
     3542     5d/pop-to-ebp
     3543     c3/return
     3544
     3545 test-convert-function-call-with-too-few-outputs:
     3546     # . prologue
     3547     55/push-ebp
     3548     89/<- %ebp 4/r32/esp
     3549     # setup
     3550     (clear-stream _test-input-stream)
     3551     (clear-stream $_test-input-buffered-file->buffer)
     3552     (clear-stream _test-output-stream)
     3553     (clear-stream $_test-output-buffered-file->buffer)
     3554     (clear-stream _test-error-stream)
     3555     (clear-stream $_test-error-buffered-file->buffer)
     3556     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     3557     68/push 0/imm32
     3558     68/push 0/imm32
     3559     89/<- %edx 4/r32/esp
     3560     (tailor-exit-descriptor %edx 0x10)
     3561     #
     3562     (write _test-input-stream "fn f {\n")
     3563     (write _test-input-stream "  g\n")
     3564     (write _test-input-stream "}\n")
     3565     (write _test-input-stream "fn g -> _/eax: int {\n")
     3566     (write _test-input-stream "}\n")
     3567     # convert
     3568     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     3569     # registers except esp clobbered at this point
     3570     # restore ed
     3571     89/<- %edx 4/r32/esp
     3572     (flush _test-output-buffered-file)
     3573     (flush _test-error-buffered-file)
     3574 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
     3580     # check output
     3581     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-too-few-outputs: output should be empty")
     3582     (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")
     3583     # check that stop(1) was called
     3584     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-too-few-outputs: exit status")
     3585     # don't restore from ebp
     3586     81 0/subop/add %esp 8/imm32
     3587     5d/pop-to-ebp
     3588     c3/return
     3589
     3590 test-convert-function-call-with-too-many-outputs:
     3591     # . prologue
     3592     55/push-ebp
     3593     89/<- %ebp 4/r32/esp
     3594     # setup
     3595     (clear-stream _test-input-stream)
     3596     (clear-stream $_test-input-buffered-file->buffer)
     3597     (clear-stream _test-output-stream)
     3598     (clear-stream $_test-output-buffered-file->buffer)
     3599     (clear-stream _test-error-stream)
     3600     (clear-stream $_test-error-buffered-file->buffer)
     3601     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     3602     68/push 0/imm32
     3603     68/push 0/imm32
     3604     89/<- %edx 4/r32/esp
     3605     (tailor-exit-descriptor %edx 0x10)
     3606     #
     3607     (write _test-input-stream "fn f {\n")
     3608     (write _test-input-stream "  var x/eax: int <- g\n")
     3609     (write _test-input-stream "}\n")
     3610     (write _test-input-stream "fn g {\n")
     3611     (write _test-input-stream "}\n")
     3612     # convert
     3613     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     3614     # registers except esp clobbered at this point
     3615     # restore ed
     3616     89/<- %edx 4/r32/esp
     3617     (flush _test-output-buffered-file)
     3618     (flush _test-error-buffered-file)
     3619 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
     3625     # check output
     3626     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-too-many-outputs: output should be empty")
     3627     (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")
     3628     # check that stop(1) was called
     3629     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-too-many-outputs: exit status")
     3630     # don't restore from ebp
     3631     81 0/subop/add %esp 8/imm32
     3632     5d/pop-to-ebp
     3633     c3/return
     3634
     3635 test-convert-function-call-with-missing-output-register:
     3636     # . prologue
     3637     55/push-ebp
     3638     89/<- %ebp 4/r32/esp
     3639     # setup
     3640     (clear-stream _test-input-stream)
     3641     (clear-stream $_test-input-buffered-file->buffer)
     3642     (clear-stream _test-output-stream)
     3643     (clear-stream $_test-output-buffered-file->buffer)
     3644     (clear-stream _test-error-stream)
     3645     (clear-stream $_test-error-buffered-file->buffer)
     3646     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     3647     68/push 0/imm32
     3648     68/push 0/imm32
     3649     89/<- %edx 4/r32/esp
     3650     (tailor-exit-descriptor %edx 0x10)
     3651     #
     3652     (write _test-input-stream "fn f {\n")
     3653     (write _test-input-stream "  var x: int\n")
     3654     (write _test-input-stream "  x <- g\n")
     3655     (write _test-input-stream "}\n")
     3656     (write _test-input-stream "fn g -> _/eax: int {\n")
     3657     (write _test-input-stream "}\n")
     3658     # convert
     3659     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     3660     # registers except esp clobbered at this point
     3661     # restore ed
     3662     89/<- %edx 4/r32/esp
     3663     (flush _test-output-buffered-file)
     3664     (flush _test-error-buffered-file)
     3665 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
     3671     # check output
     3672     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-missing-output-register: output should be empty")
     3673     (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")
     3674     # check that stop(1) was called
     3675     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-missing-output-register: exit status")
     3676     # don't restore from ebp
     3677     81 0/subop/add %esp 8/imm32
     3678     5d/pop-to-ebp
     3679     c3/return
     3680
     3681 test-convert-function-call-with-incorrect-output-register:
     3682     # . prologue
     3683     55/push-ebp
     3684     89/<- %ebp 4/r32/esp
     3685     # setup
     3686     (clear-stream _test-input-stream)
     3687     (clear-stream $_test-input-buffered-file->buffer)
     3688     (clear-stream _test-output-stream)
     3689     (clear-stream $_test-output-buffered-file->buffer)
     3690     (clear-stream _test-error-stream)
     3691     (clear-stream $_test-error-buffered-file->buffer)
     3692     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     3693     68/push 0/imm32
     3694     68/push 0/imm32
     3695     89/<- %edx 4/r32/esp
     3696     (tailor-exit-descriptor %edx 0x10)
     3697     #
     3698     (write _test-input-stream "fn f {\n")
     3699     (write _test-input-stream "  var x/ecx: int <- g\n")
     3700     (write _test-input-stream "}\n")
     3701     (write _test-input-stream "fn g -> _/eax: int {\n")
     3702     (write _test-input-stream "}\n")
     3703     # convert
     3704     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     3705     # registers except esp clobbered at this point
     3706     # restore ed
     3707     89/<- %edx 4/r32/esp
     3708     (flush _test-output-buffered-file)
     3709     (flush _test-error-buffered-file)
     3710 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
     3716     # check output
     3717     (check-stream-equal _test-output-stream  ""  "F - test-convert-function-call-with-incorrect-output-register: output should be empty")
     3718     (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")
     3719     # check that stop(1) was called
     3720     (check-ints-equal *(edx+4) 2 "F - test-convert-function-call-with-incorrect-output-register: exit status")
     3721     # don't restore from ebp
     3722     81 0/subop/add %esp 8/imm32
     3723     5d/pop-to-ebp
     3724     c3/return
     3725
     3726 test-convert-function-with-local-var-dereferenced:
     3727     # . prologue
     3728     55/push-ebp
     3729     89/<- %ebp 4/r32/esp
     3730     # setup
     3731     (clear-stream _test-input-stream)
     3732     (clear-stream $_test-input-buffered-file->buffer)
     3733     (clear-stream _test-output-stream)
     3734     (clear-stream $_test-output-buffered-file->buffer)
     3735     #
     3736     (write _test-input-stream "fn foo {\n")
     3737     (write _test-input-stream "  var x/ecx: (addr int) <- copy 0\n")
     3738     (write _test-input-stream "  increment *x\n")
     3739     (write _test-input-stream "}\n")
     3740     # convert
     3741     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     3742     (flush _test-output-buffered-file)
     3743 +--  6 lines: #?     # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------
     3749     # check output
     3750     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-dereferenced/0")
     3751     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-dereferenced/1")
     3752     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-dereferenced/2")
     3753     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-dereferenced/3")
     3754     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-dereferenced/4")
     3755     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-dereferenced/5")
     3756     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-local-var-dereferenced/6")
     3757     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"  "F - test-convert-function-with-local-var-dereferenced/7")
     3758     (check-next-stream-line-equal _test-output-stream "    ff 0/subop/increment *ecx"  "F - test-convert-function-with-local-var-dereferenced/8")
     3759     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-function-with-local-var-dereferenced/9")
     3760     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-dereferenced/10")
     3761     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-dereferenced/11")
     3762     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-dereferenced/12")
     3763     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-dereferenced/13")
     3764     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-dereferenced/14")
     3765     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-dereferenced/15")
     3766     # . epilogue
     3767     89/<- %esp 5/r32/ebp
     3768     5d/pop-to-ebp
     3769     c3/return
     3770
     3771 test-dereference-of-var-on-stack:
     3772     # . prologue
     3773     55/push-ebp
     3774     89/<- %ebp 4/r32/esp
     3775     # setup
     3776     (clear-stream _test-input-stream)
     3777     (clear-stream $_test-input-buffered-file->buffer)
     3778     (clear-stream _test-output-stream)
     3779     (clear-stream $_test-output-buffered-file->buffer)
     3780     (clear-stream _test-error-stream)
     3781     (clear-stream $_test-error-buffered-file->buffer)
     3782     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     3783     68/push 0/imm32
     3784     68/push 0/imm32
     3785     89/<- %edx 4/r32/esp
     3786     (tailor-exit-descriptor %edx 0x10)
     3787     #
     3788     (write _test-input-stream "fn foo {\n")
     3789     (write _test-input-stream "  var x: (addr int)\n")
     3790     (write _test-input-stream "  increment *x\n")
     3791     (write _test-input-stream "}\n")
     3792     # convert
     3793     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     3794     # registers except esp clobbered at this point
     3795     # restore ed
     3796     89/<- %edx 4/r32/esp
     3797     (flush _test-output-buffered-file)
     3798     (flush _test-error-buffered-file)
     3799 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
     3805     # check output
     3806     (check-stream-equal _test-output-stream  ""  "F - test-dereference-of-var-on-stack: output should be empty")
     3807     (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")
     3808     # check that stop(1) was called
     3809     (check-ints-equal *(edx+4) 2 "F - test-dereference-of-var-on-stack: exit status")
     3810     # don't restore from ebp
     3811     81 0/subop/add %esp 8/imm32
     3812     # . epilogue
     3813     5d/pop-to-ebp
     3814     c3/return
     3815
     3816 test-convert-function-with-byte-operations:
     3817     # . prologue
     3818     55/push-ebp
     3819     89/<- %ebp 4/r32/esp
     3820     # setup
     3821     (clear-stream _test-input-stream)
     3822     (clear-stream $_test-input-buffered-file->buffer)
     3823     (clear-stream _test-output-stream)
     3824     (clear-stream $_test-output-buffered-file->buffer)
     3825     #
     3826     (write _test-input-stream "fn foo {\n")
     3827     (write _test-input-stream "  var x/eax: byte <- copy 0\n")
     3828     (write _test-input-stream "  var y/ecx: byte <- copy 0\n")
     3829     (write _test-input-stream "  y <- copy-byte x\n")
     3830     (write _test-input-stream "  var z/edx: (addr byte) <- copy 0\n")
     3831     (write _test-input-stream "  y <- copy-byte *z\n")
     3832     (write _test-input-stream "  copy-byte-to *z, x\n")
     3833     (write _test-input-stream "}\n")
     3834     # convert
     3835     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     3836     (flush _test-output-buffered-file)
     3837 +--  6 lines: #?     # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------
     3843     # check output
     3844     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-function-with-byte-operations/0")
     3845     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-function-with-byte-operations/1")
     3846     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-function-with-byte-operations/2")
     3847     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-function-with-byte-operations/3")
     3848     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-function-with-byte-operations/4")
     3849     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-function-with-byte-operations/5")
     3850     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-function-with-byte-operations/6")
     3851     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-function-with-byte-operations/7")
     3852     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-function-with-byte-operations/8")
     3853     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"                  "F - test-convert-function-with-byte-operations/9")
     3854     (check-next-stream-line-equal _test-output-stream "    8a/byte-> %eax 0x00000001/r32"           "F - test-convert-function-with-byte-operations/10")
     3855     (check-next-stream-line-equal _test-output-stream "    81 4/subop/and %ecx 0xff/imm32"          "F - test-convert-function-with-byte-operations/11")
     3856     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %edx"                    "F - test-convert-function-with-byte-operations/12")
     3857     (check-next-stream-line-equal _test-output-stream "    ba/copy-to-edx 0/imm32"                  "F - test-convert-function-with-byte-operations/13")
     3858     (check-next-stream-line-equal _test-output-stream "    8a/byte-> *edx 0x00000001/r32"           "F - test-convert-function-with-byte-operations/14")
     3859     (check-next-stream-line-equal _test-output-stream "    81 4/subop/and %ecx 0xff/imm32"          "F - test-convert-function-with-byte-operations/15")
     3860     (check-next-stream-line-equal _test-output-stream "    88/byte<- *edx 0x00000000/r32"           "F - test-convert-function-with-byte-operations/16")
     3861     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %edx"                     "F - test-convert-function-with-byte-operations/17")
     3862     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-function-with-byte-operations/18")
     3863     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-function-with-byte-operations/19")
     3864     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-function-with-byte-operations/20")
     3865     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-function-with-byte-operations/21")
     3866     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-function-with-byte-operations/22")
     3867     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-function-with-byte-operations/23")
     3868     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-function-with-byte-operations/24")
     3869     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-function-with-byte-operations/25")
     3870     # . epilogue
     3871     89/<- %esp 5/r32/ebp
     3872     5d/pop-to-ebp
     3873     c3/return
     3874
     3875 # variables of type 'byte' are not allowed on the stack
     3876 test-byte-values-on-stack:
     3877     # . prologue
     3878     55/push-ebp
     3879     89/<- %ebp 4/r32/esp
     3880     # setup
     3881     (clear-stream _test-input-stream)
     3882     (clear-stream $_test-input-buffered-file->buffer)
     3883     (clear-stream _test-output-stream)
     3884     (clear-stream $_test-output-buffered-file->buffer)
     3885     (clear-stream _test-error-stream)
     3886     (clear-stream $_test-error-buffered-file->buffer)
     3887     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     3888     68/push 0/imm32
     3889     68/push 0/imm32
     3890     89/<- %edx 4/r32/esp
     3891     (tailor-exit-descriptor %edx 0x10)
     3892     #
     3893     (write _test-input-stream "fn foo {\n")
     3894     (write _test-input-stream "  var x: byte\n")
     3895     (write _test-input-stream "}\n")
     3896     # convert
     3897     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     3898     # registers except esp clobbered at this point
     3899     # restore ed
     3900     89/<- %edx 4/r32/esp
     3901     (flush _test-output-buffered-file)
     3902     (flush _test-error-buffered-file)
     3903 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
     3909     # check output
     3910     (check-stream-equal _test-output-stream  ""  "F - test-byte-values-on-stack: output should be empty")
     3911     (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")
     3912     # check that stop(1) was called
     3913     (check-ints-equal *(edx+4) 2 "F - test-byte-values-on-stack: exit status")
     3914     # don't restore from ebp
     3915     81 0/subop/add %esp 8/imm32
     3916     # . epilogue
     3917     5d/pop-to-ebp
     3918     c3/return
     3919
     3920 # variables of type 'byte' are not allowed in esi or edi
     3921 test-byte-values-in-unsupported-registers:
     3922     # . prologue
     3923     55/push-ebp
     3924     89/<- %ebp 4/r32/esp
     3925     # setup
     3926     (clear-stream _test-input-stream)
     3927     (clear-stream $_test-input-buffered-file->buffer)
     3928     (clear-stream _test-output-stream)
     3929     (clear-stream $_test-output-buffered-file->buffer)
     3930     (clear-stream _test-error-stream)
     3931     (clear-stream $_test-error-buffered-file->buffer)
     3932     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     3933     68/push 0/imm32
     3934     68/push 0/imm32
     3935     89/<- %edx 4/r32/esp
     3936     (tailor-exit-descriptor %edx 0x10)
     3937     #
     3938     (write _test-input-stream "fn foo {\n")
     3939     (write _test-input-stream "  var x/esi: byte <- copy 0\n")
     3940     (write _test-input-stream "}\n")
     3941     # convert
     3942     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     3943     # registers except esp clobbered at this point
     3944     # restore ed
     3945     89/<- %edx 4/r32/esp
     3946     (flush _test-output-buffered-file)
     3947     (flush _test-error-buffered-file)
     3948 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
     3954     # check output
     3955     (check-stream-equal _test-output-stream  ""  "F - test-byte-values-in-unsupported-registers: output should be empty")
     3956     (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")
     3957     # check that stop(1) was called
     3958     (check-ints-equal *(edx+4) 2 "F - test-byte-values-in-unsupported-registers: exit status")
     3959     # don't restore from ebp
     3960     81 0/subop/add %esp 8/imm32
     3961     # . epilogue
     3962     5d/pop-to-ebp
     3963     c3/return
     3964
     3965 # variables of type 'byte' _can_ be function args. They then occupy 4 bytes.
     3966 test-copy-byte-var-from-fn-arg:
     3967     # . prologue
     3968     55/push-ebp
     3969     89/<- %ebp 4/r32/esp
     3970     # setup
     3971     (clear-stream _test-input-stream)
     3972     (clear-stream $_test-input-buffered-file->buffer)
     3973     (clear-stream _test-output-stream)
     3974     (clear-stream $_test-output-buffered-file->buffer)
     3975     #
     3976     (write _test-input-stream "fn foo x: byte, y: int {\n")
     3977     (write _test-input-stream "  var a/eax: byte <- copy x\n")
     3978     (write _test-input-stream "  var b/eax: int <- copy y\n")
     3979     (write _test-input-stream "}\n")
     3980     # convert
     3981     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     3982     (flush _test-output-buffered-file)
     3983 +--  6 lines: #?     # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------
     3989     # check output
     3990     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-copy-byte-from-fn-arg/0")
     3991     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-copy-byte-from-fn-arg/1")
     3992     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-copy-byte-from-fn-arg/2")
     3993     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-copy-byte-from-fn-arg/3")
     3994     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-copy-byte-from-fn-arg/4")
     3995     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-copy-byte-from-fn-arg/5")
     3996     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-copy-byte-from-fn-arg/6")
     3997     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000000/r32"  "F - test-copy-byte-from-fn-arg/7")
     3998     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x0000000c) 0x00000000/r32"  "F - test-copy-byte-from-fn-arg/8")
     3999     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"   "F - test-copy-byte-from-fn-arg/9")
     4000     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-copy-byte-from-fn-arg/10")
     4001     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-copy-byte-from-fn-arg/11")
     4002     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-copy-byte-from-fn-arg/12")
     4003     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-copy-byte-from-fn-arg/13")
     4004     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-copy-byte-from-fn-arg/14")
     4005     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-copy-byte-from-fn-arg/15")
     4006     # . epilogue
     4007     89/<- %esp 5/r32/ebp
     4008     5d/pop-to-ebp
     4009     c3/return
     4010
     4011 test-convert-compare-register-with-literal:
     4012     # . prologue
     4013     55/push-ebp
     4014     89/<- %ebp 4/r32/esp
     4015     # setup
     4016     (clear-stream _test-input-stream)
     4017     (clear-stream $_test-input-buffered-file->buffer)
     4018     (clear-stream _test-output-stream)
     4019     (clear-stream $_test-output-buffered-file->buffer)
     4020     #
     4021     (write _test-input-stream "fn foo {\n")
     4022     (write _test-input-stream "  var x/ecx: int <- copy 0\n")
     4023     (write _test-input-stream "  compare x, 0\n")
     4024     (write _test-input-stream "}\n")
     4025     # convert
     4026     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     4027     (flush _test-output-buffered-file)
     4028 +--  6 lines: #?     # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------
     4034     # check output
     4035     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-compare-register-with-literal/0")
     4036     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-compare-register-with-literal/1")
     4037     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-compare-register-with-literal/2")
     4038     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-compare-register-with-literal/3")
     4039     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-compare-register-with-literal/4")
     4040     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-compare-register-with-literal/5")
     4041     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-compare-register-with-literal/6")
     4042     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"  "F - test-convert-compare-register-with-literal/7")
     4043     (check-next-stream-line-equal _test-output-stream "    81 7/subop/compare %ecx 0/imm32"  "F - test-convert-compare-register-with-literal/8")
     4044     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-compare-register-with-literal/9")
     4045     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-compare-register-with-literal/10")
     4046     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-compare-register-with-literal/11")
     4047     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-compare-register-with-literal/12")
     4048     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-compare-register-with-literal/13")
     4049     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-compare-register-with-literal/14")
     4050     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-compare-register-with-literal/15")
     4051     # . epilogue
     4052     89/<- %esp 5/r32/ebp
     4053     5d/pop-to-ebp
     4054     c3/return
     4055
     4056 test-convert-compare-byte-with-literal:
     4057     # . prologue
     4058     55/push-ebp
     4059     89/<- %ebp 4/r32/esp
     4060     # setup
     4061     (clear-stream _test-input-stream)
     4062     (clear-stream $_test-input-buffered-file->buffer)
     4063     (clear-stream _test-output-stream)
     4064     (clear-stream $_test-output-buffered-file->buffer)
     4065     #
     4066     (write _test-input-stream "fn foo {\n")
     4067     (write _test-input-stream "  var x/ecx: byte <- copy 0\n")
     4068     (write _test-input-stream "  compare x, 0\n")
     4069     (write _test-input-stream "}\n")
     4070     # convert
     4071     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     4072     (flush _test-output-buffered-file)
     4073 +--  6 lines: #?     # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------
     4079     # no errors; output is identical to test-convert-compare-register-with-literal
     4080     # . epilogue
     4081     89/<- %esp 5/r32/ebp
     4082     5d/pop-to-ebp
     4083     c3/return
     4084
     4085 test-unknown-variable:
     4086     # . prologue
     4087     55/push-ebp
     4088     89/<- %ebp 4/r32/esp
     4089     # setup
     4090     (clear-stream _test-input-stream)
     4091     (clear-stream $_test-input-buffered-file->buffer)
     4092     (clear-stream _test-output-stream)
     4093     (clear-stream $_test-output-buffered-file->buffer)
     4094     (clear-stream _test-error-stream)
     4095     (clear-stream $_test-error-buffered-file->buffer)
     4096     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     4097     68/push 0/imm32
     4098     68/push 0/imm32
     4099     89/<- %edx 4/r32/esp
     4100     (tailor-exit-descriptor %edx 0x10)
     4101     #
     4102     (write _test-input-stream "fn foo {\n")
     4103     (write _test-input-stream "  compare x, 0\n")
     4104     (write _test-input-stream "}\n")
     4105     # convert
     4106     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     4107     # registers except esp clobbered at this point
     4108     # restore ed
     4109     89/<- %edx 4/r32/esp
     4110     (flush _test-output-buffered-file)
     4111     (flush _test-error-buffered-file)
     4112 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
     4118     # check output
     4119     (check-stream-equal _test-output-stream  ""  "F - test-unknown-variable: output should be empty")
     4120     (check-next-stream-line-equal _test-error-stream  "fn foo: unknown variable 'x'"  "F - test-unknown-variable: error message")
     4121     # check that stop(1) was called
     4122     (check-ints-equal *(edx+4) 2 "F - test-unknown-variable: exit status")
     4123     # don't restore from ebp
     4124     81 0/subop/add %esp 8/imm32
     4125     # . epilogue
     4126     5d/pop-to-ebp
     4127     c3/return
     4128
     4129 test-convert-function-with-local-var-in-block:
     4130     # . prologue
     4131     55/push-ebp
     4132     89/<- %ebp 4/r32/esp
     4133     # setup
     4134     (clear-stream _test-input-stream)
     4135     (clear-stream $_test-input-buffered-file->buffer)
     4136     (clear-stream _test-output-stream)
     4137     (clear-stream $_test-output-buffered-file->buffer)
     4138     #
     4139     (write _test-input-stream "fn foo {\n")
     4140     (write _test-input-stream "  {\n")
     4141     (write _test-input-stream "    var x: int\n")
     4142     (write _test-input-stream "    increment x\n")
     4143     (write _test-input-stream "  }\n")
     4144     (write _test-input-stream "}\n")
     4145     # convert
     4146     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     4147     (flush _test-output-buffered-file)
     4148 +--  6 lines: #?     # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------
     4154     # check output
     4155     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-in-block/0")
     4156     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-in-block/1")
     4157     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-in-block/2")
     4158     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-in-block/3")
     4159     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-in-block/4")
     4160     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-in-block/5")
     4161     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-local-var-in-block/6")
     4162     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-local-var-in-block/7")
     4163     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-local-var-in-block/8")
     4164     (check-next-stream-line-equal _test-output-stream "      ff 0/subop/increment *(ebp+0xfffffffc)"  "F - test-convert-function-with-local-var-in-block/9")
     4165     (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")
     4166     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-local-var-in-block/11")
     4167     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-local-var-in-block/12")
     4168     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-in-block/13")
     4169     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-in-block/14")
     4170     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-in-block/15")
     4171     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-in-block/16")
     4172     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-in-block/17")
     4173     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-in-block/18")
     4174     # . epilogue
     4175     89/<- %esp 5/r32/ebp
     4176     5d/pop-to-ebp
     4177     c3/return
     4178
     4179 test-convert-function-with-local-var-in-mem-after-block:
     4180     # . prologue
     4181     55/push-ebp
     4182     89/<- %ebp 4/r32/esp
     4183     # setup
     4184     (clear-stream _test-input-stream)
     4185     (clear-stream $_test-input-buffered-file->buffer)
     4186     (clear-stream _test-output-stream)
     4187     (clear-stream $_test-output-buffered-file->buffer)
     4188     #
     4189     (write _test-input-stream "fn foo {\n")
     4190     (write _test-input-stream "  {\n")
     4191     (write _test-input-stream "    var y: int\n")
     4192     (write _test-input-stream "  }\n")
     4193     (write _test-input-stream "  var x: int\n")
     4194     (write _test-input-stream "  increment x\n")
     4195     (write _test-input-stream "}\n")
     4196     # convert
     4197     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     4198     (flush _test-output-buffered-file)
     4199 +--  6 lines: #?     # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------
     4205     # check output
     4206     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-in-mem-after-block/0")
     4207     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-in-mem-after-block/1")
     4208     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-in-mem-after-block/2")
     4209     (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")
     4210     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-in-mem-after-block/4")
     4211     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-in-mem-after-block/5")
     4212     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-local-var-in-mem-after-block/6")
     4213     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-local-var-in-mem-after-block/7")
     4214     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-local-var-in-mem-after-block/8")
     4215     (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")
     4216     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-local-var-in-mem-after-block/10")
     4217     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-local-var-in-mem-after-block/11")
     4218     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-with-local-var-in-mem-after-block/12")
     4219     (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")
     4220     (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")
     4221     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-in-mem-after-block/15")
     4222     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-in-mem-after-block/16")
     4223     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-in-mem-after-block/17")
     4224     (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")
     4225     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-in-mem-after-block/19")
     4226     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-in-mem-after-block/20")
     4227     # . epilogue
     4228     89/<- %esp 5/r32/ebp
     4229     5d/pop-to-ebp
     4230     c3/return
     4231
     4232 test-convert-function-with-local-var-in-named-block:
     4233     # . prologue
     4234     55/push-ebp
     4235     89/<- %ebp 4/r32/esp
     4236     # setup
     4237     (clear-stream _test-input-stream)
     4238     (clear-stream $_test-input-buffered-file->buffer)
     4239     (clear-stream _test-output-stream)
     4240     (clear-stream $_test-output-buffered-file->buffer)
     4241     #
     4242     (write _test-input-stream "fn foo {\n")
     4243     (write _test-input-stream "  $bar: {\n")
     4244     (write _test-input-stream "    var x: int\n")
     4245     (write _test-input-stream "    increment x\n")
     4246     (write _test-input-stream "  }\n")
     4247     (write _test-input-stream "}\n")
     4248     # convert
     4249     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     4250     (flush _test-output-buffered-file)
     4251 +--  6 lines: #?     # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------
     4257     # check output
     4258     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-in-named-block/0")
     4259     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-in-named-block/1")
     4260     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-in-named-block/2")
     4261     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-var-in-named-block/3")
     4262     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-in-named-block/4")
     4263     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-in-named-block/5")
     4264     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-local-var-in-named-block/6")
     4265     (check-next-stream-line-equal _test-output-stream "$bar:loop:"              "F - test-convert-function-with-local-var-in-named-block/7")
     4266     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-local-var-in-named-block/8")
     4267     (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")
     4268     (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")
     4269     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-local-var-in-named-block/11")
     4270     (check-next-stream-line-equal _test-output-stream "$bar:break:"             "F - test-convert-function-with-local-var-in-named-block/12")
     4271     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-in-named-block/13")
     4272     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-in-named-block/14")
     4273     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-in-named-block/15")
     4274     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-var-in-named-block/16")
     4275     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-in-named-block/17")
     4276     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-in-named-block/18")
     4277     # . epilogue
     4278     89/<- %esp 5/r32/ebp
     4279     5d/pop-to-ebp
     4280     c3/return
     4281
     4282 test-unknown-variable-in-named-block:
     4283     # . prologue
     4284     55/push-ebp
     4285     89/<- %ebp 4/r32/esp
     4286     # setup
     4287     (clear-stream _test-input-stream)
     4288     (clear-stream $_test-input-buffered-file->buffer)
     4289     (clear-stream _test-output-stream)
     4290     (clear-stream $_test-output-buffered-file->buffer)
     4291     (clear-stream _test-error-stream)
     4292     (clear-stream $_test-error-buffered-file->buffer)
     4293     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     4294     68/push 0/imm32
     4295     68/push 0/imm32
     4296     89/<- %edx 4/r32/esp
     4297     (tailor-exit-descriptor %edx 0x10)
     4298     #
     4299     (write _test-input-stream "fn foo {\n")
     4300     (write _test-input-stream "  $a: {\n")
     4301     (write _test-input-stream "    compare x, 0\n")
     4302     (write _test-input-stream "  }\n")
     4303     (write _test-input-stream "}\n")
     4304     # convert
     4305     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     4306     # registers except esp clobbered at this point
     4307     # restore ed
     4308     89/<- %edx 4/r32/esp
     4309     (flush _test-output-buffered-file)
     4310     (flush _test-error-buffered-file)
     4311 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
     4317     # check output
     4318     (check-stream-equal _test-output-stream  ""  "F - test-unknown-variable-in-named-block: output should be empty")
     4319     (check-next-stream-line-equal _test-error-stream  "fn foo: unknown variable 'x'"  "F - test-unknown-variable-in-named-block: error message")
     4320     # check that stop(1) was called
     4321     (check-ints-equal *(edx+4) 2 "F - test-unknown-variable-in-named-block: exit status")
     4322     # don't restore from ebp
     4323     81 0/subop/add %esp 8/imm32
     4324     # . epilogue
     4325     5d/pop-to-ebp
     4326     c3/return
     4327
     4328 test-always-shadow-outermost-reg-vars-in-function:
     4329     # . prologue
     4330     55/push-ebp
     4331     89/<- %ebp 4/r32/esp
     4332     # setup
     4333     (clear-stream _test-input-stream)
     4334     (clear-stream $_test-input-buffered-file->buffer)
     4335     (clear-stream _test-output-stream)
     4336     (clear-stream $_test-output-buffered-file->buffer)
     4337     #
     4338     (write _test-input-stream "fn foo {\n")
     4339     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
     4340     (write _test-input-stream "}\n")
     4341     # convert
     4342     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     4343     (flush _test-output-buffered-file)
     4344 +--  6 lines: #?     # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------
     4350     # check output
     4351     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-always-shadow-outermost-reg-vars-in-function/0")
     4352     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-always-shadow-outermost-reg-vars-in-function/1")
     4353     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-always-shadow-outermost-reg-vars-in-function/2")
     4354     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-always-shadow-outermost-reg-vars-in-function/3")
     4355     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-always-shadow-outermost-reg-vars-in-function/4")
     4356     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-always-shadow-outermost-reg-vars-in-function/5")
     4357     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-compare-register-with-literal/6")
     4358     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-always-shadow-outermost-reg-vars-in-function/8")
     4359     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-compare-register-with-literal/9")
     4360     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-always-shadow-outermost-reg-vars-in-function/12")
     4361     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-always-shadow-outermost-reg-vars-in-function/13")
     4362     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-always-shadow-outermost-reg-vars-in-function/14")
     4363     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-always-shadow-outermost-reg-vars-in-function/15")
     4364     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-always-shadow-outermost-reg-vars-in-function/16")
     4365     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-always-shadow-outermost-reg-vars-in-function/17")
     4366     # . epilogue
     4367     89/<- %esp 5/r32/ebp
     4368     5d/pop-to-ebp
     4369     c3/return
     4370
     4371 test-shadow-local:
     4372     # . prologue
     4373     55/push-ebp
     4374     89/<- %ebp 4/r32/esp
     4375     # setup
     4376     (clear-stream _test-input-stream)
     4377     (clear-stream $_test-input-buffered-file->buffer)
     4378     (clear-stream _test-output-stream)
     4379     (clear-stream $_test-output-buffered-file->buffer)
     4380     #
     4381     (write _test-input-stream "fn foo {\n")
     4382     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
     4383     (write _test-input-stream "  {\n")
     4384     (write _test-input-stream "    var y/ecx: int <- copy 4\n")
     4385     (write _test-input-stream "  }\n")
     4386     (write _test-input-stream "  x <- increment\n")
     4387     (write _test-input-stream "}\n")
     4388     # convert
     4389     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     4390     (flush _test-output-buffered-file)
     4391 +--  6 lines: #?     # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------
     4397     # check output
     4398     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-shadow-local/0")
     4399     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-shadow-local/1")
     4400     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-shadow-local/2")
     4401     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-shadow-local/3")
     4402     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-shadow-local/4")
     4403     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-shadow-local/5")
     4404     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-shadow-local/6")
     4405     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-shadow-local/7")
     4406     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-shadow-local/8")
     4407     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-shadow-local/9")
     4408     (check-next-stream-line-equal _test-output-stream "      ff 6/subop/push %ecx"  "F - test-shadow-local/10")
     4409     (check-next-stream-line-equal _test-output-stream "      b9/copy-to-ecx 4/imm32"  "F - test-shadow-local/11")
     4410     (check-next-stream-line-equal _test-output-stream "      8f 0/subop/pop %ecx" "F - test-shadow-local/12")
     4411     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-shadow-local/13")
     4412     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-shadow-local/14")
     4413     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-shadow-local/15")
     4414     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-shadow-local/16")
     4415     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-shadow-local/17")
     4416     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-shadow-local/18")
     4417     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-shadow-local/19")
     4418     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-shadow-local/20")
     4419     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-shadow-local/21")
     4420     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-shadow-local/22")
     4421     # . epilogue
     4422     89/<- %esp 5/r32/ebp
     4423     5d/pop-to-ebp
     4424     c3/return
     4425
     4426 test-shadow-name:
     4427     # . prologue
     4428     55/push-ebp
     4429     89/<- %ebp 4/r32/esp
     4430     # setup
     4431     (clear-stream _test-input-stream)
     4432     (clear-stream $_test-input-buffered-file->buffer)
     4433     (clear-stream _test-output-stream)
     4434     (clear-stream $_test-output-buffered-file->buffer)
     4435     #
     4436     (write _test-input-stream "fn foo {\n")
     4437     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
     4438     (write _test-input-stream "  {\n")
     4439     (write _test-input-stream "    var x/edx: int <- copy 4\n")
     4440     (write _test-input-stream "  }\n")
     4441     (write _test-input-stream "  x <- increment\n")
     4442     (write _test-input-stream "}\n")
     4443     # convert
     4444     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     4445     (flush _test-output-buffered-file)
     4446 +--  6 lines: #?     # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------
     4452     # check output
     4453     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-shadow-name/0")
     4454     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-shadow-name/1")
     4455     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-shadow-name/2")
     4456     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-shadow-name/3")
     4457     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-shadow-name/4")
     4458     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-shadow-name/5")
     4459     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-shadow-name/6")
     4460     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-shadow-name/7")
     4461     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-shadow-name/8")
     4462     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-shadow-name/9")
     4463     (check-next-stream-line-equal _test-output-stream "      ff 6/subop/push %edx"  "F - test-shadow-name/10")
     4464     (check-next-stream-line-equal _test-output-stream "      ba/copy-to-edx 4/imm32"  "F - test-shadow-name/11")
     4465     (check-next-stream-line-equal _test-output-stream "      8f 0/subop/pop %edx" "F - test-shadow-name/12")
     4466     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-shadow-name/13")
     4467     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-shadow-name/14")
     4468     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-shadow-name/15")
     4469     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-shadow-name/16")
     4470     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-shadow-name/17")
     4471     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-shadow-name/18")
     4472     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-shadow-name/19")
     4473     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-shadow-name/20")
     4474     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-shadow-name/21")
     4475     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-shadow-name/22")
     4476     # . epilogue
     4477     89/<- %esp 5/r32/ebp
     4478     5d/pop-to-ebp
     4479     c3/return
     4480
     4481 test-shadow-name-2:
     4482     # . prologue
     4483     55/push-ebp
     4484     89/<- %ebp 4/r32/esp
     4485     # setup
     4486     (clear-stream _test-input-stream)
     4487     (clear-stream $_test-input-buffered-file->buffer)
     4488     (clear-stream _test-output-stream)
     4489     (clear-stream $_test-output-buffered-file->buffer)
     4490     #
     4491     (write _test-input-stream "fn foo {\n")
     4492     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
     4493     (write _test-input-stream "  {\n")
     4494     (write _test-input-stream "    var x/edx: int <- copy 4\n")
     4495     (write _test-input-stream "    var y/ecx: int <- copy 5\n")
     4496     (write _test-input-stream "  }\n")
     4497     (write _test-input-stream "  x <- increment\n")
     4498     (write _test-input-stream "}\n")
     4499     # convert
     4500     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     4501     (flush _test-output-buffered-file)
     4502 +--  6 lines: #?     # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------
     4508     # check output
     4509     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-shadow-name-2/0")
     4510     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-shadow-name-2/1")
     4511     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-shadow-name-2/2")
     4512     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-shadow-name-2/3")
     4513     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-shadow-name-2/4")
     4514     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-shadow-name-2/5")
     4515     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-shadow-name-2/6")
     4516     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-shadow-name-2/7")
     4517     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-shadow-name-2/8")
     4518     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-shadow-name-2/9")
     4519     (check-next-stream-line-equal _test-output-stream "      ff 6/subop/push %edx"  "F - test-shadow-name-2/10")
     4520     (check-next-stream-line-equal _test-output-stream "      ba/copy-to-edx 4/imm32"  "F - test-shadow-name-2/11")
     4521     (check-next-stream-line-equal _test-output-stream "      ff 6/subop/push %ecx"  "F - test-shadow-name-2/12")
     4522     (check-next-stream-line-equal _test-output-stream "      b9/copy-to-ecx 5/imm32"  "F - test-shadow-name-2/13")
     4523     (check-next-stream-line-equal _test-output-stream "      8f 0/subop/pop %ecx" "F - test-shadow-name-2/14")
     4524     (check-next-stream-line-equal _test-output-stream "      8f 0/subop/pop %edx" "F - test-shadow-name-2/15")
     4525     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-shadow-name-2/16")
     4526     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-shadow-name-2/17")
     4527     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-shadow-name-2/18")
     4528     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-shadow-name-2/19")
     4529     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-shadow-name-2/20")
     4530     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-shadow-name-2/21")
     4531     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-shadow-name-2/22")
     4532     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-shadow-name-2/23")
     4533     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-shadow-name-2/24")
     4534     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-shadow-name-2/25")
     4535     # . epilogue
     4536     89/<- %esp 5/r32/ebp
     4537     5d/pop-to-ebp
     4538     c3/return
     4539
     4540 test-do-not-spill-same-register-in-block:
     4541     # . prologue
     4542     55/push-ebp
     4543     89/<- %ebp 4/r32/esp
     4544     # setup
     4545     (clear-stream _test-input-stream)
     4546     (clear-stream $_test-input-buffered-file->buffer)
     4547     (clear-stream _test-output-stream)
     4548     (clear-stream $_test-output-buffered-file->buffer)
     4549     #
     4550     (write _test-input-stream "fn foo {\n")
     4551     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
     4552     (write _test-input-stream "  var y/ecx: int <- copy 4\n")
     4553     (write _test-input-stream "  y <- increment\n")
     4554     (write _test-input-stream "}\n")
     4555     # convert
     4556     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     4557     (flush _test-output-buffered-file)
     4558 +--  6 lines: #?     # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------
     4564     # check output
     4565     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-do-not-spill-same-register-in-block/0")
     4566     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-do-not-spill-same-register-in-block/1")
     4567     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-do-not-spill-same-register-in-block/2")
     4568     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-do-not-spill-same-register-in-block/3")
     4569     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-do-not-spill-same-register-in-block/4")
     4570     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-do-not-spill-same-register-in-block/5")
     4571     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-do-not-spill-same-register-in-block/6")
     4572     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"  "F - test-do-not-spill-same-register-in-block/7")
     4573     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 4/imm32"  "F - test-do-not-spill-same-register-in-block/8")
     4574     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-do-not-spill-same-register-in-block/9")
     4575     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-do-not-spill-same-register-in-block/10")
     4576     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-do-not-spill-same-register-in-block/11")
     4577     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-do-not-spill-same-register-in-block/12")
     4578     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-do-not-spill-same-register-in-block/13")
     4579     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-do-not-spill-same-register-in-block/14")
     4580     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-do-not-spill-same-register-in-block/15")
     4581     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-do-not-spill-same-register-in-block/16")
     4582     # . epilogue
     4583     89/<- %esp 5/r32/ebp
     4584     5d/pop-to-ebp
     4585     c3/return
     4586
     4587 test-spill-different-register-in-block:
     4588     # . prologue
     4589     55/push-ebp
     4590     89/<- %ebp 4/r32/esp
     4591     # setup
     4592     (clear-stream _test-input-stream)
     4593     (clear-stream $_test-input-buffered-file->buffer)
     4594     (clear-stream _test-output-stream)
     4595     (clear-stream $_test-output-buffered-file->buffer)
     4596     #
     4597     (write _test-input-stream "fn foo {\n")
     4598     (write _test-input-stream "  var x/eax: int <- copy 3\n")
     4599     (write _test-input-stream "  var y/ecx: int <- copy 4\n")
     4600     (write _test-input-stream "  y <- increment\n")
     4601     (write _test-input-stream "}\n")
     4602     # convert
     4603     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     4604     (flush _test-output-buffered-file)
     4605 +--  6 lines: #?     # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------
     4611     # check output
     4612     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-spill-different-register-in-block/0")
     4613     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-spill-different-register-in-block/1")
     4614     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-spill-different-register-in-block/2")
     4615     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-spill-different-register-in-block/3")
     4616     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-spill-different-register-in-block/4")
     4617     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-spill-different-register-in-block/5")
     4618     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-spill-different-register-in-block/6")
     4619     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 3/imm32"  "F - test-spill-different-register-in-block/7")
     4620     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-spill-different-register-in-block/8")
     4621     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 4/imm32"  "F - test-spill-different-register-in-block/9")
     4622     (check-next-stream-line-equal _test-output-stream "    41/increment-ecx"    "F - test-spill-different-register-in-block/10")
     4623     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-spill-different-register-in-block/11")
     4624     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax" "F - test-spill-different-register-in-block/12")
     4625     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-spill-different-register-in-block/13")
     4626     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-spill-different-register-in-block/14")
     4627     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-spill-different-register-in-block/15")
     4628     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-spill-different-register-in-block/16")
     4629     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-spill-different-register-in-block/17")
     4630     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-spill-different-register-in-block/18")
     4631     # . epilogue
     4632     89/<- %esp 5/r32/ebp
     4633     5d/pop-to-ebp
     4634     c3/return
     4635
     4636 test-convert-function-with-branches-in-block:
     4637     # . prologue
     4638     55/push-ebp
     4639     89/<- %ebp 4/r32/esp
     4640     # setup
     4641     (clear-stream _test-input-stream)
     4642     (clear-stream $_test-input-buffered-file->buffer)
     4643     (clear-stream _test-output-stream)
     4644     (clear-stream $_test-output-buffered-file->buffer)
     4645     #
     4646     (write _test-input-stream "fn foo x: int {\n")
     4647     (write _test-input-stream "  {\n")
     4648     (write _test-input-stream "    break-if->=\n")
     4649     (write _test-input-stream "    loop-if-addr<\n")
     4650     (write _test-input-stream "    increment x\n")
     4651     (write _test-input-stream "    loop\n")
     4652     (write _test-input-stream "  }\n")
     4653     (write _test-input-stream "}\n")
     4654     # convert
     4655     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     4656     (flush _test-output-buffered-file)
     4657 +--  6 lines: #?     # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------
     4663     # check output
     4664     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-branches-in-block/0")
     4665     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-branches-in-block/1")
     4666     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-branches-in-block/2")
     4667     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-branches-in-block/3")
     4668     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-branches-in-block/4")
     4669     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-branches-in-block/5")
     4670     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-branches-in-block/6")
     4671     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-branches-in-block/7")
     4672     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-in-block/8")
     4673     (check-next-stream-line-equal _test-output-stream "        0f 8c/jump-if-< break/disp32"  "F - test-convert-function-with-branches-in-block/9")
     4674     (check-next-stream-line-equal _test-output-stream "        e9/jump $foo:0x00000002:break/disp32"  "F - test-convert-function-with-branches-in-block/10")
     4675     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-in-block/11")
     4676     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-in-block/12")
     4677     (check-next-stream-line-equal _test-output-stream "        0f 83/jump-if-addr>= break/disp32"  "F - test-convert-function-with-branches-in-block/13")
     4678     (check-next-stream-line-equal _test-output-stream "        e9/jump $foo:0x00000002:loop/disp32"  "F - test-convert-function-with-branches-in-block/14")
     4679     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-in-block/15")
     4680     (check-next-stream-line-equal _test-output-stream "      ff 0/subop/increment *(ebp+0x00000008)"  "F - test-convert-function-with-branches-in-block/16")
     4681     (check-next-stream-line-equal _test-output-stream "      e9/jump loop/disp32"  "F - test-convert-function-with-branches-in-block/17")
     4682     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-branches-in-block/18")
     4683     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-branches-in-block/19")
     4684     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-branches-in-block/20")
     4685     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-branches-in-block/21")
     4686     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-branches-in-block/22")
     4687     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-branches-in-block/23")
     4688     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-branches-in-block/24")
     4689     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-branches-in-block/25")
     4690     # . epilogue
     4691     89/<- %esp 5/r32/ebp
     4692     5d/pop-to-ebp
     4693     c3/return
     4694
     4695 test-convert-function-with-branches-in-block-2:
     4696     # . prologue
     4697     55/push-ebp
     4698     89/<- %ebp 4/r32/esp
     4699     # setup
     4700     (clear-stream _test-input-stream)
     4701     (clear-stream $_test-input-buffered-file->buffer)
     4702     (clear-stream _test-output-stream)
     4703     (clear-stream $_test-output-buffered-file->buffer)
     4704     #
     4705     (write _test-input-stream "fn foo x: int {\n")
     4706     (write _test-input-stream "  {\n")
     4707     (write _test-input-stream "    break-if->=\n")
     4708     (write _test-input-stream "    loop-if-float<\n")
     4709     (write _test-input-stream "    increment x\n")
     4710     (write _test-input-stream "    loop\n")
     4711     (write _test-input-stream "  }\n")
     4712     (write _test-input-stream "}\n")
     4713     # convert
     4714     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     4715     (flush _test-output-buffered-file)
     4716 +--  6 lines: #?     # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------
     4722     # check output
     4723     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-branches-in-block/0")
     4724     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-branches-in-block/1")
     4725     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-branches-in-block/2")
     4726     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-branches-in-block/3")
     4727     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-branches-in-block/4")
     4728     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-branches-in-block/5")
     4729     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-branches-in-block/6")
     4730     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-branches-in-block/7")
     4731     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-in-block/8")
     4732     (check-next-stream-line-equal _test-output-stream "        0f 8c/jump-if-< break/disp32"  "F - test-convert-function-with-branches-in-block/9")
     4733     (check-next-stream-line-equal _test-output-stream "        e9/jump $foo:0x00000002:break/disp32"  "F - test-convert-function-with-branches-in-block/10")
     4734     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-in-block/11")
     4735     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-in-block/12")
     4736     (check-next-stream-line-equal _test-output-stream "        0f 83/jump-if-addr>= break/disp32"  "F - test-convert-function-with-branches-in-block/13")
     4737     (check-next-stream-line-equal _test-output-stream "        e9/jump $foo:0x00000002:loop/disp32"  "F - test-convert-function-with-branches-in-block/14")
     4738     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-in-block/15")
     4739     (check-next-stream-line-equal _test-output-stream "      ff 0/subop/increment *(ebp+0x00000008)"  "F - test-convert-function-with-branches-in-block/16")
     4740     (check-next-stream-line-equal _test-output-stream "      e9/jump loop/disp32"  "F - test-convert-function-with-branches-in-block/17")
     4741     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-branches-in-block/18")
     4742     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-branches-in-block/19")
     4743     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-branches-in-block/20")
     4744     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-branches-in-block/21")
     4745     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-branches-in-block/22")
     4746     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-branches-in-block/23")
     4747     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-branches-in-block/24")
     4748     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-branches-in-block/25")
     4749     # . epilogue
     4750     89/<- %esp 5/r32/ebp
     4751     5d/pop-to-ebp
     4752     c3/return
     4753
     4754 test-convert-function-with-branches-in-named-block:
     4755     # . prologue
     4756     55/push-ebp
     4757     89/<- %ebp 4/r32/esp
     4758     # setup
     4759     (clear-stream _test-input-stream)
     4760     (clear-stream $_test-input-buffered-file->buffer)
     4761     (clear-stream _test-output-stream)
     4762     (clear-stream $_test-output-buffered-file->buffer)
     4763     #
     4764     (write _test-input-stream "fn foo x: int {\n")
     4765     (write _test-input-stream "  $bar: {\n")
     4766     (write _test-input-stream "    break-if->= $bar\n")
     4767     (write _test-input-stream "    loop-if-addr< $bar\n")
     4768     (write _test-input-stream "    increment x\n")
     4769     (write _test-input-stream "    loop\n")
     4770     (write _test-input-stream "  }\n")
     4771     (write _test-input-stream "}\n")
     4772     # convert
     4773     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     4774     (flush _test-output-buffered-file)
     4775 +--  6 lines: #?     # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------
     4781     # check output
     4782     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-branches-in-named-block/0")
     4783     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-branches-in-named-block/1")
     4784     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-branches-in-named-block/2")
     4785     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-branches-in-named-block/3")
     4786     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-branches-in-named-block/4")
     4787     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-branches-in-named-block/5")
     4788     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-branches-in-named-block/6")
     4789     (check-next-stream-line-equal _test-output-stream "$bar:loop:"              "F - test-convert-function-with-branches-in-named-block/7")
     4790     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-in-named-block/8")
     4791     (check-next-stream-line-equal _test-output-stream "        0f 8c/jump-if-< break/disp32"  "F - test-convert-function-with-branches-in-named-block/9")
     4792     (check-next-stream-line-equal _test-output-stream "        e9/jump $bar:break/disp32"  "F - test-convert-function-with-branches-in-named-block/10")
     4793     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-in-named-block/11")
     4794     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-in-named-block/12")
     4795     (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")
     4796     (check-next-stream-line-equal _test-output-stream "        e9/jump $bar:loop/disp32"  "F - test-convert-function-with-branches-in-named-block/14")
     4797     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-in-named-block/15")
     4798     (check-next-stream-line-equal _test-output-stream "      ff 0/subop/increment *(ebp+0x00000008)"  "F - test-convert-function-with-branches-in-named-block/16")
     4799     (check-next-stream-line-equal _test-output-stream "      e9/jump loop/disp32"   "F - test-convert-function-with-branches-in-named-block/17")
     4800     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-branches-in-named-block/18")
     4801     (check-next-stream-line-equal _test-output-stream "$bar:break:"             "F - test-convert-function-with-branches-in-named-block/19")
     4802     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-branches-in-named-block/20")
     4803     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-branches-in-named-block/21")
     4804     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-branches-in-named-block/22")
     4805     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-branches-in-named-block/23")
     4806     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-branches-in-named-block/24")
     4807     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-branches-in-named-block/25")
     4808     # . epilogue
     4809     89/<- %esp 5/r32/ebp
     4810     5d/pop-to-ebp
     4811     c3/return
     4812
     4813 test-convert-function-with-var-in-nested-block:
     4814     # . prologue
     4815     55/push-ebp
     4816     89/<- %ebp 4/r32/esp
     4817     # setup
     4818     (clear-stream _test-input-stream)
     4819     (clear-stream $_test-input-buffered-file->buffer)
     4820     (clear-stream _test-output-stream)
     4821     (clear-stream $_test-output-buffered-file->buffer)
     4822     #
     4823     (write _test-input-stream "fn foo x: int {\n")
     4824     (write _test-input-stream "  {\n")
     4825     (write _test-input-stream "    {\n")
     4826     (write _test-input-stream "      var x: int\n")
     4827     (write _test-input-stream "      increment x\n")
     4828     (write _test-input-stream "    }\n")
     4829     (write _test-input-stream "  }\n")
     4830     (write _test-input-stream "}\n")
     4831     # convert
     4832     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     4833     (flush _test-output-buffered-file)
     4834 +--  6 lines: #?     # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------
     4840     # check output
     4841     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-var-in-nested-block/0")
     4842     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-var-in-nested-block/1")
     4843     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-var-in-nested-block/2")
     4844     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-var-in-nested-block/3")
     4845     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-var-in-nested-block/4")
     4846     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-var-in-nested-block/5")
     4847     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-var-in-nested-block/6")
     4848     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-var-in-nested-block/7")
     4849     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-var-in-nested-block/8")
     4850     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-var-in-nested-block/9")
     4851     (check-next-stream-line-equal _test-output-stream "        68/push 0/imm32" "F - test-convert-function-with-var-in-nested-block/10")
     4852     (check-next-stream-line-equal _test-output-stream "        ff 0/subop/increment *(ebp+0xfffffffc)"  "F - test-convert-function-with-var-in-nested-block/11")
     4853     (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")
     4854     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-var-in-nested-block/13")
     4855     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-var-in-nested-block/14")
     4856     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-var-in-nested-block/15")
     4857     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-var-in-nested-block/16")
     4858     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-var-in-nested-block/17")
     4859     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-var-in-nested-block/18")
     4860     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-var-in-nested-block/19")
     4861     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-var-in-nested-block/20")
     4862     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-var-in-nested-block/21")
     4863     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-var-in-nested-block/22")
     4864     # . epilogue
     4865     89/<- %esp 5/r32/ebp
     4866     5d/pop-to-ebp
     4867     c3/return
     4868
     4869 test-convert-function-with-multiple-vars-in-nested-blocks:
     4870     # . prologue
     4871     55/push-ebp
     4872     89/<- %ebp 4/r32/esp
     4873     # setup
     4874     (clear-stream _test-input-stream)
     4875     (clear-stream $_test-input-buffered-file->buffer)
     4876     (clear-stream _test-output-stream)
     4877     (clear-stream $_test-output-buffered-file->buffer)
     4878     #
     4879     (write _test-input-stream "fn foo x: int {\n")
     4880     (write _test-input-stream "  {\n")
     4881     (write _test-input-stream "    var x/eax: int <- copy 0\n")
     4882     (write _test-input-stream "    {\n")
     4883     (write _test-input-stream "      var y: int\n")
     4884     (write _test-input-stream "      x <- add y\n")
     4885     (write _test-input-stream "    }\n")
     4886     (write _test-input-stream "  }\n")
     4887     (write _test-input-stream "}\n")
     4888     # convert
     4889     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     4890     (flush _test-output-buffered-file)
     4891 +--  6 lines: #?     # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------
     4897     # check output
     4898     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-multiple-vars-in-nested-blocks/0")
     4899     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-multiple-vars-in-nested-blocks/1")
     4900     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-multiple-vars-in-nested-blocks/2")
     4901     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/3")
     4902     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-multiple-vars-in-nested-blocks/4")
     4903     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-multiple-vars-in-nested-blocks/5")
     4904     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-multiple-vars-in-nested-blocks/6")
     4905     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-multiple-vars-in-nested-blocks/7")
     4906     (check-next-stream-line-equal _test-output-stream "      ff 6/subop/push %eax"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/8")
     4907     (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")
     4908     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-multiple-vars-in-nested-blocks/10")
     4909     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-multiple-vars-in-nested-blocks/11")
     4910     (check-next-stream-line-equal _test-output-stream "        68/push 0/imm32" "F - test-convert-function-with-multiple-vars-in-nested-blocks/12")
     4911     (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")
     4912     (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")
     4913     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-multiple-vars-in-nested-blocks/15")
     4914     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/16")
     4915     (check-next-stream-line-equal _test-output-stream "      8f 0/subop/pop %eax"   "F - test-convert-function-with-multiple-vars-in-nested-blocks/17")
     4916     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-multiple-vars-in-nested-blocks/18")
     4917     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/19")
     4918     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-multiple-vars-in-nested-blocks/20")
     4919     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/21")
     4920     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-multiple-vars-in-nested-blocks/22")
     4921     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-multiple-vars-in-nested-blocks/23")
     4922     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-multiple-vars-in-nested-blocks/24")
     4923     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-multiple-vars-in-nested-blocks/25")
     4924     # . epilogue
     4925     89/<- %esp 5/r32/ebp
     4926     5d/pop-to-ebp
     4927     c3/return
     4928
     4929 test-convert-function-with-branches-and-local-vars:
     4930     # A conditional 'break' after a 'var' in a block is converted into a
     4931     # nested block that performs all necessary cleanup before jumping. This
     4932     # results in some ugly code duplication.
     4933     # . prologue
     4934     55/push-ebp
     4935     89/<- %ebp 4/r32/esp
     4936     # setup
     4937     (clear-stream _test-input-stream)
     4938     (clear-stream $_test-input-buffered-file->buffer)
     4939     (clear-stream _test-output-stream)
     4940     (clear-stream $_test-output-buffered-file->buffer)
     4941     #
     4942     (write _test-input-stream "fn foo {\n")
     4943     (write _test-input-stream "  {\n")
     4944     (write _test-input-stream "    var x: int\n")
     4945     (write _test-input-stream "    break-if->=\n")
     4946     (write _test-input-stream "    increment x\n")
     4947     (write _test-input-stream "  }\n")
     4948     (write _test-input-stream "}\n")
     4949     # convert
     4950     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     4951     (flush _test-output-buffered-file)
     4952 +--  6 lines: #?     # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------
     4958     # check output
     4959     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-branches-and-local-vars/0")
     4960     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-branches-and-local-vars/1")
     4961     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-branches-and-local-vars/2")
     4962     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-branches-and-local-vars/3")
     4963     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-branches-and-local-vars/4")
     4964     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-branches-and-local-vars/5")
     4965     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-branches-and-local-vars/6")
     4966     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-branches-and-local-vars/7")
     4967     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-branches-and-local-vars/8")
     4968     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-and-local-vars/9")
     4969     (check-next-stream-line-equal _test-output-stream "        0f 8c/jump-if-< break/disp32"  "F - test-convert-function-with-branches-and-local-vars/10")
     4970     (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")
     4971     (check-next-stream-line-equal _test-output-stream "        e9/jump $foo:0x00000002:break/disp32"  "F - test-convert-function-with-branches-and-local-vars/12")
     4972     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-and-local-vars/13")
     4973     (check-next-stream-line-equal _test-output-stream "      ff 0/subop/increment *(ebp+0xfffffffc)"  "F - test-convert-function-with-branches-and-local-vars/14")
     4974     (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")
     4975     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-branches-and-local-vars/16")
     4976     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-branches-and-local-vars/17")
     4977     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-branches-and-local-vars/18")
     4978     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-branches-and-local-vars/19")
     4979     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-branches-and-local-vars/20")
     4980     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-branches-and-local-vars/21")
     4981     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-branches-and-local-vars/22")
     4982     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-branches-and-local-vars/23")
     4983     # . epilogue
     4984     89/<- %esp 5/r32/ebp
     4985     5d/pop-to-ebp
     4986     c3/return
     4987
     4988 test-convert-function-with-conditional-loops-and-local-vars:
     4989     # A conditional 'loop' after a 'var' in a block is converted into a nested
     4990     # block that performs all necessary cleanup before jumping. This results
     4991     # in some ugly code duplication.
     4992     # . prologue
     4993     55/push-ebp
     4994     89/<- %ebp 4/r32/esp
     4995     # setup
     4996     (clear-stream _test-input-stream)
     4997     (clear-stream $_test-input-buffered-file->buffer)
     4998     (clear-stream _test-output-stream)
     4999     (clear-stream $_test-output-buffered-file->buffer)
     5000     #
     5001     (write _test-input-stream "fn foo {\n")
     5002     (write _test-input-stream "  {\n")
     5003     (write _test-input-stream "    var x: int\n")
     5004     (write _test-input-stream "    loop-if->=\n")
     5005     (write _test-input-stream "    increment x\n")
     5006     (write _test-input-stream "  }\n")
     5007     (write _test-input-stream "}\n")
     5008     # convert
     5009     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     5010     (flush _test-output-buffered-file)
     5011 +--  6 lines: #?     # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------
     5017     # check output
     5018     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-conditional-loops-and-local-vars/0")
     5019     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-conditional-loops-and-local-vars/1")
     5020     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-conditional-loops-and-local-vars/2")
     5021     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-conditional-loops-and-local-vars/3")
     5022     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-conditional-loops-and-local-vars/4")
     5023     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-conditional-loops-and-local-vars/5")
     5024     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-conditional-loops-and-local-vars/6")
     5025     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-conditional-loops-and-local-vars/7")
     5026     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-conditional-loops-and-local-vars/8")
     5027     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-conditional-loops-and-local-vars/9")
     5028     (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")
     5029     (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")
     5030     (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")
     5031     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-conditional-loops-and-local-vars/13")
     5032     (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")
     5033     (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")
     5034     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-conditional-loops-and-local-vars/16")
     5035     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-conditional-loops-and-local-vars/17")
     5036     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-conditional-loops-and-local-vars/18")
     5037     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-conditional-loops-and-local-vars/19")
     5038     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-conditional-loops-and-local-vars/20")
     5039     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-conditional-loops-and-local-vars/21")
     5040     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-conditional-loops-and-local-vars/22")
     5041     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-conditional-loops-and-local-vars/23")
     5042     # . epilogue
     5043     89/<- %esp 5/r32/ebp
     5044     5d/pop-to-ebp
     5045     c3/return
     5046
     5047 test-convert-function-with-unconditional-loops-and-local-vars:
     5048     # An unconditional 'loop' after a 'var' in a block is emitted _after_ the
     5049     # regular block cleanup. Any instructions after 'loop' are dead and
     5050     # therefore skipped.
     5051     # . prologue
     5052     55/push-ebp
     5053     89/<- %ebp 4/r32/esp
     5054     # setup
     5055     (clear-stream _test-input-stream)
     5056     (clear-stream $_test-input-buffered-file->buffer)
     5057     (clear-stream _test-output-stream)
     5058     (clear-stream $_test-output-buffered-file->buffer)
     5059     #
     5060     (write _test-input-stream "fn foo {\n")
     5061     (write _test-input-stream "  {\n")
     5062     (write _test-input-stream "    var x: int\n")
     5063     (write _test-input-stream "    loop\n")
     5064     (write _test-input-stream "    increment x\n")
     5065     (write _test-input-stream "  }\n")
     5066     (write _test-input-stream "}\n")
     5067     # convert
     5068     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     5069     (flush _test-output-buffered-file)
     5070 +--  6 lines: #?     # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------
     5076     # check output
     5077     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-unconditional-loops-and-local-vars/0")
     5078     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-unconditional-loops-and-local-vars/1")
     5079     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-unconditional-loops-and-local-vars/2")
     5080     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-unconditional-loops-and-local-vars/3")
     5081     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-unconditional-loops-and-local-vars/4")
     5082     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-unconditional-loops-and-local-vars/5")
     5083     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-unconditional-loops-and-local-vars/6")
     5084     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-unconditional-loops-and-local-vars/7")
     5085     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-unconditional-loops-and-local-vars/8")
     5086     (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")
     5087     (check-next-stream-line-equal _test-output-stream "      e9/jump loop/disp32"  "F - test-convert-function-with-unconditional-loops-and-local-vars/10")
     5088     # not emitted:                                           ff 0/subop/increment *(ebp+0xfffffffc)
     5089     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-unconditional-loops-and-local-vars/11")
     5090     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-unconditional-loops-and-local-vars/12")
     5091     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-unconditional-loops-and-local-vars/13")
     5092     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-unconditional-loops-and-local-vars/14")
     5093     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-unconditional-loops-and-local-vars/15")
     5094     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-unconditional-loops-and-local-vars/16")
     5095     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-unconditional-loops-and-local-vars/17")
     5096     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-unconditional-loops-and-local-vars/18")
     5097     # . epilogue
     5098     89/<- %esp 5/r32/ebp
     5099     5d/pop-to-ebp
     5100     c3/return
     5101
     5102 test-convert-function-with-branches-and-loops-and-local-vars:
     5103     # . prologue
     5104     55/push-ebp
     5105     89/<- %ebp 4/r32/esp
     5106     # setup
     5107     (clear-stream _test-input-stream)
     5108     (clear-stream $_test-input-buffered-file->buffer)
     5109     (clear-stream _test-output-stream)
     5110     (clear-stream $_test-output-buffered-file->buffer)
     5111     #
     5112     (write _test-input-stream "fn foo {\n")
     5113     (write _test-input-stream "  {\n")
     5114     (write _test-input-stream "    var x: int\n")
     5115     (write _test-input-stream "    break-if->=\n")
     5116     (write _test-input-stream "    increment x\n")
     5117     (write _test-input-stream "    loop\n")
     5118     (write _test-input-stream "  }\n")
     5119     (write _test-input-stream "}\n")
     5120     # convert
     5121     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     5122     (flush _test-output-buffered-file)
     5123 +--  6 lines: #?     # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------
     5129     # check output
     5130     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-branches-and-loops-and-local-vars/0")
     5131     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-branches-and-loops-and-local-vars/1")
     5132     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-branches-and-loops-and-local-vars/2")
     5133     (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")
     5134     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-branches-and-loops-and-local-vars/4")
     5135     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-branches-and-loops-and-local-vars/5")
     5136     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-branches-and-loops-and-local-vars/6")
     5137     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-branches-and-loops-and-local-vars/7")
     5138     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-branches-and-loops-and-local-vars/8")
     5139     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-branches-and-loops-and-local-vars/9")
     5140     (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")
     5141     (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")
     5142     (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")
     5143     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-branches-and-loops-and-local-vars/13")
     5144     (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")
     5145     (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")
     5146     (check-next-stream-line-equal _test-output-stream "      e9/jump loop/disp32"  "F - test-convert-function-with-branches-and-loops-and-local-vars/16")
     5147     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-branches-and-loops-and-local-vars/17")
     5148     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-branches-and-loops-and-local-vars/18")
     5149     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-branches-and-loops-and-local-vars/19")
     5150     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-branches-and-loops-and-local-vars/20")
     5151     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-branches-and-loops-and-local-vars/21")
     5152     (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")
     5153     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-branches-and-loops-and-local-vars/23")
     5154     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-branches-and-loops-and-local-vars/24")
     5155     # . epilogue
     5156     89/<- %esp 5/r32/ebp
     5157     5d/pop-to-ebp
     5158     c3/return
     5159
     5160 test-convert-function-with-nonlocal-branches-and-loops-and-local-vars:
     5161     # . prologue
     5162     55/push-ebp
     5163     89/<- %ebp 4/r32/esp
     5164     # setup
     5165     (clear-stream _test-input-stream)
     5166     (clear-stream $_test-input-buffered-file->buffer)
     5167     (clear-stream _test-output-stream)
     5168     (clear-stream $_test-output-buffered-file->buffer)
     5169     #
     5170     (write _test-input-stream "fn foo {\n")
     5171     (write _test-input-stream "  a: {\n")
     5172     (write _test-input-stream "    var x: int\n")
     5173     (write _test-input-stream "    {\n")
     5174     (write _test-input-stream "      var y: int\n")
     5175     (write _test-input-stream "      break-if->= a\n")
     5176     (write _test-input-stream "      increment x\n")
     5177     (write _test-input-stream "      loop\n")
     5178     (write _test-input-stream "    }\n")
     5179     (write _test-input-stream "  }\n")
     5180     (write _test-input-stream "}\n")
     5181     # convert
     5182     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     5183     (flush _test-output-buffered-file)
     5184 +--  6 lines: #?     # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------
     5190     # check output
     5191     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/0")
     5192     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/1")
     5193     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/2")
     5194     (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")
     5195     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/4")
     5196     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/5")
     5197     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/6")
     5198     (check-next-stream-line-equal _test-output-stream "a:loop:"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/7")
     5199     (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")
     5200     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/9")
     5201     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/10")
     5202     (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")
     5203     (check-next-stream-line-equal _test-output-stream "        {"               "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/12")
     5204     (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")
     5205     (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")
     5206     (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")
     5207     (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")
     5208     (check-next-stream-line-equal _test-output-stream "        }"               "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/17")
     5209     (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")
     5210     (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")
     5211     (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")
     5212     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/21")
     5213     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/22")
     5214     (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")
     5215     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/24")
     5216     (check-next-stream-line-equal _test-output-stream "a:break:"                "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/25")
     5217     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/26")
     5218     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/27")
     5219     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/28")
     5220     (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")
     5221     (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")
     5222     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars/31")
     5223     # . epilogue
     5224     89/<- %esp 5/r32/ebp
     5225     5d/pop-to-ebp
     5226     c3/return
     5227
     5228 test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2:
     5229     # . prologue
     5230     55/push-ebp
     5231     89/<- %ebp 4/r32/esp
     5232     # setup
     5233     (clear-stream _test-input-stream)
     5234     (clear-stream $_test-input-buffered-file->buffer)
     5235     (clear-stream _test-output-stream)
     5236     (clear-stream $_test-output-buffered-file->buffer)
     5237     # non-local conditional branch from a block without a local variable,
     5238     # unwinding a local on the stack
     5239     (write _test-input-stream "fn foo {\n")
     5240     (write _test-input-stream "  a: {\n")
     5241     (write _test-input-stream "    var x: int\n")
     5242     (write _test-input-stream "    {\n")
     5243     (write _test-input-stream "      break-if->= a\n")
     5244     (write _test-input-stream "    }\n")
     5245     (write _test-input-stream "  }\n")
     5246     (write _test-input-stream "}\n")
     5247     # convert
     5248     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     5249     (flush _test-output-buffered-file)
     5250 +--  6 lines: #?     # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------
     5256     # check output
     5257     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/0")
     5258     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/1")
     5259     (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")
     5260     (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")
     5261     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/4")
     5262     (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")
     5263     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/6")
     5264     (check-next-stream-line-equal _test-output-stream "a:loop:"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/7")
     5265     (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")
     5266     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/9")
     5267     (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")
     5268     (check-next-stream-line-equal _test-output-stream "        {"               "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/11")
     5269     (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")
     5270     (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")
     5271     (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")
     5272     (check-next-stream-line-equal _test-output-stream "        }"               "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/15")
     5273     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/16")
     5274     (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")
     5275     (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")
     5276     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/19")
     5277     (check-next-stream-line-equal _test-output-stream "a:break:"                "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/20")
     5278     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/21")
     5279     (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")
     5280     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/23")
     5281     (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")
     5282     (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")
     5283     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-2/26")
     5284     # . epilogue
     5285     89/<- %esp 5/r32/ebp
     5286     5d/pop-to-ebp
     5287     c3/return
     5288
     5289 test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3:
     5290     # . prologue
     5291     55/push-ebp
     5292     89/<- %ebp 4/r32/esp
     5293     # setup
     5294     (clear-stream _test-input-stream)
     5295     (clear-stream $_test-input-buffered-file->buffer)
     5296     (clear-stream _test-output-stream)
     5297     (clear-stream $_test-output-buffered-file->buffer)
     5298     # non-local unconditional branch from a block without a local variable,
     5299     # unwinding a local on the stack
     5300     (write _test-input-stream "fn foo {\n")
     5301     (write _test-input-stream "  a: {\n")
     5302     (write _test-input-stream "    var x: int\n")
     5303     (write _test-input-stream "    {\n")
     5304     (write _test-input-stream "      break a\n")
     5305     (write _test-input-stream "    }\n")
     5306     (write _test-input-stream "  }\n")
     5307     (write _test-input-stream "}\n")
     5308     # convert
     5309     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     5310     (flush _test-output-buffered-file)
     5311 +--  6 lines: #?     # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------
     5317     # check output
     5318     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/0")
     5319     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/1")
     5320     (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")
     5321     (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")
     5322     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/4")
     5323     (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")
     5324     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/6")
     5325     (check-next-stream-line-equal _test-output-stream "a:loop:"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/7")
     5326     (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")
     5327     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/9")
     5328     (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")
     5329     (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")
     5330     (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")
     5331     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/14")
     5332     (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")
     5333     (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")
     5334     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/17")
     5335     (check-next-stream-line-equal _test-output-stream "a:break:"                "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/18")
     5336     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/19")
     5337     (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")
     5338     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/21")
     5339     (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")
     5340     (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")
     5341     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-3/24")
     5342     # . epilogue
     5343     89/<- %esp 5/r32/ebp
     5344     5d/pop-to-ebp
     5345     c3/return
     5346
     5347 test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4:
     5348     # . prologue
     5349     55/push-ebp
     5350     89/<- %ebp 4/r32/esp
     5351     # setup
     5352     (clear-stream _test-input-stream)
     5353     (clear-stream $_test-input-buffered-file->buffer)
     5354     (clear-stream _test-output-stream)
     5355     (clear-stream $_test-output-buffered-file->buffer)
     5356     #
     5357     (write _test-input-stream "fn foo {\n")
     5358     (write _test-input-stream "  a: {\n")
     5359     (write _test-input-stream "    var x/esi: int <- copy 0\n")
     5360     (write _test-input-stream "    {\n")
     5361     (write _test-input-stream "      break a\n")
     5362     (write _test-input-stream "    }\n")
     5363     (write _test-input-stream "  }\n")
     5364     (write _test-input-stream "}\n")
     5365     # convert
     5366     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     5367     (flush _test-output-buffered-file)
     5368 +--  6 lines: #?     # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------
     5374     # check output
     5375     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/0")
     5376     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/1")
     5377     (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")
     5378     (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")
     5379     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/4")
     5380     (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")
     5381     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/6")
     5382     (check-next-stream-line-equal _test-output-stream "a:loop:"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/7")
     5383     (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")
     5384     (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")
     5385     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/10")
     5386     (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")
     5387     (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")
     5388     (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")
     5389     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/14")
     5390     (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")
     5391     (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")
     5392     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/17")
     5393     (check-next-stream-line-equal _test-output-stream "a:break:"                "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/18")
     5394     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/19")
     5395     (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")
     5396     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/21")
     5397     (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")
     5398     (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")
     5399     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-nonlocal-branches-and-loops-and-local-vars-4/24")
     5400     # . epilogue
     5401     89/<- %esp 5/r32/ebp
     5402     5d/pop-to-ebp
     5403     c3/return
     5404
     5405 test-convert-function-with-nonlocal-unconditional-break-and-local-vars:
     5406     # . prologue
     5407     55/push-ebp
     5408     89/<- %ebp 4/r32/esp
     5409     # setup
     5410     (clear-stream _test-input-stream)
     5411     (clear-stream $_test-input-buffered-file->buffer)
     5412     (clear-stream _test-output-stream)
     5413     (clear-stream $_test-output-buffered-file->buffer)
     5414     #
     5415     (write _test-input-stream "fn foo {\n")
     5416     (write _test-input-stream "  a: {\n")
     5417     (write _test-input-stream "    var x: int\n")
     5418     (write _test-input-stream "    {\n")
     5419     (write _test-input-stream "      var y: int\n")
     5420     (write _test-input-stream "      break a\n")
     5421     (write _test-input-stream "      increment x\n")
     5422     (write _test-input-stream "    }\n")
     5423     (write _test-input-stream "  }\n")
     5424     (write _test-input-stream "}\n")
     5425     # convert
     5426     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     5427     (flush _test-output-buffered-file)
     5428 +--  6 lines: #?     # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------
     5434     # check output
     5435     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/0")
     5436     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/1")
     5437     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/2")
     5438     (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")
     5439     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/4")
     5440     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/5")
     5441     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/6")
     5442     (check-next-stream-line-equal _test-output-stream "a:loop:"                 "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/7")
     5443     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/8")
     5444     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/9")
     5445     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/10")
     5446     (check-next-stream-line-equal _test-output-stream "        68/push 0/imm32" "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/11")
     5447     (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")
     5448     (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")
     5449     (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")
     5450     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/15")
     5451     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/16")
     5452     (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")
     5453     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/18")
     5454     (check-next-stream-line-equal _test-output-stream "a:break:"                "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/19")
     5455     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/20")
     5456     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/21")
     5457     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/22")
     5458     (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")
     5459     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/24")
     5460     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-nonlocal-unconditional-break-and-local-vars/25")
     5461     # . epilogue
     5462     89/<- %esp 5/r32/ebp
     5463     5d/pop-to-ebp
     5464     c3/return
     5465
     5466 test-convert-function-with-unconditional-break-and-local-vars:
     5467     # . prologue
     5468     55/push-ebp
     5469     89/<- %ebp 4/r32/esp
     5470     # setup
     5471     (clear-stream _test-input-stream)
     5472     (clear-stream $_test-input-buffered-file->buffer)
     5473     (clear-stream _test-output-stream)
     5474     (clear-stream $_test-output-buffered-file->buffer)
     5475     #
     5476     (write _test-input-stream "fn foo {\n")
     5477     (write _test-input-stream "  {\n")
     5478     (write _test-input-stream "    var x: int\n")
     5479     (write _test-input-stream "    {\n")
     5480     (write _test-input-stream "      var y: int\n")
     5481     (write _test-input-stream "      break\n")
     5482     (write _test-input-stream "      increment x\n")
     5483     (write _test-input-stream "    }\n")
     5484     (write _test-input-stream "  }\n")
     5485     (write _test-input-stream "}\n")
     5486     # convert
     5487     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     5488     (flush _test-output-buffered-file)
     5489 +--  6 lines: #?     # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------
     5495     # check output
     5496     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-unconditional-break-and-local-vars/0")
     5497     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-unconditional-break-and-local-vars/1")
     5498     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-unconditional-break-and-local-vars/2")
     5499     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-unconditional-break-and-local-vars/3")
     5500     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-unconditional-break-and-local-vars/4")
     5501     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-unconditional-break-and-local-vars/5")
     5502     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-unconditional-break-and-local-vars/6")
     5503     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-unconditional-break-and-local-vars/7")
     5504     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-unconditional-break-and-local-vars/8")
     5505     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-unconditional-break-and-local-vars/9")
     5506     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-unconditional-break-and-local-vars/10")
     5507     (check-next-stream-line-equal _test-output-stream "        68/push 0/imm32" "F - test-convert-function-with-unconditional-break-and-local-vars/11")
     5508     (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")
     5509     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-unconditional-break-and-local-vars/13")
     5510     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-unconditional-break-and-local-vars/14")
     5511     (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")
     5512     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-unconditional-break-and-local-vars/16")
     5513     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-unconditional-break-and-local-vars/17")
     5514     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-unconditional-break-and-local-vars/18")
     5515     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-unconditional-break-and-local-vars/19")
     5516     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-unconditional-break-and-local-vars/20")
     5517     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-unconditional-break-and-local-vars/21")
     5518     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-unconditional-break-and-local-vars/22")
     5519     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-unconditional-break-and-local-vars/23")
     5520     # . epilogue
     5521     89/<- %esp 5/r32/ebp
     5522     5d/pop-to-ebp
     5523     c3/return
     5524
     5525 test-convert-function-with-nonlocal-unconditional-loop-and-local-vars:
     5526     # . prologue
     5527     55/push-ebp
     5528     89/<- %ebp 4/r32/esp
     5529     # setup
     5530     (clear-stream _test-input-stream)
     5531     (clear-stream $_test-input-buffered-file->buffer)
     5532     (clear-stream _test-output-stream)
     5533     (clear-stream $_test-output-buffered-file->buffer)
     5534     #
     5535     (write _test-input-stream "fn foo {\n")
     5536     (write _test-input-stream "  a: {\n")
     5537     (write _test-input-stream "    var x: int\n")
     5538     (write _test-input-stream "    {\n")
     5539     (write _test-input-stream "      var y: int\n")
     5540     (write _test-input-stream "      loop a\n")
     5541     (write _test-input-stream "      increment x\n")
     5542     (write _test-input-stream "    }\n")
     5543     (write _test-input-stream "  }\n")
     5544     (write _test-input-stream "}\n")
     5545     # convert
     5546     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     5547     (flush _test-output-buffered-file)
     5548 +--  6 lines: #?     # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------
     5554     # check output
     5555     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/0")
     5556     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/1")
     5557     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/2")
     5558     (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")
     5559     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/4")
     5560     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/5")
     5561     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/6")
     5562     (check-next-stream-line-equal _test-output-stream "a:loop:"                 "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/7")
     5563     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/8")
     5564     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/9")
     5565     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/10")
     5566     (check-next-stream-line-equal _test-output-stream "        68/push 0/imm32" "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/11")
     5567     (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")
     5568     (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")
     5569     (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")
     5570     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/15")
     5571     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/16")
     5572     (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")
     5573     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/18")
     5574     (check-next-stream-line-equal _test-output-stream "a:break:"                "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/19")
     5575     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/20")
     5576     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/21")
     5577     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/22")
     5578     (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")
     5579     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/24")
     5580     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-nonlocal-unconditional-loop-and-local-vars/25")
     5581     # . epilogue
     5582     89/<- %esp 5/r32/ebp
     5583     5d/pop-to-ebp
     5584     c3/return
     5585
     5586 test-convert-function-with-local-array-var-in-mem:
     5587     # . prologue
     5588     55/push-ebp
     5589     89/<- %ebp 4/r32/esp
     5590     # setup
     5591     (clear-stream _test-input-stream)
     5592     (clear-stream $_test-input-buffered-file->buffer)
     5593     (clear-stream _test-output-stream)
     5594     (clear-stream $_test-output-buffered-file->buffer)
     5595     #
     5596     (write _test-input-stream "fn foo {\n")
     5597     (write _test-input-stream "  var x: (array int 3)\n")
     5598     (write _test-input-stream "}\n")
     5599     # convert
     5600     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     5601     (flush _test-output-buffered-file)
     5602 +--  6 lines: #?     # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------
     5608     # check output
     5609     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-array-var-in-mem/0")
     5610     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-array-var-in-mem/1")
     5611     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-array-var-in-mem/2")
     5612     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-local-array-var-in-mem/3")
     5613     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-array-var-in-mem/4")
     5614     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-array-var-in-mem/5")
     5615     # define x
     5616     (check-next-stream-line-equal _test-output-stream "    (push-n-zero-bytes 0x0000000c)"  "F - test-convert-function-with-local-array-var-in-mem/7")
     5617     (check-next-stream-line-equal _test-output-stream "    68/push 0x0000000c/imm32"  "F - test-convert-function-with-local-array-var-in-mem/8")
     5618     # reclaim x
     5619     (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")
     5620     #
     5621     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-array-var-in-mem/10")
     5622     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-array-var-in-mem/11")
     5623     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-array-var-in-mem/12")
     5624     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-local-array-var-in-mem/13")
     5625     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-array-var-in-mem/14")
     5626     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-array-var-in-mem/15")
     5627     # . epilogue
     5628     89/<- %esp 5/r32/ebp
     5629     5d/pop-to-ebp
     5630     c3/return
     5631
     5632 test-array-size-in-hex:
     5633     # . prologue
     5634     55/push-ebp
     5635     89/<- %ebp 4/r32/esp
     5636     # setup
     5637     (clear-stream _test-input-stream)
     5638     (clear-stream $_test-input-buffered-file->buffer)
     5639     (clear-stream _test-output-stream)
     5640     (clear-stream $_test-output-buffered-file->buffer)
     5641     (clear-stream _test-error-stream)
     5642     (clear-stream $_test-error-buffered-file->buffer)
     5643     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     5644     68/push 0/imm32
     5645     68/push 0/imm32
     5646     89/<- %edx 4/r32/esp
     5647     (tailor-exit-descriptor %edx 0x10)
     5648     #
     5649     (write _test-input-stream "fn foo {\n")
     5650     (write _test-input-stream "  var x: (array int 10)\n")
     5651     (write _test-input-stream "}\n")
     5652     # convert
     5653     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     5654     # registers except esp clobbered at this point
     5655     # restore ed
     5656     89/<- %edx 4/r32/esp
     5657     (flush _test-output-buffered-file)
     5658     (flush _test-error-buffered-file)
     5659 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
     5665     # check output
     5666     (check-stream-equal _test-output-stream  ""  "F - test-array-size-in-hex: output should be empty")
     5667     (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")
     5668     # check that stop(1) was called
     5669     (check-ints-equal *(edx+4) 2 "F - test-array-size-in-hex: exit status")
     5670     # don't restore from ebp
     5671     81 0/subop/add %esp 8/imm32
     5672     # . epilogue
     5673     5d/pop-to-ebp
     5674     c3/return
     5675
     5676 test-array-size-with-metadata:
     5677     # . prologue
     5678     55/push-ebp
     5679     89/<- %ebp 4/r32/esp
     5680     # setup
     5681     (clear-stream _test-input-stream)
     5682     (clear-stream $_test-input-buffered-file->buffer)
     5683     (clear-stream _test-output-stream)
     5684     (clear-stream $_test-output-buffered-file->buffer)
     5685     #
     5686     (write _test-input-stream "fn foo {\n")
     5687     (write _test-input-stream "  var x: (array int 3/bar)\n")
     5688     (write _test-input-stream "}\n")
     5689     # convert
     5690     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     5691     (flush _test-output-buffered-file)
     5692 +--  6 lines: #?     # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------
     5698     # no errors
     5699     # . epilogue
     5700     89/<- %esp 5/r32/ebp
     5701     5d/pop-to-ebp
     5702     c3/return
     5703
     5704 test-convert-function-with-populate:
     5705     # . prologue
     5706     55/push-ebp
     5707     89/<- %ebp 4/r32/esp
     5708     # setup
     5709     (clear-stream _test-input-stream)
     5710     (clear-stream $_test-input-buffered-file->buffer)
     5711     (clear-stream _test-output-stream)
     5712     (clear-stream $_test-output-buffered-file->buffer)
     5713     #
     5714     (write _test-input-stream "fn foo {\n")
     5715     (write _test-input-stream "  var x/ecx: (addr handle array int) <- copy 0\n")
     5716     (write _test-input-stream "  populate x, 7\n")
     5717     (write _test-input-stream "}\n")
     5718     # convert
     5719     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     5720     (flush _test-output-buffered-file)
     5721 +--  6 lines: #?     # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------
     5727     # check output
     5728     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-populate/0")
     5729     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-populate/1")
     5730     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-populate/2")
     5731     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-populate/3")
     5732     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-populate/4")
     5733     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-populate/5")
     5734     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-populate/6")
     5735     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"  "F - test-convert-function-with-populate/7")
     5736     (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)
     5737     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-function-with-populate/9")
     5738     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-populate/10")
     5739     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-populate/11")
     5740     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-populate/12")
     5741     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-populate/13")
     5742     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-populate/14")
     5743     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-populate/15")
     5744     # . epilogue
     5745     89/<- %esp 5/r32/ebp
     5746     5d/pop-to-ebp
     5747     c3/return
     5748
     5749 # special-case for size(byte) when allocating array
     5750 test-convert-function-with-local-array-of-bytes-in-mem:
     5751     # . prologue
     5752     55/push-ebp
     5753     89/<- %ebp 4/r32/esp
     5754     # setup
     5755     (clear-stream _test-input-stream)
     5756     (clear-stream $_test-input-buffered-file->buffer)
     5757     (clear-stream _test-output-stream)
     5758     (clear-stream $_test-output-buffered-file->buffer)
     5759     #
     5760     (write _test-input-stream "fn foo {\n")
     5761     (write _test-input-stream "  var x: (array byte 3)\n")
     5762     (write _test-input-stream "}\n")
     5763     # convert
     5764     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     5765     (flush _test-output-buffered-file)
     5766 +--  6 lines: #?     # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------
     5772     # check output
     5773     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-array-of-bytes-in-mem/0")
     5774     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-array-of-bytes-in-mem/1")
     5775     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-array-of-bytes-in-mem/2")
     5776     (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")
     5777     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-array-of-bytes-in-mem/4")
     5778     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-array-of-bytes-in-mem/5")
     5779     # define x
     5780     (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")
     5781     (check-next-stream-line-equal _test-output-stream "    68/push 0x00000003/imm32"  "F - test-convert-function-with-local-array-of-bytes-in-mem/8")
     5782     # reclaim x
     5783     (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")
     5784     #
     5785     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-array-of-bytes-in-mem/10")
     5786     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-array-of-bytes-in-mem/11")
     5787     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-array-of-bytes-in-mem/12")
     5788     (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")
     5789     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-array-of-bytes-in-mem/14")
     5790     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-array-of-bytes-in-mem/15")
     5791     # . epilogue
     5792     89/<- %esp 5/r32/ebp
     5793     5d/pop-to-ebp
     5794     c3/return
     5795
     5796 test-convert-address:
     5797     # . prologue
     5798     55/push-ebp
     5799     89/<- %ebp 4/r32/esp
     5800     # setup
     5801     (clear-stream _test-input-stream)
     5802     (clear-stream $_test-input-buffered-file->buffer)
     5803     (clear-stream _test-output-stream)
     5804     (clear-stream $_test-output-buffered-file->buffer)
     5805     #
     5806     (write _test-input-stream "fn foo {\n")
     5807     (write _test-input-stream "  var a: int\n")
     5808     (write _test-input-stream "  var b/eax: (addr int) <- address a\n")
     5809     (write _test-input-stream "}\n")
     5810     # convert
     5811     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     5812     (flush _test-output-buffered-file)
     5813 +--  6 lines: #?     # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------
     5819     # check output
     5820     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-address/0")
     5821     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-address/1")
     5822     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-address/2")
     5823     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-address/3")
     5824     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-address/4")
     5825     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-address/5")
     5826     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-address/6")
     5827     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-address/7")
     5828     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(ebp+0xfffffffc) 0x00000000/r32"  "F - test-convert-address/8")
     5829     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"  "F - test-convert-address/9")
     5830     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"  "F - test-convert-address/10")
     5831     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-address/11")
     5832     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-address/12")
     5833     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-address/13")
     5834     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-address/14")
     5835     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-address/15")
     5836     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-address/16")
     5837     # . epilogue
     5838     89/<- %esp 5/r32/ebp
     5839     5d/pop-to-ebp
     5840     c3/return
     5841
     5842 test-convert-floating-point-convert:
     5843     # . prologue
     5844     55/push-ebp
     5845     89/<- %ebp 4/r32/esp
     5846     # setup
     5847     (clear-stream _test-input-stream)
     5848     (clear-stream $_test-input-buffered-file->buffer)
     5849     (clear-stream _test-output-stream)
     5850     (clear-stream $_test-output-buffered-file->buffer)
     5851     #
     5852     (write _test-input-stream "fn foo {\n")
     5853     (write _test-input-stream "  var a/eax: int <- copy 0\n")
     5854     (write _test-input-stream "  var b/xmm1: float <- convert a\n")
     5855     (write _test-input-stream "}\n")
     5856     # convert
     5857     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     5858     (flush _test-output-buffered-file)
     5859 +--  6 lines: #?     # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------
     5865     # check output
     5866     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-floating-point-convert/0")
     5867     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-floating-point-convert/1")
     5868     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-floating-point-convert/2")
     5869     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-floating-point-convert/3")
     5870     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-floating-point-convert/4")
     5871     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-floating-point-convert/5")
     5872     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-floating-point-convert/6")
     5873     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"  "F - test-convert-floating-point-convert/7")
     5874     (check-next-stream-line-equal _test-output-stream "    81 5/subop/subtract %esp 4/imm32"  "F - test-convert-floating-point-convert/8")
     5875     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/<- *esp 1/x32"  "F - test-convert-floating-point-convert/9")
     5876     (check-next-stream-line-equal _test-output-stream "    f3 0f 2a/convert-to-float %eax 0x00000001/x32"  "F - test-convert-floating-point-convert/10")
     5877     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/-> *esp 1/x32"  "F - test-convert-floating-point-convert/11")
     5878     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-floating-point-convert/12")
     5879     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax" "F - test-convert-floating-point-convert/13")
     5880     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-floating-point-convert/14")
     5881     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-floating-point-convert/15")
     5882     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-floating-point-convert/16")
     5883     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-floating-point-convert/17")
     5884     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-floating-point-convert/18")
     5885     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-floating-point-convert/19")
     5886     # . epilogue
     5887     89/<- %esp 5/r32/ebp
     5888     5d/pop-to-ebp
     5889     c3/return
     5890
     5891 test-convert-floating-point-convert-2:
     5892     # . prologue
     5893     55/push-ebp
     5894     89/<- %ebp 4/r32/esp
     5895     # setup
     5896     (clear-stream _test-input-stream)
     5897     (clear-stream $_test-input-buffered-file->buffer)
     5898     (clear-stream _test-output-stream)
     5899     (clear-stream $_test-output-buffered-file->buffer)
     5900     #
     5901     (write _test-input-stream "fn foo {\n")
     5902     (write _test-input-stream "  var a/eax: int <- copy 0\n")
     5903     (write _test-input-stream "  var b/xmm1: float <- convert a\n")
     5904     (write _test-input-stream "  a <- convert b\n")
     5905     (write _test-input-stream "}\n")
     5906     # convert
     5907     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     5908     (flush _test-output-buffered-file)
     5909 +--  6 lines: #?     # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------
     5915     # check output
     5916     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-floating-point-convert-2/0")
     5917     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-floating-point-convert-2/1")
     5918     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-floating-point-convert-2/2")
     5919     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-floating-point-convert-2/3")
     5920     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-floating-point-convert-2/4")
     5921     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-floating-point-convert-2/5")
     5922     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-floating-point-convert-2/6")
     5923     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"  "F - test-convert-floating-point-convert-2/7")
     5924     (check-next-stream-line-equal _test-output-stream "    81 5/subop/subtract %esp 4/imm32"  "F - test-convert-floating-point-convert-2/8")
     5925     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/<- *esp 1/x32"  "F - test-convert-floating-point-convert-2/9")
     5926     (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")
     5927     (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")
     5928     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/-> *esp 1/x32"  "F - test-convert-floating-point-convert-2/12")
     5929     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-floating-point-convert-2/13")
     5930     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax" "F - test-convert-floating-point-convert-2/14")
     5931     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-floating-point-convert-2/15")
     5932     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-floating-point-convert-2/16")
     5933     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-floating-point-convert-2/17")
     5934     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-floating-point-convert-2/18")
     5935     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-floating-point-convert-2/19")
     5936     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-floating-point-convert-2/20")
     5937     # . epilogue
     5938     89/<- %esp 5/r32/ebp
     5939     5d/pop-to-ebp
     5940     c3/return
     5941
     5942 test-convert-floating-point-operation:
     5943     # . prologue
     5944     55/push-ebp
     5945     89/<- %ebp 4/r32/esp
     5946     # setup
     5947     (clear-stream _test-input-stream)
     5948     (clear-stream $_test-input-buffered-file->buffer)
     5949     (clear-stream _test-output-stream)
     5950     (clear-stream $_test-output-buffered-file->buffer)
     5951     #
     5952     (write _test-input-stream "fn f {\n")
     5953     (write _test-input-stream "  var m: float\n")
     5954     (write _test-input-stream "  var x/xmm1: float <- copy m\n")
     5955     (write _test-input-stream "  var y/xmm5: float <- copy m\n")
     5956     (write _test-input-stream "  x <- copy y\n")
     5957     (write _test-input-stream "  copy-to m, y\n")
     5958     (write _test-input-stream "  x <- add y\n")
     5959     (write _test-input-stream "  x <- add m\n")
     5960     (write _test-input-stream "  x <- subtract y\n")
     5961     (write _test-input-stream "  x <- subtract m\n")
     5962     (write _test-input-stream "  x <- multiply y\n")
     5963     (write _test-input-stream "  x <- multiply m\n")
     5964     (write _test-input-stream "  x <- divide y\n")
     5965     (write _test-input-stream "  x <- divide m\n")
     5966     (write _test-input-stream "  x <- reciprocal y\n")
     5967     (write _test-input-stream "  x <- reciprocal m\n")
     5968     (write _test-input-stream "  x <- square-root y\n")
     5969     (write _test-input-stream "  x <- square-root m\n")
     5970     (write _test-input-stream "  x <- inverse-square-root y\n")
     5971     (write _test-input-stream "  x <- inverse-square-root m\n")
     5972     (write _test-input-stream "  x <- max y\n")
     5973     (write _test-input-stream "  x <- max m\n")
     5974     (write _test-input-stream "  x <- min y\n")
     5975     (write _test-input-stream "  x <- min m\n")
     5976     (write _test-input-stream "  compare x, y\n")
     5977     (write _test-input-stream "  compare x, m\n")
     5978     (write _test-input-stream "}\n")
     5979     # convert
     5980     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     5981     (flush _test-output-buffered-file)
     5982 +--  6 lines: #?     # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------
     5988     # check output
     5989     (check-next-stream-line-equal _test-output-stream "f:"                                                                     "F - test-convert-floating-point-operation/0")
     5990     (check-next-stream-line-equal _test-output-stream "  # . prologue"                                                         "F - test-convert-floating-point-operation/1")
     5991     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                                                          "F - test-convert-floating-point-operation/2")
     5992     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                                                 "F - test-convert-floating-point-operation/3")
     5993     (check-next-stream-line-equal _test-output-stream "  {"                                                                    "F - test-convert-floating-point-operation/4")
     5994     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:loop:"                                                    "F - test-convert-floating-point-operation/5")
     5995     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"                                                    "F - test-convert-floating-point-operation/6")
     5996     (check-next-stream-line-equal _test-output-stream "    81 5/subop/subtract %esp 4/imm32"                                   "F - test-convert-floating-point-operation/7")
     5997     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/<- *esp 1/x32"                                             "F - test-convert-floating-point-operation/8")
     5998     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/copy *(ebp+0xfffffffc) 0x00000001/x32"                     "F - test-convert-floating-point-operation/9")
     5999     (check-next-stream-line-equal _test-output-stream "    81 5/subop/subtract %esp 4/imm32"                                   "F - test-convert-floating-point-operation/10")
     6000     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/<- *esp 5/x32"                                             "F - test-convert-floating-point-operation/11")
     6001     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/copy *(ebp+0xfffffffc) 0x00000005/x32"                     "F - test-convert-floating-point-operation/12")
     6002     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/copy %xmm1 0x00000005/x32"                                 "F - test-convert-floating-point-operation/13")
     6003     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/copy *(ebp+0xfffffffc) 0x00000005/x32"                     "F - test-convert-floating-point-operation/14")
     6004     (check-next-stream-line-equal _test-output-stream "    f3 0f 58/add %xmm5 0x00000001/x32"                                  "F - test-convert-floating-point-operation/15")
     6005     (check-next-stream-line-equal _test-output-stream "    f3 0f 58/add *(ebp+0xfffffffc) 0x00000001/x32"                      "F - test-convert-floating-point-operation/16")
     6006     (check-next-stream-line-equal _test-output-stream "    f3 0f 5c/subtract %xmm5 0x00000001/x32"                             "F - test-convert-floating-point-operation/17")
     6007     (check-next-stream-line-equal _test-output-stream "    f3 0f 5c/subtract *(ebp+0xfffffffc) 0x00000001/x32"                 "F - test-convert-floating-point-operation/18")
     6008     (check-next-stream-line-equal _test-output-stream "    f3 0f 59/multiply %xmm5 0x00000001/x32"                             "F - test-convert-floating-point-operation/19")
     6009     (check-next-stream-line-equal _test-output-stream "    f3 0f 59/multiply *(ebp+0xfffffffc) 0x00000001/x32"                 "F - test-convert-floating-point-operation/20")
     6010     (check-next-stream-line-equal _test-output-stream "    f3 0f 5e/divide %xmm5 0x00000001/x32"                               "F - test-convert-floating-point-operation/21")
     6011     (check-next-stream-line-equal _test-output-stream "    f3 0f 5e/divide *(ebp+0xfffffffc) 0x00000001/x32"                   "F - test-convert-floating-point-operation/22")
     6012     (check-next-stream-line-equal _test-output-stream "    f3 0f 53/reciprocal %xmm5 0x00000001/x32"                           "F - test-convert-floating-point-operation/23")
     6013     (check-next-stream-line-equal _test-output-stream "    f3 0f 53/reciprocal *(ebp+0xfffffffc) 0x00000001/x32"               "F - test-convert-floating-point-operation/24")
     6014     (check-next-stream-line-equal _test-output-stream "    f3 0f 51/square-root %xmm5 0x00000001/x32"                          "F - test-convert-floating-point-operation/25")
     6015     (check-next-stream-line-equal _test-output-stream "    f3 0f 51/square-root *(ebp+0xfffffffc) 0x00000001/x32"              "F - test-convert-floating-point-operation/26")
     6016     (check-next-stream-line-equal _test-output-stream "    f3 0f 52/inverse-square-root %xmm5 0x00000001/x32"                  "F - test-convert-floating-point-operation/27")
     6017     (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")
     6018     (check-next-stream-line-equal _test-output-stream "    f3 0f 5f/max %xmm5 0x00000001/x32"                                  "F - test-convert-floating-point-operation/29")
     6019     (check-next-stream-line-equal _test-output-stream "    f3 0f 5f/max *(ebp+0xfffffffc) 0x00000001/x32"                      "F - test-convert-floating-point-operation/30")
     6020     (check-next-stream-line-equal _test-output-stream "    f3 0f 5d/min %xmm5 0x00000001/x32"                                  "F - test-convert-floating-point-operation/31")
     6021     (check-next-stream-line-equal _test-output-stream "    f3 0f 5d/min *(ebp+0xfffffffc) 0x00000001/x32"                      "F - test-convert-floating-point-operation/32")
     6022     (check-next-stream-line-equal _test-output-stream "    0f 2f/compare %xmm5 0x00000001/x32"                                 "F - test-convert-floating-point-operation/33")
     6023     (check-next-stream-line-equal _test-output-stream "    0f 2f/compare *(ebp+0xfffffffc) 0x00000001/x32"                     "F - test-convert-floating-point-operation/34")
     6024     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/-> *esp 5/x32"                                             "F - test-convert-floating-point-operation/35")
     6025     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"                                        "F - test-convert-floating-point-operation/36")
     6026     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/-> *esp 1/x32"                                             "F - test-convert-floating-point-operation/37")
     6027     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"                                        "F - test-convert-floating-point-operation/38")
     6028     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"                               "F - test-convert-floating-point-operation/39")
     6029     (check-next-stream-line-equal _test-output-stream "  }"                                                                    "F - test-convert-floating-point-operation/40")
     6030     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:break:"                                                   "F - test-convert-floating-point-operation/41")
     6031     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                                                         "F - test-convert-floating-point-operation/42")
     6032     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                                                 "F - test-convert-floating-point-operation/43")
     6033     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                                                        "F - test-convert-floating-point-operation/44")
     6034     (check-next-stream-line-equal _test-output-stream "  c3/return"                                                            "F - test-convert-floating-point-operation/45")
     6035     # . epilogue
     6036     89/<- %esp 5/r32/ebp
     6037     5d/pop-to-ebp
     6038     c3/return
     6039
     6040 test-convert-floating-point-dereferenced:
     6041     # . prologue
     6042     55/push-ebp
     6043     89/<- %ebp 4/r32/esp
     6044     # setup
     6045     (clear-stream _test-input-stream)
     6046     (clear-stream $_test-input-buffered-file->buffer)
     6047     (clear-stream _test-output-stream)
     6048     (clear-stream $_test-output-buffered-file->buffer)
     6049     #
     6050     (write _test-input-stream "fn f {\n")
     6051     (write _test-input-stream "  var m: float\n")
     6052     (write _test-input-stream "  var x/xmm1: float <- copy m\n")
     6053     (write _test-input-stream "  var y/eax: (addr float) <- copy 0\n")
     6054     (write _test-input-stream "  x <- multiply *y\n")
     6055     (write _test-input-stream "}\n")
     6056     # convert
     6057     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     6058     (flush _test-output-buffered-file)
     6059 +--  6 lines: #?     # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------
     6065     # check output
     6066     (check-next-stream-line-equal _test-output-stream "f:"                                                                     "F - test-convert-floating-point-dereferenced/0")
     6067     (check-next-stream-line-equal _test-output-stream "  # . prologue"                                                         "F - test-convert-floating-point-dereferenced/1")
     6068     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                                                          "F - test-convert-floating-point-dereferenced/2")
     6069     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                                                 "F - test-convert-floating-point-dereferenced/3")
     6070     (check-next-stream-line-equal _test-output-stream "  {"                                                                    "F - test-convert-floating-point-dereferenced/4")
     6071     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:loop:"                                                    "F - test-convert-floating-point-dereferenced/5")
     6072     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"                                                    "F - test-convert-floating-point-dereferenced/6")
     6073     (check-next-stream-line-equal _test-output-stream "    81 5/subop/subtract %esp 4/imm32"                                   "F - test-convert-floating-point-dereferenced/7")
     6074     (check-next-stream-line-equal _test-output-stream "    f3 0f 11/<- *esp 1/x32"                                             "F - test-convert-floating-point-dereferenced/8")
     6075     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/copy *(ebp+0xfffffffc) 0x00000001/x32"                     "F - test-convert-floating-point-dereferenced/9")
     6076     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                                               "F - test-convert-floating-point-dereferenced/10")
     6077     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                                             "F - test-convert-floating-point-dereferenced/11")
     6078     (check-next-stream-line-equal _test-output-stream "    f3 0f 59/multiply *eax 0x00000001/x32"                              "F - test-convert-floating-point-dereferenced/12")
     6079     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                                                "F - test-convert-floating-point-dereferenced/13")
     6080     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/-> *esp 1/x32"                                             "F - test-convert-floating-point-dereferenced/14")
     6081     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"                                        "F - test-convert-floating-point-dereferenced/15")
     6082     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000004/imm32"                               "F - test-convert-floating-point-dereferenced/16")
     6083     (check-next-stream-line-equal _test-output-stream "  }"                                                                    "F - test-convert-floating-point-dereferenced/17")
     6084     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:break:"                                                   "F - test-convert-floating-point-dereferenced/18")
     6085     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                                                         "F - test-convert-floating-point-dereferenced/19")
     6086     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                                                 "F - test-convert-floating-point-dereferenced/20")
     6087     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                                                        "F - test-convert-floating-point-dereferenced/21")
     6088     (check-next-stream-line-equal _test-output-stream "  c3/return"                                                            "F - test-convert-floating-point-dereferenced/22")
     6089     # . epilogue
     6090     89/<- %esp 5/r32/ebp
     6091     5d/pop-to-ebp
     6092     c3/return
     6093
     6094 test-convert-length-of-array:
     6095     # . prologue
     6096     55/push-ebp
     6097     89/<- %ebp 4/r32/esp
     6098     # setup
     6099     (clear-stream _test-input-stream)
     6100     (clear-stream $_test-input-buffered-file->buffer)
     6101     (clear-stream _test-output-stream)
     6102     (clear-stream $_test-output-buffered-file->buffer)
     6103     #
     6104     (write _test-input-stream "fn foo a: (addr array int) {\n")
     6105     (write _test-input-stream "  var b/eax: (addr array int) <- copy a\n")
     6106     (write _test-input-stream "  var c/eax: int <- length b\n")
     6107     (write _test-input-stream "}\n")
     6108     # convert
     6109     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     6110     (flush _test-output-buffered-file)
     6111 +--  6 lines: #?     # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------
     6117     # check output
     6118     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array/0")
     6119     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array/1")
     6120     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array/2")
     6121     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-length-of-array/3")
     6122     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array/4")
     6123     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array/5")
     6124     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-length-of-array/6")
     6125     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000000/r32"  "F - test-convert-length-of-array/7")
     6126     (check-next-stream-line-equal _test-output-stream "    8b/-> *eax 0x00000000/r32"  "F - test-convert-length-of-array/8")
     6127     (check-next-stream-line-equal _test-output-stream "    c1/shift 5/subop/>> %eax 0x00000002/imm8"  "F - test-convert-length-of-array/9")
     6128     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"  "F - test-convert-length-of-array/10")
     6129     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array/11")
     6130     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array/12")
     6131     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array/13")
     6132     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-length-of-array/14")
     6133     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-length-of-array/15")
     6134     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array/16")
     6135     # . epilogue
     6136     89/<- %esp 5/r32/ebp
     6137     5d/pop-to-ebp
     6138     c3/return
     6139
     6140 # special-case for size(byte) when computing array length
     6141 test-convert-length-of-array-of-bytes:
     6142     # . prologue
     6143     55/push-ebp
     6144     89/<- %ebp 4/r32/esp
     6145     # setup
     6146     (clear-stream _test-input-stream)
     6147     (clear-stream $_test-input-buffered-file->buffer)
     6148     (clear-stream _test-output-stream)
     6149     (clear-stream $_test-output-buffered-file->buffer)
     6150     #
     6151     (write _test-input-stream "fn foo a: (addr array byte) {\n")
     6152     (write _test-input-stream "  var b/eax: (addr array byte) <- copy a\n")
     6153     (write _test-input-stream "  var c/eax: int <- length b\n")
     6154     (write _test-input-stream "}\n")
     6155     # convert
     6156     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     6157     (flush _test-output-buffered-file)
     6158 +--  6 lines: #?     # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------
     6164     # check output
     6165     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array-of-bytes/0")
     6166     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array-of-bytes/1")
     6167     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array-of-bytes/2")
     6168     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-length-of-array-of-bytes/3")
     6169     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array-of-bytes/4")
     6170     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array-of-bytes/5")
     6171     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-length-of-array-of-bytes/6")
     6172     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000000/r32"  "F - test-convert-length-of-array-of-bytes/7")
     6173     (check-next-stream-line-equal _test-output-stream "    8b/-> *eax 0x00000000/r32"  "F - test-convert-length-of-array-of-bytes/8")
     6174     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"  "F - test-convert-length-of-array-of-bytes/9")
     6175     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array-of-bytes/10")
     6176     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array-of-bytes/11")
     6177     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array-of-bytes/12")
     6178     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-length-of-array-of-bytes/13")
     6179     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-length-of-array-of-bytes/14")
     6180     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array-of-bytes/15")
     6181     # . epilogue
     6182     89/<- %esp 5/r32/ebp
     6183     5d/pop-to-ebp
     6184     c3/return
     6185
     6186 test-convert-length-of-array-on-stack:
     6187     # . prologue
     6188     55/push-ebp
     6189     89/<- %ebp 4/r32/esp
     6190     # setup
     6191     (clear-stream _test-input-stream)
     6192     (clear-stream $_test-input-buffered-file->buffer)
     6193     (clear-stream _test-output-stream)
     6194     (clear-stream $_test-output-buffered-file->buffer)
     6195     #
     6196     (write _test-input-stream "fn foo {\n")
     6197     (write _test-input-stream "  var a: (array int 3)\n")
     6198     (write _test-input-stream "  var b/eax: int <- length a\n")
     6199     (write _test-input-stream "}\n")
     6200     # convert
     6201     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     6202     (flush _test-output-buffered-file)
     6203 +--  6 lines: #?     # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------
     6209     # check output
     6210     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array-on-stack/0")
     6211     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array-on-stack/1")
     6212     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array-on-stack/2")
     6213     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-length-of-array-on-stack/3")
     6214     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array-on-stack/4")
     6215     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array-on-stack/5")
     6216     # define x
     6217     (check-next-stream-line-equal _test-output-stream "    (push-n-zero-bytes 0x0000000c)"  "F - test-convert-length-of-array-on-stack/6")
     6218     (check-next-stream-line-equal _test-output-stream "    68/push 0x0000000c/imm32"  "F - test-convert-length-of-array-on-stack/7")
     6219     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-length-of-array-on-stack/8")
     6220     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0xfffffff0) 0x00000000/r32"  "F - test-convert-length-of-array-on-stack/9")
     6221     (check-next-stream-line-equal _test-output-stream "    c1/shift 5/subop/>> %eax 0x00000002/imm8"  "F - test-convert-length-of-array-on-stack/10")
     6222     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"  "F - test-convert-length-of-array-on-stack/11")
     6223     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000010/imm32"  "F - test-convert-length-of-array-on-stack/12")
     6224     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array-on-stack/13")
     6225     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array-on-stack/14")
     6226     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array-on-stack/15")
     6227     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-length-of-array-on-stack/16")
     6228     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-length-of-array-on-stack/17")
     6229     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array-on-stack/18")
     6230     # . epilogue
     6231     89/<- %esp 5/r32/ebp
     6232     5d/pop-to-ebp
     6233     c3/return
     6234
     6235 test-reg-var-def-with-read-of-same-register:
     6236     # . prologue
     6237     55/push-ebp
     6238     89/<- %ebp 4/r32/esp
     6239     # setup
     6240     (clear-stream _test-input-stream)
     6241     (clear-stream $_test-input-buffered-file->buffer)
     6242     (clear-stream _test-output-stream)
     6243     (clear-stream $_test-output-buffered-file->buffer)
     6244     (clear-stream _test-error-stream)
     6245     (clear-stream $_test-error-buffered-file->buffer)
     6246     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)  # bytes of args in call to convert-mu
     6247     68/push 0/imm32
     6248     68/push 0/imm32
     6249     89/<- %edx 4/r32/esp
     6250     (tailor-exit-descriptor %edx 0x10)
     6251     #
     6252     (write _test-input-stream "fn foo {\n")
     6253     (write _test-input-stream "  var x/eax: int <- copy 3\n")
     6254     (write _test-input-stream "  var y/eax: int <- add x\n")
     6255     (write _test-input-stream "}\n")
     6256     # convert
     6257     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     6258     # registers except esp could be clobbered at this point (though they shouldn't be)
     6259     # restore ed
     6260     89/<- %edx 4/r32/esp
     6261     (flush _test-output-buffered-file)
     6262     (flush _test-error-buffered-file)
     6263 +--  6 lines: #?     # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------
     6269 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
     6275     (check-stream-equal _test-error-stream  ""  "F - test-reg-var-def-with-read-of-same-register: error stream should be empty")
     6276     # check output
     6277     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-reg-var-def-with-read-of-same-register/0")
     6278     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-reg-var-def-with-read-of-same-register/1")
     6279     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-reg-var-def-with-read-of-same-register/2")
     6280     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-reg-var-def-with-read-of-same-register/3")
     6281     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-reg-var-def-with-read-of-same-register/4")
     6282     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-reg-var-def-with-read-of-same-register/5")
     6283     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-reg-var-def-with-read-of-same-register/6")
     6284     (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")
     6285     (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")
     6286     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-reg-var-def-with-read-of-same-register/9")
     6287     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-reg-var-def-with-read-of-same-register/10")
     6288     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-reg-var-def-with-read-of-same-register/11")
     6289     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-reg-var-def-with-read-of-same-register/12")
     6290     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-reg-var-def-with-read-of-same-register/13")
     6291     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-reg-var-def-with-read-of-same-register/14")
     6292     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-reg-var-def-with-read-of-same-register/15")
     6293     # don't restore from ebp
     6294     81 0/subop/add %esp 8/imm32
     6295     # . epilogue
     6296     5d/pop-to-ebp
     6297     c3/return
     6298
     6299 test-convert-index-into-array:
     6300     # . prologue
     6301     55/push-ebp
     6302     89/<- %ebp 4/r32/esp
     6303     # setup
     6304     (clear-stream _test-input-stream)
     6305     (clear-stream $_test-input-buffered-file->buffer)
     6306     (clear-stream _test-output-stream)
     6307     (clear-stream $_test-output-buffered-file->buffer)
     6308     #
     6309     (write _test-input-stream "fn foo {\n")
     6310     (write _test-input-stream "  var arr/eax: (addr array int) <- copy 0\n")
     6311     (write _test-input-stream "  var idx/ecx: int <- copy 3\n")
     6312     (write _test-input-stream "  var x/eax: (addr int) <- index arr, idx\n")
     6313     (write _test-input-stream "}\n")
     6314     # convert
     6315     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     6316     (flush _test-output-buffered-file)
     6317 +--  6 lines: #?     # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------
     6323     # check output
     6324     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array/0")
     6325     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array/1")
     6326     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array/2")
     6327     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array/3")
     6328     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array/4")
     6329     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array/5")
     6330     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array/6")
     6331     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-index-into-array/7")
     6332     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-index-into-array/8")
     6333     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"                  "F - test-convert-index-into-array/9")
     6334     (check-next-stream-line-equal _test-output-stream "    (__check-mu-array-bounds %ecx 0x00000004 *eax \"foo\" \"arr\")"  "F - test-convert-index-into-array/10")
     6335     (check-next-stream-line-equal _test-output-stream "    81 7/subop/compare %eax 0/imm32"  "F - test-convert-index-into-array/11")
     6336     (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")
     6337     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + ecx<<0x00000002 + 4) 0x00000000/r32"  "F - test-convert-index-into-array/13")
     6338     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-index-into-array/14")
     6339     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array/15")
     6340     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array/16")
     6341     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array/17")
     6342     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array/18")
     6343     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array/19")
     6344     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array/20")
     6345     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array/21")
     6346     # . epilogue
     6347     89/<- %esp 5/r32/ebp
     6348     5d/pop-to-ebp
     6349     c3/return
     6350
     6351 test-convert-index-into-array-of-bytes:
     6352     # . prologue
     6353     55/push-ebp
     6354     89/<- %ebp 4/r32/esp
     6355     # setup
     6356     (clear-stream _test-input-stream)
     6357     (clear-stream $_test-input-buffered-file->buffer)
     6358     (clear-stream _test-output-stream)
     6359     (clear-stream $_test-output-buffered-file->buffer)
     6360     #
     6361     (write _test-input-stream "fn foo {\n")
     6362     (write _test-input-stream "  var arr/eax: (addr array byte) <- copy 0\n")
     6363     (write _test-input-stream "  var idx/ecx: int <- copy 3\n")
     6364     (write _test-input-stream "  var x/eax: (addr byte) <- index arr, idx\n")
     6365     (write _test-input-stream "}\n")
     6366     # convert
     6367     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     6368     (flush _test-output-buffered-file)
     6369 +--  6 lines: #?     # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------
     6375     # check output
     6376     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-of-bytes/0")
     6377     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-of-bytes/1")
     6378     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-of-bytes/2")
     6379     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-of-bytes/3")
     6380     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-of-bytes/4")
     6381     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-of-bytes/5")
     6382     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-of-bytes/6")
     6383     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-index-into-array-of-bytes/7")
     6384     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-index-into-array-of-bytes/8")
     6385     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"                  "F - test-convert-index-into-array-of-bytes/9")
     6386     (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")
     6387     (check-next-stream-line-equal _test-output-stream "    81 7/subop/compare %eax 0/imm32"  "F - test-convert-index-into-array-of-bytes/11")
     6388     (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")
     6389     (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")
     6390     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-index-into-array-of-bytes/14")
     6391     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-of-bytes/15")
     6392     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-of-bytes/16")
     6393     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-of-bytes/17")
     6394     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-of-bytes/18")
     6395     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-of-bytes/19")
     6396     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-of-bytes/20")
     6397     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-of-bytes/21")
     6398     # . epilogue
     6399     89/<- %esp 5/r32/ebp
     6400     5d/pop-to-ebp
     6401     c3/return
     6402
     6403 test-convert-index-into-array-with-literal:
     6404     # . prologue
     6405     55/push-ebp
     6406     89/<- %ebp 4/r32/esp
     6407     # setup
     6408     (clear-stream _test-input-stream)
     6409     (clear-stream $_test-input-buffered-file->buffer)
     6410     (clear-stream _test-output-stream)
     6411     (clear-stream $_test-output-buffered-file->buffer)
     6412     #
     6413     (write _test-input-stream "fn foo {\n")
     6414     (write _test-input-stream "  var arr/eax: (addr array int) <- copy 0\n")
     6415     (write _test-input-stream "  var x/eax: (addr int) <- index arr, 2\n")
     6416     (write _test-input-stream "}\n")
     6417     # convert
     6418     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     6419     (flush _test-output-buffered-file)
     6420 +--  6 lines: #?     # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------
     6426     # check output
     6427     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-with-literal/0")
     6428     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-with-literal/1")
     6429     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-with-literal/2")
     6430     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-with-literal/3")
     6431     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-with-literal/4")
     6432     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-with-literal/5")
     6433     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-with-literal/6")
     6434     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-index-into-array-with-literal/7")
     6435     (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")
     6436     (check-next-stream-line-equal _test-output-stream "    81 7/subop/compare %eax 0/imm32"  "F - test-convert-index-into-array-with-literal/9")
     6437     (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")
     6438                                                                                  # 2 * 4 bytes/elem + 4 bytes for size = offset 12
     6439     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + 0x0000000c) 0x00000000/r32"  "F - test-convert-index-into-array-with-literal/11")
     6440     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-with-literal/12")
     6441     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-with-literal/13")
     6442     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-with-literal/14")
     6443     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-with-literal/15")
     6444     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-with-literal/16")
     6445     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-with-literal/17")
     6446     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-with-literal/18")
     6447     # . epilogue
     6448     89/<- %esp 5/r32/ebp
     6449     5d/pop-to-ebp
     6450     c3/return
     6451
     6452 test-convert-index-into-array-of-bytes-with-literal:
     6453     # . prologue
     6454     55/push-ebp
     6455     89/<- %ebp 4/r32/esp
     6456     # setup
     6457     (clear-stream _test-input-stream)
     6458     (clear-stream $_test-input-buffered-file->buffer)
     6459     (clear-stream _test-output-stream)
     6460     (clear-stream $_test-output-buffered-file->buffer)
     6461     #
     6462     (write _test-input-stream "fn foo {\n")
     6463     (write _test-input-stream "  var arr/eax: (addr array byte) <- copy 0\n")
     6464     (write _test-input-stream "  var x/eax: (addr byte) <- index arr, 2\n")
     6465     (write _test-input-stream "}\n")
     6466     # convert
     6467     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     6468     (flush _test-output-buffered-file)
     6469 +--  6 lines: #?     # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------
     6475     # check output
     6476     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-of-bytes-with-literal/0")
     6477     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-of-bytes-with-literal/1")
     6478     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-of-bytes-with-literal/2")
     6479     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-of-bytes-with-literal/3")
     6480     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-of-bytes-with-literal/4")
     6481     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-of-bytes-with-literal/5")
     6482     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-of-bytes-with-literal/6")
     6483     (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")
     6484     (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")
     6485     (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")
     6486     (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")
     6487                                                                                  # 2 * 1 byte/elem + 4 bytes for size = offset 6
     6488     (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")
     6489     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-of-bytes-with-literal/12")
     6490     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-of-bytes-with-literal/13")
     6491     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-of-bytes-with-literal/14")
     6492     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-of-bytes-with-literal/15")
     6493     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-of-bytes-with-literal/16")
     6494     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-of-bytes-with-literal/17")
     6495     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-of-bytes-with-literal/18")
     6496     # . epilogue
     6497     89/<- %esp 5/r32/ebp
     6498     5d/pop-to-ebp
     6499     c3/return
     6500
     6501 test-convert-index-into-array-on-stack:
     6502     # . prologue
     6503     55/push-ebp
     6504     89/<- %ebp 4/r32/esp
     6505     # setup
     6506     (clear-stream _test-input-stream)
     6507     (clear-stream $_test-input-buffered-file->buffer)
     6508     (clear-stream _test-output-stream)
     6509     (clear-stream $_test-output-buffered-file->buffer)
     6510     #
     6511     (write _test-input-stream "fn foo {\n")
     6512     (write _test-input-stream "  var arr: (array int 3)\n")
     6513     (write _test-input-stream "  var idx/eax: int <- copy 2\n")
     6514     (write _test-input-stream "  var x/eax: (addr int) <- index arr, idx\n")
     6515     (write _test-input-stream "}\n")
     6516     # convert
     6517     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     6518     (flush _test-output-buffered-file)
     6519 +--  6 lines: #?     # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------
     6525     # check output
     6526     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-on-stack/0")
     6527     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-on-stack/1")
     6528     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-on-stack/2")
     6529     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-on-stack/3")
     6530     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-on-stack/4")
     6531     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-on-stack/5")
     6532     # var arr
     6533     (check-next-stream-line-equal _test-output-stream "    (push-n-zero-bytes 0x0000000c)"          "F - test-convert-index-into-array-on-stack/6")
     6534     (check-next-stream-line-equal _test-output-stream "    68/push 0x0000000c/imm32"                "F - test-convert-index-into-array-on-stack/7")
     6535     # var idx
     6536     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-on-stack/8")
     6537     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 2/imm32"                  "F - test-convert-index-into-array-on-stack/9")
     6538     (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")
     6539     # var x is at (ebp-0x10) + idx<<2 + 4 = ebp + idx<<2 - 0xc
     6540     (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")
     6541     # reclaim idx
     6542     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-on-stack/12")
     6543     # reclaim arr
     6544     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000010/imm32"    "F - test-convert-index-into-array-on-stack/13")
     6545     #
     6546     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-on-stack/14")
     6547     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-on-stack/15")
     6548     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-on-stack/16")
     6549     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-on-stack/17")
     6550     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-on-stack/18")
     6551     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-on-stack/19")
     6552     # . epilogue
     6553     89/<- %esp 5/r32/ebp
     6554     5d/pop-to-ebp
     6555     c3/return
     6556
     6557 test-convert-index-into-array-on-stack-with-literal:
     6558     # . prologue
     6559     55/push-ebp
     6560     89/<- %ebp 4/r32/esp
     6561     # setup
     6562     (clear-stream _test-input-stream)
     6563     (clear-stream $_test-input-buffered-file->buffer)
     6564     (clear-stream _test-output-stream)
     6565     (clear-stream $_test-output-buffered-file->buffer)
     6566     #
     6567     (write _test-input-stream "fn foo {\n")
     6568     (write _test-input-stream "  var arr: (array int 3)\n")
     6569     (write _test-input-stream "  var x/eax: (addr int) <- index arr, 2\n")
     6570     (write _test-input-stream "}\n")
     6571     # convert
     6572     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     6573     (flush _test-output-buffered-file)
     6574 +--  6 lines: #?     # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------
     6580     # check output
     6581     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-on-stack-with-literal/0")
     6582     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-on-stack-with-literal/1")
     6583     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-on-stack-with-literal/2")
     6584     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-on-stack-with-literal/3")
     6585     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-on-stack-with-literal/4")
     6586     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-on-stack-with-literal/5")
     6587     # var arr
     6588     (check-next-stream-line-equal _test-output-stream "    (push-n-zero-bytes 0x0000000c)"          "F - test-convert-index-into-array-on-stack-with-literal/6")
     6589     (check-next-stream-line-equal _test-output-stream "    68/push 0x0000000c/imm32"                "F - test-convert-index-into-array-on-stack-with-literal/7")
     6590     # var x
     6591     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-on-stack-with-literal/8")
     6592     (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")
     6593     # x is at (ebp-0x10) + 4 + 2*4 = ebp-4
     6594     (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")
     6595     # reclaim x
     6596     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-on-stack-with-literal/11")
     6597     # reclaim arr
     6598     (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")
     6599     #
     6600     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-on-stack-with-literal/13")
     6601     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-on-stack-with-literal/14")
     6602     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-on-stack-with-literal/15")
     6603     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-on-stack-with-literal/16")
     6604     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-on-stack-with-literal/17")
     6605     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-on-stack-with-literal/18")
     6606     # . epilogue
     6607     89/<- %esp 5/r32/ebp
     6608     5d/pop-to-ebp
     6609     c3/return
     6610
     6611 test-convert-index-into-array-of-bytes-on-stack-with-literal:
     6612     # . prologue
     6613     55/push-ebp
     6614     89/<- %ebp 4/r32/esp
     6615     # setup
     6616     (clear-stream _test-input-stream)
     6617     (clear-stream $_test-input-buffered-file->buffer)
     6618     (clear-stream _test-output-stream)
     6619     (clear-stream $_test-output-buffered-file->buffer)
     6620     #
     6621     (write _test-input-stream "fn foo {\n")
     6622     (write _test-input-stream "  var arr: (array byte 3)\n")
     6623     (write _test-input-stream "  var x/eax: (addr byte) <- index arr, 2\n")
     6624     (write _test-input-stream "}\n")
     6625     # convert
     6626     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     6627     (flush _test-output-buffered-file)
     6628 +--  6 lines: #?     # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------
     6634     # check output
     6635     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/0")
     6636     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/1")
     6637     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/2")
     6638     (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")
     6639     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/4")
     6640     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/5")
     6641     # var arr
     6642     (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")
     6643     (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")
     6644     # var x
     6645     (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")
     6646     (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")
     6647     # x is at (ebp-7) + 4 + 2 = ebp-1
     6648     (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")
     6649     # reclaim x
     6650     (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")
     6651     # reclaim arr
     6652     (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")
     6653     #
     6654     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/13")
     6655     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/14")
     6656     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/15")
     6657     (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")
     6658     (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")
     6659     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-of-bytes-on-stack-with-literal/18")
     6660     # . epilogue
     6661     89/<- %esp 5/r32/ebp
     6662     5d/pop-to-ebp
     6663     c3/return
     6664
     6665 test-convert-index-into-array-using-offset:
     6666     # . prologue
     6667     55/push-ebp
     6668     89/<- %ebp 4/r32/esp
     6669     # setup
     6670     (clear-stream _test-input-stream)
     6671     (clear-stream $_test-input-buffered-file->buffer)
     6672     (clear-stream _test-output-stream)
     6673     (clear-stream $_test-output-buffered-file->buffer)
     6674     #
     6675     (write _test-input-stream "fn foo {\n")
     6676     (write _test-input-stream "  var arr/eax: (addr array int) <- copy 0\n")
     6677     (write _test-input-stream "  var idx/ecx: int <- copy 3\n")
     6678     (write _test-input-stream "  var off/ecx: (offset int) <- compute-offset arr, idx\n")
     6679     (write _test-input-stream "  var x/eax: (addr int) <- index arr, off\n")
     6680     (write _test-input-stream "}\n")
     6681     # convert
     6682     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     6683     (flush _test-output-buffered-file)
     6684 +--  6 lines: #?     # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------
     6690     # check output
     6691     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-using-offset/0")
     6692     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-using-offset/1")
     6693     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-using-offset/2")
     6694     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-using-offset/3")
     6695     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-using-offset/4")
     6696     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-using-offset/5")
     6697     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-using-offset/6")
     6698     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-index-into-array-using-offset/7")
     6699     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-index-into-array-using-offset/8")
     6700     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"                  "F - test-convert-index-into-array-using-offset/9")
     6701     (check-next-stream-line-equal _test-output-stream "    69/multiply %ecx 0x00000004/imm32 0x00000001/r32"  "F - test-convert-index-into-array-using-offset/10")
     6702     (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")
     6703     (check-next-stream-line-equal _test-output-stream "    81 7/subop/compare %eax 0/imm32"  "F - test-convert-index-into-array-using-offset/12")
     6704     (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")
     6705     (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")
     6706     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-index-into-array-using-offset/16")
     6707     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-using-offset/17")
     6708     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-using-offset/18")
     6709     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-using-offset/19")
     6710     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-using-offset/20")
     6711     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-using-offset/21")
     6712     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-using-offset/22")
     6713     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-using-offset/23")
     6714     # . epilogue
     6715     89/<- %esp 5/r32/ebp
     6716     5d/pop-to-ebp
     6717     c3/return
     6718
     6719 test-convert-index-into-array-of-bytes-using-offset:
     6720     # . prologue
     6721     55/push-ebp
     6722     89/<- %ebp 4/r32/esp
     6723     # setup
     6724     (clear-stream _test-input-stream)
     6725     (clear-stream $_test-input-buffered-file->buffer)
     6726     (clear-stream _test-output-stream)
     6727     (clear-stream $_test-output-buffered-file->buffer)
     6728     #
     6729     (write _test-input-stream "fn foo {\n")
     6730     (write _test-input-stream "  var arr/eax: (addr array byte) <- copy 0\n")
     6731     (write _test-input-stream "  var idx/ecx: int <- copy 3\n")
     6732     (write _test-input-stream "  var off/ecx: (offset byte) <- compute-offset arr, idx\n")
     6733     (write _test-input-stream "  var x/eax: (addr byte) <- index arr, off\n")
     6734     (write _test-input-stream "}\n")
     6735     # convert
     6736     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     6737     (flush _test-output-buffered-file)
     6738 +--  6 lines: #?     # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------
     6744     # check output
     6745     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-of-bytes-using-offset/0")
     6746     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-of-bytes-using-offset/1")
     6747     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-of-bytes-using-offset/2")
     6748     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-of-bytes-using-offset/3")
     6749     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-of-bytes-using-offset/4")
     6750     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-of-bytes-using-offset/5")
     6751     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-of-bytes-using-offset/6")
     6752     (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")
     6753     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-index-into-array-of-bytes-using-offset/8")
     6754     (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")
     6755     (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")
     6756     (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")
     6757     (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")
     6758     (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")
     6759     (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")
     6760     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-index-into-array-of-bytes-using-offset/15")
     6761     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-of-bytes-using-offset/16")
     6762     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-of-bytes-using-offset/17")
     6763     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-of-bytes-using-offset/18")
     6764     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-of-bytes-using-offset/19")
     6765     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-of-bytes-using-offset/20")
     6766     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-of-bytes-using-offset/21")
     6767     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-of-bytes-using-offset/22")
     6768     # . epilogue
     6769     89/<- %esp 5/r32/ebp
     6770     5d/pop-to-ebp
     6771     c3/return
     6772
     6773 test-convert-index-into-array-using-offset-on-stack:
     6774     # . prologue
     6775     55/push-ebp
     6776     89/<- %ebp 4/r32/esp
     6777     # setup
     6778     (clear-stream _test-input-stream)
     6779     (clear-stream $_test-input-buffered-file->buffer)
     6780     (clear-stream _test-output-stream)
     6781     (clear-stream $_test-output-buffered-file->buffer)
     6782     #
     6783     (write _test-input-stream "fn foo {\n")
     6784     (write _test-input-stream "  var arr/eax: (addr array int) <- copy 0\n")
     6785     (write _test-input-stream "  var idx: int\n")
     6786     (write _test-input-stream "  var off/ecx: (offset int) <- compute-offset arr, idx\n")
     6787     (write _test-input-stream "  var x/eax: (addr int) <- index arr, off\n")
     6788     (write _test-input-stream "}\n")
     6789     # convert
     6790     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     6791     (flush _test-output-buffered-file)
     6792 +--  6 lines: #?     # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------
     6798     # check output
     6799     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-using-offset-on-stack/0")
     6800     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-using-offset-on-stack/1")
     6801     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-using-offset-on-stack/2")
     6802     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-index-into-array-using-offset-on-stack/3")
     6803     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-using-offset-on-stack/4")
     6804     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-using-offset-on-stack/5")
     6805     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-index-into-array-using-offset-on-stack/6")
     6806     (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")
     6807     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"                         "F - test-convert-index-into-array-using-offset-on-stack/8")
     6808     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-index-into-array-using-offset-on-stack/9")
     6809     (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")
     6810     (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")
     6811     (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")
     6812     (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")
     6813     (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")
     6814     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-index-into-array-using-offset-on-stack/15")
     6815     (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")
     6816     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-index-into-array-using-offset-on-stack/17")
     6817     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-using-offset-on-stack/18")
     6818     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-using-offset-on-stack/19")
     6819     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-using-offset-on-stack/20")
     6820     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-index-into-array-using-offset-on-stack/21")
     6821     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-index-into-array-using-offset-on-stack/22")
     6822     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-using-offset-on-stack/23")
     6823     # . epilogue
     6824     89/<- %esp 5/r32/ebp
     6825     5d/pop-to-ebp
     6826     c3/return
     6827
     6828 test-convert-index-into-array-of-bytes-using-offset-on-stack:
     6829     # . prologue
     6830     55/push-ebp
     6831     89/<- %ebp 4/r32/esp
     6832     # setup
     6833     (clear-stream _test-input-stream)
     6834     (clear-stream $_test-input-buffered-file->buffer)
     6835     (clear-stream _test-output-stream)
     6836     (clear-stream $_test-output-buffered-file->buffer)
     6837     #
     6838     (write _test-input-stream "fn foo {\n")
     6839     (write _test-input-stream "  var arr/eax: (addr array byte) <- copy 0\n")
     6840     (write _test-input-stream "  var idx: int\n")
     6841     (write _test-input-stream "  var off/ecx: (offset byte) <- compute-offset arr, idx\n")
     6842     (write _test-input-stream "  var x/eax: (addr byte) <- index arr, off\n")
     6843     (write _test-input-stream "}\n")
     6844     # convert
     6845     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     6846     (flush _test-output-buffered-file)
     6847 +--  6 lines: #?     # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------
     6853     # check output
     6854     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/0")
     6855     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/1")
     6856     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/2")
     6857     (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")
     6858     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/4")
     6859     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/5")
     6860     (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")
     6861     (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")
     6862     (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")
     6863     (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")
     6864     (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")
     6865     (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")
     6866     (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")
     6867     (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")
     6868     (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")
     6869     (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")
     6870     (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")
     6871     (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")
     6872     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/18")
     6873     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/19")
     6874     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/20")
     6875     (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")
     6876     (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")
     6877     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-index-into-array-of-bytes-using-offset-on-stack/23")
     6878     # . epilogue
     6879     89/<- %esp 5/r32/ebp
     6880     5d/pop-to-ebp
     6881     c3/return
     6882
     6883 test-convert-function-and-type-definition:
     6884     # . prologue
     6885     55/push-ebp
     6886     89/<- %ebp 4/r32/esp
     6887     # setup
     6888     (clear-stream _test-input-stream)
     6889     (clear-stream $_test-input-buffered-file->buffer)
     6890     (clear-stream _test-output-stream)
     6891     (clear-stream $_test-output-buffered-file->buffer)
     6892     #
     6893     (write _test-input-stream "fn foo a: (addr t) {\n")
     6894     (write _test-input-stream "  var _a/eax: (addr t) <- copy a\n")
     6895     (write _test-input-stream "  var b/ecx: (addr int) <- get _a, x\n")
     6896     (write _test-input-stream "  var c/ecx: (addr int) <- get _a, y\n")
     6897     (write _test-input-stream "}\n")
     6898     (write _test-input-stream "type t {\n")
     6899     (write _test-input-stream "  x: int\n")
     6900     (write _test-input-stream "  y: int\n")
     6901     (write _test-input-stream "}\n")
     6902     # convert
     6903     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     6904     (flush _test-output-buffered-file)
     6905 +--  6 lines: #?     # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------
     6911     # check output
     6912     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-and-type-definition/0")
     6913     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-and-type-definition/1")
     6914     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-and-type-definition/2")
     6915     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-and-type-definition/3")
     6916     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-and-type-definition/4")
     6917     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-and-type-definition/5")
     6918     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-and-type-definition/6")
     6919     (check-next-stream-line-equal _test-output-stream "    8b/-> *(ebp+0x00000008) 0x00000000/r32"  "F - test-convert-function-and-type-definition/7")
     6920     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-and-type-definition/8")
     6921     (check-next-stream-line-equal _test-output-stream "    81 7/subop/compare %eax 0/imm32"  "F - test-convert-function-and-type-definition/9")
     6922     (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")
     6923     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + 0x00000000) 0x00000001/r32"  "F - test-convert-function-and-type-definition/11")
     6924     (check-next-stream-line-equal _test-output-stream "    81 7/subop/compare %eax 0/imm32"  "F - test-convert-function-and-type-definition/12")
     6925     (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")
     6926     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(eax + 0x00000004) 0x00000001/r32"  "F - test-convert-function-and-type-definition/14")
     6927     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-function-and-type-definition/15")
     6928     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax" "F - test-convert-function-and-type-definition/16")
     6929     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-and-type-definition/17")
     6930     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-and-type-definition/18")
     6931     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-and-type-definition/19")
     6932     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-and-type-definition/20")
     6933     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-and-type-definition/21")
     6934     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-and-type-definition/22")
     6935     # . epilogue
     6936     89/<- %esp 5/r32/ebp
     6937     5d/pop-to-ebp
     6938     c3/return
     6939
     6940 test-type-definition-with-array:
     6941     # . prologue
     6942     55/push-ebp
     6943     89/<- %ebp 4/r32/esp
     6944     # setup
     6945     (clear-stream _test-input-stream)
     6946     (clear-stream $_test-input-buffered-file->buffer)
     6947     (clear-stream _test-output-stream)
     6948     (clear-stream $_test-output-buffered-file->buffer)
     6949     (clear-stream _test-error-stream)
     6950     (clear-stream $_test-error-buffered-file->buffer)
     6951     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     6952     68/push 0/imm32
     6953     68/push 0/imm32
     6954     89/<- %edx 4/r32/esp
     6955     (tailor-exit-descriptor %edx 0x10)
     6956     #
     6957     (write _test-input-stream "type t {\n")
     6958     (write _test-input-stream "  a: (array int 3)\n")
     6959     (write _test-input-stream "}\n")
     6960     # convert
     6961     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     6962     # registers except esp clobbered at this point
     6963     # restore ed
     6964     89/<- %edx 4/r32/esp
     6965     (flush _test-output-buffered-file)
     6966     (flush _test-error-buffered-file)
     6967 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
     6973     # check output
     6974     (check-stream-equal _test-output-stream  ""  "F - test-type-definition-with-array: output should be empty")
     6975     (check-next-stream-line-equal _test-error-stream  "type t: 'array' elements not allowed for now"  "F - test-type-definition-with-array: error message")
     6976     # check that stop(1) was called
     6977     (check-ints-equal *(edx+4) 2 "F - test-type-definition-with-array: exit status")
     6978     # don't restore from ebp
     6979     81 0/subop/add %esp 8/imm32
     6980     # . epilogue
     6981     5d/pop-to-ebp
     6982     c3/return
     6983
     6984 test-type-definition-with-addr:
     6985     # . prologue
     6986     55/push-ebp
     6987     89/<- %ebp 4/r32/esp
     6988     # setup
     6989     (clear-stream _test-input-stream)
     6990     (clear-stream $_test-input-buffered-file->buffer)
     6991     (clear-stream _test-output-stream)
     6992     (clear-stream $_test-output-buffered-file->buffer)
     6993     (clear-stream _test-error-stream)
     6994     (clear-stream $_test-error-buffered-file->buffer)
     6995     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     6996     68/push 0/imm32
     6997     68/push 0/imm32
     6998     89/<- %edx 4/r32/esp
     6999     (tailor-exit-descriptor %edx 0x10)
     7000     #
     7001     (write _test-input-stream "type t {\n")
     7002     (write _test-input-stream "  a: (addr int)\n")
     7003     (write _test-input-stream "}\n")
     7004     # convert
     7005     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     7006     # registers except esp clobbered at this point
     7007     # restore ed
     7008     89/<- %edx 4/r32/esp
     7009     (flush _test-output-buffered-file)
     7010     (flush _test-error-buffered-file)
     7011 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
     7017     # check output
     7018     (check-stream-equal _test-output-stream  ""  "F - test-type-definition-with-addr: output should be empty")
     7019     (check-next-stream-line-equal _test-error-stream  "type t: 'addr' elements not allowed"  "F - test-type-definition-with-addr: error message")
     7020     # check that stop(1) was called
     7021     (check-ints-equal *(edx+4) 2 "F - test-type-definition-with-addr: exit status")
     7022     # don't restore from ebp
     7023     81 0/subop/add %esp 8/imm32
     7024     # . epilogue
     7025     5d/pop-to-ebp
     7026     c3/return
     7027
     7028 test-convert-function-with-local-var-with-user-defined-type:
     7029     # . prologue
     7030     55/push-ebp
     7031     89/<- %ebp 4/r32/esp
     7032     # setup
     7033     (clear-stream _test-input-stream)
     7034     (clear-stream $_test-input-buffered-file->buffer)
     7035     (clear-stream _test-output-stream)
     7036     (clear-stream $_test-output-buffered-file->buffer)
     7037     #
     7038     (write _test-input-stream "fn foo {\n")
     7039     (write _test-input-stream "  var a: t\n")
     7040     (write _test-input-stream "}\n")
     7041     (write _test-input-stream "type t {\n")
     7042     (write _test-input-stream "  x: int\n")
     7043     (write _test-input-stream "  y: int\n")
     7044     (write _test-input-stream "}\n")
     7045     # convert
     7046     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     7047     (flush _test-output-buffered-file)
     7048 +--  6 lines: #?     # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------
     7054     # check output
     7055     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-local-var-with-user-defined-type/0")
     7056     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-local-var-with-user-defined-type/1")
     7057     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-local-var-with-user-defined-type/2")
     7058     (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")
     7059     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-with-user-defined-type/4")
     7060     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-local-var-with-user-defined-type/5")
     7061     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-with-local-var-with-user-defined-type/6")
     7062     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-with-local-var-with-user-defined-type/7")
     7063     (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")
     7064     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-with-user-defined-type/9")
     7065     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-local-var-with-user-defined-type/10")
     7066     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-local-var-with-user-defined-type/11")
     7067     (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")
     7068     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-local-var-with-user-defined-type/13")
     7069     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-local-var-with-user-defined-type/14")
     7070     # . epilogue
     7071     89/<- %esp 5/r32/ebp
     7072     5d/pop-to-ebp
     7073     c3/return
     7074
     7075 test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type:
     7076     # . prologue
     7077     55/push-ebp
     7078     89/<- %ebp 4/r32/esp
     7079     # setup
     7080     (clear-stream _test-input-stream)
     7081     (clear-stream $_test-input-buffered-file->buffer)
     7082     (clear-stream _test-output-stream)
     7083     (clear-stream $_test-output-buffered-file->buffer)
     7084     #
     7085     (write _test-input-stream "fn foo {\n")
     7086     (write _test-input-stream "  var a: t\n")
     7087     (write _test-input-stream "}\n")
     7088     (write _test-input-stream "type t {\n")
     7089     (write _test-input-stream "  x: s\n")
     7090     (write _test-input-stream "}\n")
     7091     (write _test-input-stream "type s {\n")
     7092     (write _test-input-stream "  z: int\n")
     7093     (write _test-input-stream "}\n")
     7094     # convert
     7095     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     7096     (flush _test-output-buffered-file)
     7097 +--  6 lines: #?     # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------
     7103     # check output
     7104     (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")
     7105     (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")
     7106     (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")
     7107     (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")
     7108     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type/4")
     7109     (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")
     7110     (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")
     7111     (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")
     7112     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-local-var-with-user-defined-type-containing-user-defined-type/9")
     7113     (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")
     7114     (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")
     7115     (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")
     7116     (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")
     7117     (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")
     7118     # . epilogue
     7119     89/<- %esp 5/r32/ebp
     7120     5d/pop-to-ebp
     7121     c3/return
     7122
     7123 test-convert-function-call-with-arg-of-user-defined-type:
     7124     # . prologue
     7125     55/push-ebp
     7126     89/<- %ebp 4/r32/esp
     7127     # setup
     7128     (clear-stream _test-input-stream)
     7129     (clear-stream $_test-input-buffered-file->buffer)
     7130     (clear-stream _test-output-stream)
     7131     (clear-stream $_test-output-buffered-file->buffer)
     7132     #
     7133     (write _test-input-stream "fn f {\n")
     7134     (write _test-input-stream "  var a: t\n")
     7135     (write _test-input-stream "  foo a\n")
     7136     (write _test-input-stream "}\n")
     7137     (write _test-input-stream "fn foo x: t {\n")
     7138     (write _test-input-stream "}\n")
     7139     (write _test-input-stream "type t {\n")
     7140     (write _test-input-stream "  x: int\n")
     7141     (write _test-input-stream "  y: int\n")
     7142     (write _test-input-stream "}\n")
     7143     # convert
     7144     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     7145     (flush _test-output-buffered-file)
     7146 +--  6 lines: #?     # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------
     7152     # check output
     7153     (check-next-stream-line-equal _test-output-stream "f:"                      "F - test-convert-function-call-with-arg-of-user-defined-type/0")
     7154     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-arg-of-user-defined-type/1")
     7155     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-arg-of-user-defined-type/2")
     7156     (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")
     7157     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-arg-of-user-defined-type/4")
     7158     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:loop:"     "F - test-convert-function-call-with-arg-of-user-defined-type/5")
     7159     # var a: t
     7160     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-call-with-arg-of-user-defined-type/6")
     7161     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-function-call-with-arg-of-user-defined-type/7")
     7162     # foo a
     7163     (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")
     7164     #
     7165     (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")
     7166     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-arg-of-user-defined-type/10")
     7167     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:break:"    "F - test-convert-function-call-with-arg-of-user-defined-type/11")
     7168     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-arg-of-user-defined-type/12")
     7169     (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")
     7170     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-arg-of-user-defined-type/14")
     7171     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-arg-of-user-defined-type/15")
     7172     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-call-with-arg-of-user-defined-type/16")
     7173     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-arg-of-user-defined-type/17")
     7174     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-arg-of-user-defined-type/18")
     7175     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-call-with-arg-of-user-defined-type/19")
     7176     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-arg-of-user-defined-type/20")
     7177     (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")
     7178     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-arg-of-user-defined-type/22")
     7179     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-arg-of-user-defined-type/23")
     7180     # . epilogue
     7181     89/<- %esp 5/r32/ebp
     7182     5d/pop-to-ebp
     7183     c3/return
     7184
     7185 test-convert-function-call-with-arg-of-user-defined-type-register-indirect:
     7186     # . prologue
     7187     55/push-ebp
     7188     89/<- %ebp 4/r32/esp
     7189     # setup
     7190     (clear-stream _test-input-stream)
     7191     (clear-stream $_test-input-buffered-file->buffer)
     7192     (clear-stream _test-output-stream)
     7193     (clear-stream $_test-output-buffered-file->buffer)
     7194     #
     7195     (write _test-input-stream "fn f {\n")
     7196     (write _test-input-stream "  var a/eax: (addr t) <- copy 0\n")
     7197     (write _test-input-stream "  foo *a\n")
     7198     (write _test-input-stream "}\n")
     7199     (write _test-input-stream "fn foo x: t {\n")
     7200     (write _test-input-stream "}\n")
     7201     (write _test-input-stream "type t {\n")
     7202     (write _test-input-stream "  x: int\n")
     7203     (write _test-input-stream "  y: int\n")
     7204     (write _test-input-stream "}\n")
     7205     # convert
     7206     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     7207     (flush _test-output-buffered-file)
     7208 +--  6 lines: #?     # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------
     7214     # check output
     7215     (check-next-stream-line-equal _test-output-stream "f:"                      "F - test-convert-function-call-with-arg-of-user-defined-type/0")
     7216     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-arg-of-user-defined-type/1")
     7217     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-arg-of-user-defined-type/2")
     7218     (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")
     7219     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-arg-of-user-defined-type/4")
     7220     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:loop:"     "F - test-convert-function-call-with-arg-of-user-defined-type/5")
     7221     # var a
     7222     (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")
     7223     (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")
     7224     # foo a
     7225     (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")
     7226     #
     7227     (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")
     7228     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-arg-of-user-defined-type/10")
     7229     (check-next-stream-line-equal _test-output-stream "$f:0x00000001:break:"    "F - test-convert-function-call-with-arg-of-user-defined-type/11")
     7230     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-arg-of-user-defined-type/12")
     7231     (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")
     7232     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-arg-of-user-defined-type/14")
     7233     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-arg-of-user-defined-type/15")
     7234     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-call-with-arg-of-user-defined-type/16")
     7235     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-arg-of-user-defined-type/17")
     7236     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-call-with-arg-of-user-defined-type/18")
     7237     (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")
     7238     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-arg-of-user-defined-type/20")
     7239     (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")
     7240     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-call-with-arg-of-user-defined-type/22")
     7241     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-arg-of-user-defined-type/23")
     7242     # . epilogue
     7243     89/<- %esp 5/r32/ebp
     7244     5d/pop-to-ebp
     7245     c3/return
     7246
     7247 # we don't have special support for call-by-reference; just explicitly create
     7248 # a new variable with the address of the arg
     7249 test-convert-function-call-with-arg-of-user-defined-type-by-reference:
     7250     # . prologue
     7251     55/push-ebp
     7252     89/<- %ebp 4/r32/esp
     7253     # setup
     7254     (clear-stream _test-input-stream)
     7255     (clear-stream $_test-input-buffered-file->buffer)
     7256     (clear-stream _test-output-stream)
     7257     (clear-stream $_test-output-buffered-file->buffer)
     7258     #
     7259     (write _test-input-stream "fn f {\n")
     7260     (write _test-input-stream "  var a: t\n")
     7261     (write _test-input-stream "  var b/eax: (addr t) <- address a\n")
     7262     (write _test-input-stream "  foo b\n")
     7263     (write _test-input-stream "}\n")
     7264     (write _test-input-stream "fn foo x: (addr t) {\n")
     7265     (write _test-input-stream "  var x/ecx: (addr t) <- copy x\n")
     7266     (write _test-input-stream "}\n")
     7267     (write _test-input-stream "type t {\n")
     7268     (write _test-input-stream "  x: int\n")
     7269     (write _test-input-stream "  y: int\n")
     7270     (write _test-input-stream "}\n")
     7271     # convert
     7272     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     7273     (flush _test-output-buffered-file)
     7274 +--  6 lines: #?     # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------
     7280     # check output
     7281     (check-next-stream-line-equal _test-output-stream "f:"                      "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/0")
     7282     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/1")
     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/2")
     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/3")
     7285     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/4")
     7286     (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")
     7287     # var a: t
     7288     (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")
     7289     (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")
     7290     # var b/eax: (addr t)
     7291     (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")
     7292     (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")
     7293     # foo a
     7294     (check-next-stream-line-equal _test-output-stream "    (foo %eax)"          "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/10")
     7295     #
     7296     (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")
     7297     (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")
     7298     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/13")
     7299     (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")
     7300     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/15")
     7301     (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")
     7302     (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")
     7303     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/18")
     7304     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/19")
     7305     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/20")
     7306     (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")
     7307     (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")
     7308     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/23")
     7309     (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")
     7310     (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")
     7311     (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")
     7312     (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")
     7313     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/28")
     7314     (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")
     7315     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/30")
     7316     (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")
     7317     (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")
     7318     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-call-with-arg-of-user-defined-type-by-reference/33")
     7319     # . epilogue
     7320     89/<- %esp 5/r32/ebp
     7321     5d/pop-to-ebp
     7322     c3/return
     7323
     7324 test-convert-get-on-local-variable:
     7325     # . prologue
     7326     55/push-ebp
     7327     89/<- %ebp 4/r32/esp
     7328     # setup
     7329     (clear-stream _test-input-stream)
     7330     (clear-stream $_test-input-buffered-file->buffer)
     7331     (clear-stream _test-output-stream)
     7332     (clear-stream $_test-output-buffered-file->buffer)
     7333     #
     7334     (write _test-input-stream "fn foo {\n")
     7335     (write _test-input-stream "  var a: t\n")
     7336     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
     7337     (write _test-input-stream "}\n")
     7338     (write _test-input-stream "type t {\n")
     7339     (write _test-input-stream "  x: int\n")
     7340     (write _test-input-stream "  y: int\n")
     7341     (write _test-input-stream "}\n")
     7342     # convert
     7343     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     7344     (flush _test-output-buffered-file)
     7345 +--  6 lines: #?     # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------
     7351     # check output
     7352     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-get-on-local-variable/0")
     7353     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-get-on-local-variable/1")
     7354     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-get-on-local-variable/2")
     7355     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-get-on-local-variable/3")
     7356     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-get-on-local-variable/4")
     7357     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-get-on-local-variable/5")
     7358     # var a
     7359     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-get-on-local-variable/6")
     7360     (check-next-stream-line-equal _test-output-stream "    68/push 0/imm32"     "F - test-convert-get-on-local-variable/7")
     7361     # var c
     7362     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-get-on-local-variable/8")
     7363     # get
     7364     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(ebp+0xfffffffc) 0x00000001/r32"  "F - test-convert-get-on-local-variable/9")
     7365     # reclaim c
     7366     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-get-on-local-variable/10")
     7367     # reclaim a
     7368     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 0x00000008/imm32"  "F - test-convert-get-on-local-variable/11")
     7369     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-get-on-local-variable/12")
     7370     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-get-on-local-variable/13")
     7371     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-get-on-local-variable/14")
     7372     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-get-on-local-variable/15")
     7373     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-get-on-local-variable/16")
     7374     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-get-on-local-variable/17")
     7375     # . epilogue
     7376     89/<- %esp 5/r32/ebp
     7377     5d/pop-to-ebp
     7378     c3/return
     7379
     7380 test-convert-get-on-function-argument:
     7381     # . prologue
     7382     55/push-ebp
     7383     89/<- %ebp 4/r32/esp
     7384     # setup
     7385     (clear-stream _test-input-stream)
     7386     (clear-stream $_test-input-buffered-file->buffer)
     7387     (clear-stream _test-output-stream)
     7388     (clear-stream $_test-output-buffered-file->buffer)
     7389     #
     7390     (write _test-input-stream "fn foo a: t {\n")
     7391     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
     7392     (write _test-input-stream "}\n")
     7393     (write _test-input-stream "type t {\n")
     7394     (write _test-input-stream "  x: int\n")
     7395     (write _test-input-stream "  y: int\n")
     7396     (write _test-input-stream "}\n")
     7397     # convert
     7398     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     7399     (flush _test-output-buffered-file)
     7400 +--  6 lines: #?     # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------
     7406     # check output
     7407     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-get-on-function-argument/0")
     7408     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-get-on-function-argument/1")
     7409     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-get-on-function-argument/2")
     7410     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-get-on-function-argument/3")
     7411     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-get-on-function-argument/4")
     7412     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-get-on-function-argument/5")
     7413     # var c
     7414     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-get-on-function-argument/6")
     7415     # get
     7416     (check-next-stream-line-equal _test-output-stream "    8d/copy-address *(ebp+0x0000000c) 0x00000001/r32"  "F - test-convert-get-on-function-argument/7")
     7417     # reclaim c
     7418     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-get-on-function-argument/8")
     7419     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-get-on-function-argument/9")
     7420     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-get-on-function-argument/10")
     7421     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-get-on-function-argument/11")
     7422     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-get-on-function-argument/12")
     7423     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-get-on-function-argument/13")
     7424     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-get-on-function-argument/14")
     7425     # . epilogue
     7426     89/<- %esp 5/r32/ebp
     7427     5d/pop-to-ebp
     7428     c3/return
     7429
     7430 test-convert-get-on-function-argument-with-known-type:
     7431     # . prologue
     7432     55/push-ebp
     7433     89/<- %ebp 4/r32/esp
     7434     # setup
     7435     (clear-stream _test-input-stream)
     7436     (clear-stream $_test-input-buffered-file->buffer)
     7437     (clear-stream _test-output-stream)
     7438     (clear-stream $_test-output-buffered-file->buffer)
     7439     #
     7440     (write _test-input-stream "type t {\n")
     7441     (write _test-input-stream "  x: int\n")
     7442     (write _test-input-stream "  y: int\n")
     7443     (write _test-input-stream "}\n")
     7444     (write _test-input-stream "fn foo a: t {\n")
     7445     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
     7446     (write _test-input-stream "}\n")
     7447     # convert
     7448     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     7449     (flush _test-output-buffered-file)
     7450 +--  6 lines: #?     # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------
     7456     # check output
     7457     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-get-on-function-argument-with-known-type/0")
     7458     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-get-on-function-argument-with-known-type/1")
     7459     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-get-on-function-argument-with-known-type/2")
     7460     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-get-on-function-argument-with-known-type/3")
     7461     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-get-on-function-argument-with-known-type/4")
     7462     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-get-on-function-argument-with-known-type/5")
     7463     # var c
     7464     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-get-on-function-argument-with-known-type/6")
     7465     # get
     7466     (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")
     7467     # reclaim c
     7468     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx" "F - test-convert-get-on-function-argument-with-known-type/8")
     7469     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-get-on-function-argument-with-known-type/9")
     7470     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-get-on-function-argument-with-known-type/10")
     7471     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-get-on-function-argument-with-known-type/11")
     7472     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-get-on-function-argument-with-known-type/12")
     7473     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-get-on-function-argument-with-known-type/13")
     7474     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-get-on-function-argument-with-known-type/14")
     7475     # . epilogue
     7476     89/<- %esp 5/r32/ebp
     7477     5d/pop-to-ebp
     7478     c3/return
     7479
     7480 test-add-with-too-many-inouts:
     7481     # . prologue
     7482     55/push-ebp
     7483     89/<- %ebp 4/r32/esp
     7484     # setup
     7485     (clear-stream _test-input-stream)
     7486     (clear-stream $_test-input-buffered-file->buffer)
     7487     (clear-stream _test-output-stream)
     7488     (clear-stream $_test-output-buffered-file->buffer)
     7489     (clear-stream _test-error-stream)
     7490     (clear-stream $_test-error-buffered-file->buffer)
     7491     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     7492     68/push 0/imm32
     7493     68/push 0/imm32
     7494     89/<- %edx 4/r32/esp
     7495     (tailor-exit-descriptor %edx 0x10)
     7496     #
     7497     (write _test-input-stream "fn foo {\n")
     7498     (write _test-input-stream "  var a: int\n")
     7499     (write _test-input-stream "  var b/ecx: int <- add a, 0\n")
     7500     (write _test-input-stream "}\n")
     7501     # convert
     7502     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     7503     # registers except esp clobbered at this point
     7504     # restore ed
     7505     89/<- %edx 4/r32/esp
     7506     (flush _test-output-buffered-file)
     7507     (flush _test-error-buffered-file)
     7508 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
     7514     # check output
     7515     (check-stream-equal _test-output-stream  ""  "F - test-add-with-too-many-inouts: output should be empty")
     7516     (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")
     7517     # check that stop(1) was called
     7518     (check-ints-equal *(edx+4) 2 "F - test-add-with-too-many-inouts: exit status")
     7519     # don't restore from ebp
     7520     81 0/subop/add %esp 8/imm32
     7521     # . epilogue
     7522     5d/pop-to-ebp
     7523     c3/return
     7524
     7525 test-add-with-too-many-inouts-2:
     7526     # . prologue
     7527     55/push-ebp
     7528     89/<- %ebp 4/r32/esp
     7529     # setup
     7530     (clear-stream _test-input-stream)
     7531     (clear-stream $_test-input-buffered-file->buffer)
     7532     (clear-stream _test-output-stream)
     7533     (clear-stream $_test-output-buffered-file->buffer)
     7534     (clear-stream _test-error-stream)
     7535     (clear-stream $_test-error-buffered-file->buffer)
     7536     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     7537     68/push 0/imm32
     7538     68/push 0/imm32
     7539     89/<- %edx 4/r32/esp
     7540     (tailor-exit-descriptor %edx 0x10)
     7541     #
     7542     (write _test-input-stream "fn foo {\n")
     7543     (write _test-input-stream "  var a: int\n")
     7544     (write _test-input-stream "  add-to a, 0, 1\n")
     7545     (write _test-input-stream "}\n")
     7546     # convert
     7547     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     7548     # registers except esp clobbered at this point
     7549     # restore ed
     7550     89/<- %edx 4/r32/esp
     7551     (flush _test-output-buffered-file)
     7552     (flush _test-error-buffered-file)
     7553 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
     7559     # check output
     7560     (check-stream-equal _test-output-stream  ""  "F - test-add-with-too-many-inouts-2: output should be empty")
     7561     (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")
     7562     # check that stop(1) was called
     7563     (check-ints-equal *(edx+4) 2 "F - test-add-with-too-many-inouts-2: exit status")
     7564     # don't restore from ebp
     7565     81 0/subop/add %esp 8/imm32
     7566     # . epilogue
     7567     5d/pop-to-ebp
     7568     c3/return
     7569
     7570 test-add-with-too-many-outputs:
     7571     # . prologue
     7572     55/push-ebp
     7573     89/<- %ebp 4/r32/esp
     7574     # setup
     7575     (clear-stream _test-input-stream)
     7576     (clear-stream $_test-input-buffered-file->buffer)
     7577     (clear-stream _test-output-stream)
     7578     (clear-stream $_test-output-buffered-file->buffer)
     7579     (clear-stream _test-error-stream)
     7580     (clear-stream $_test-error-buffered-file->buffer)
     7581     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     7582     68/push 0/imm32
     7583     68/push 0/imm32
     7584     89/<- %edx 4/r32/esp
     7585     (tailor-exit-descriptor %edx 0x10)
     7586     #
     7587     (write _test-input-stream "fn foo {\n")
     7588     (write _test-input-stream "  var a/eax: int <- copy 0\n")
     7589     (write _test-input-stream "  var b/ebx: int <- copy 0\n")
     7590     (write _test-input-stream "  var c/ecx: int <- copy 0\n")
     7591     (write _test-input-stream "  c, b <- add a\n")
     7592     (write _test-input-stream "}\n")
     7593     # convert
     7594     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     7595     # registers except esp clobbered at this point
     7596     # restore ed
     7597     89/<- %edx 4/r32/esp
     7598     (flush _test-output-buffered-file)
     7599     (flush _test-error-buffered-file)
     7600 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
     7606     # check output
     7607     (check-stream-equal _test-output-stream  ""  "F - test-add-with-too-many-outputs: output should be empty")
     7608     (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")
     7609     # check that stop(1) was called
     7610     (check-ints-equal *(edx+4) 2 "F - test-add-with-too-many-outputs: exit status")
     7611     # don't restore from ebp
     7612     81 0/subop/add %esp 8/imm32
     7613     # . epilogue
     7614     5d/pop-to-ebp
     7615     c3/return
     7616
     7617 test-add-with-non-number:
     7618     # . prologue
     7619     55/push-ebp
     7620     89/<- %ebp 4/r32/esp
     7621     # setup
     7622     (clear-stream _test-input-stream)
     7623     (clear-stream $_test-input-buffered-file->buffer)
     7624     (clear-stream _test-output-stream)
     7625     (clear-stream $_test-output-buffered-file->buffer)
     7626     (clear-stream _test-error-stream)
     7627     (clear-stream $_test-error-buffered-file->buffer)
     7628     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     7629     68/push 0/imm32
     7630     68/push 0/imm32
     7631     89/<- %edx 4/r32/esp
     7632     (tailor-exit-descriptor %edx 0x10)
     7633     #
     7634     (write _test-input-stream "fn foo {\n")
     7635     (write _test-input-stream "  var a: int\n")
     7636     (write _test-input-stream "  var b/ecx: (addr int) <- add a\n")
     7637     (write _test-input-stream "}\n")
     7638     # convert
     7639     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     7640     # registers except esp clobbered at this point
     7641     # restore ed
     7642     89/<- %edx 4/r32/esp
     7643     (flush _test-output-buffered-file)
     7644     (flush _test-error-buffered-file)
     7645 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
     7651     # check output
     7652     (check-stream-equal _test-output-stream  ""  "F - test-add-with-non-number: output should be empty")
     7653     (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")
     7654     # check that stop(1) was called
     7655     (check-ints-equal *(edx+4) 2 "F - test-add-with-non-number: exit status")
     7656     # don't restore from ebp
     7657     81 0/subop/add %esp 8/imm32
     7658     # . epilogue
     7659     5d/pop-to-ebp
     7660     c3/return
     7661
     7662 test-add-with-addr-dereferenced:
     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     #
     7672     (write _test-input-stream "fn foo {\n")
     7673     (write _test-input-stream "  var a/eax: (addr int) <- copy 0\n")
     7674     (write _test-input-stream "  add-to *a, 1\n")
     7675     (write _test-input-stream "}\n")
     7676     # convert
     7677     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     7678     (flush _test-output-buffered-file)
     7679     # no error
     7680     # . epilogue
     7681     89/<- %esp 5/r32/ebp
     7682     5d/pop-to-ebp
     7683     c3/return
     7684
     7685 test-copy-with-no-inout:
     7686     # . prologue
     7687     55/push-ebp
     7688     89/<- %ebp 4/r32/esp
     7689     # setup
     7690     (clear-stream _test-input-stream)
     7691     (clear-stream $_test-input-buffered-file->buffer)
     7692     (clear-stream _test-output-stream)
     7693     (clear-stream $_test-output-buffered-file->buffer)
     7694     (clear-stream _test-error-stream)
     7695     (clear-stream $_test-error-buffered-file->buffer)
     7696     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     7697     68/push 0/imm32
     7698     68/push 0/imm32
     7699     89/<- %edx 4/r32/esp
     7700     (tailor-exit-descriptor %edx 0x10)
     7701     #
     7702     (write _test-input-stream "fn foo {\n")
     7703     (write _test-input-stream "  var x/eax: boolean <- copy\n")
     7704     (write _test-input-stream "}\n")
     7705     # convert
     7706     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     7707     # registers except esp clobbered at this point
     7708     # restore ed
     7709     89/<- %edx 4/r32/esp
     7710     (flush _test-output-buffered-file)
     7711     (flush _test-error-buffered-file)
     7712 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
     7718     # check output
     7719     (check-stream-equal _test-output-stream  ""  "F - test-copy-with-no-inout: output should be empty")
     7720     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy' expects an inout"  "F - test-copy-with-no-inout: error message")
     7721     # check that stop(1) was called
     7722     (check-ints-equal *(edx+4) 2 "F - test-copy-with-no-inout: exit status")
     7723     # don't restore from ebp
     7724     81 0/subop/add %esp 8/imm32
     7725     # . epilogue
     7726     5d/pop-to-ebp
     7727     c3/return
     7728
     7729 test-copy-with-multiple-inouts:
     7730     # . prologue
     7731     55/push-ebp
     7732     89/<- %ebp 4/r32/esp
     7733     # setup
     7734     (clear-stream _test-input-stream)
     7735     (clear-stream $_test-input-buffered-file->buffer)
     7736     (clear-stream _test-output-stream)
     7737     (clear-stream $_test-output-buffered-file->buffer)
     7738     (clear-stream _test-error-stream)
     7739     (clear-stream $_test-error-buffered-file->buffer)
     7740     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     7741     68/push 0/imm32
     7742     68/push 0/imm32
     7743     89/<- %edx 4/r32/esp
     7744     (tailor-exit-descriptor %edx 0x10)
     7745     #
     7746     (write _test-input-stream "fn foo {\n")
     7747     (write _test-input-stream "  var x/eax: boolean <- copy 0, 0\n")
     7748     (write _test-input-stream "}\n")
     7749     # convert
     7750     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     7751     # registers except esp clobbered at this point
     7752     # restore ed
     7753     89/<- %edx 4/r32/esp
     7754     (flush _test-output-buffered-file)
     7755     (flush _test-error-buffered-file)
     7756 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
     7762     # check output
     7763     (check-stream-equal _test-output-stream  ""  "F - test-copy-with-multiple-inouts: output should be empty")
     7764     (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")
     7765     # check that stop(1) was called
     7766     (check-ints-equal *(edx+4) 2 "F - test-copy-with-multiple-inouts: exit status")
     7767     # don't restore from ebp
     7768     81 0/subop/add %esp 8/imm32
     7769     # . epilogue
     7770     5d/pop-to-ebp
     7771     c3/return
     7772
     7773 test-copy-with-no-output:
     7774     # . prologue
     7775     55/push-ebp
     7776     89/<- %ebp 4/r32/esp
     7777     # setup
     7778     (clear-stream _test-input-stream)
     7779     (clear-stream $_test-input-buffered-file->buffer)
     7780     (clear-stream _test-output-stream)
     7781     (clear-stream $_test-output-buffered-file->buffer)
     7782     (clear-stream _test-error-stream)
     7783     (clear-stream $_test-error-buffered-file->buffer)
     7784     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     7785     68/push 0/imm32
     7786     68/push 0/imm32
     7787     89/<- %edx 4/r32/esp
     7788     (tailor-exit-descriptor %edx 0x10)
     7789     #
     7790     (write _test-input-stream "fn foo {\n")
     7791     (write _test-input-stream "  copy 0\n")
     7792     (write _test-input-stream "}\n")
     7793     # convert
     7794     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     7795     # registers except esp clobbered at this point
     7796     # restore ed
     7797     89/<- %edx 4/r32/esp
     7798     (flush _test-output-buffered-file)
     7799     (flush _test-error-buffered-file)
     7800 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
     7806     # check output
     7807     (check-stream-equal _test-output-stream  ""  "F - test-copy-with-no-output: output should be empty")
     7808     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy' expects an output"  "F - test-copy-with-no-output: error message")
     7809     # check that stop(1) was called
     7810     (check-ints-equal *(edx+4) 2 "F - test-copy-with-no-output: exit status")
     7811     # don't restore from ebp
     7812     81 0/subop/add %esp 8/imm32
     7813     # . epilogue
     7814     5d/pop-to-ebp
     7815     c3/return
     7816
     7817 test-copy-with-multiple-outputs:
     7818     # . prologue
     7819     55/push-ebp
     7820     89/<- %ebp 4/r32/esp
     7821     # setup
     7822     (clear-stream _test-input-stream)
     7823     (clear-stream $_test-input-buffered-file->buffer)
     7824     (clear-stream _test-output-stream)
     7825     (clear-stream $_test-output-buffered-file->buffer)
     7826     (clear-stream _test-error-stream)
     7827     (clear-stream $_test-error-buffered-file->buffer)
     7828     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     7829     68/push 0/imm32
     7830     68/push 0/imm32
     7831     89/<- %edx 4/r32/esp
     7832     (tailor-exit-descriptor %edx 0x10)
     7833     #
     7834     (write _test-input-stream "fn foo {\n")
     7835     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
     7836     (write _test-input-stream "  var y/ecx: boolean <- copy 0\n")
     7837     (write _test-input-stream "  x, y <- copy 0\n")
     7838     (write _test-input-stream "}\n")
     7839     # convert
     7840     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     7841     # registers except esp clobbered at this point
     7842     # restore ed
     7843     89/<- %edx 4/r32/esp
     7844     (flush _test-output-buffered-file)
     7845     (flush _test-error-buffered-file)
     7846 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
     7852     # check output
     7853     (check-stream-equal _test-output-stream  ""  "F - test-copy-with-multiple-outputs: output should be empty")
     7854     (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")
     7855     # check that stop(1) was called
     7856     (check-ints-equal *(edx+4) 2 "F - test-copy-with-multiple-outputs: exit status")
     7857     # don't restore from ebp
     7858     81 0/subop/add %esp 8/imm32
     7859     # . epilogue
     7860     5d/pop-to-ebp
     7861     c3/return
     7862
     7863 test-copy-invalid-value-to-address:
     7864     # . prologue
     7865     55/push-ebp
     7866     89/<- %ebp 4/r32/esp
     7867     # setup
     7868     (clear-stream _test-input-stream)
     7869     (clear-stream $_test-input-buffered-file->buffer)
     7870     (clear-stream _test-output-stream)
     7871     (clear-stream $_test-output-buffered-file->buffer)
     7872     (clear-stream _test-error-stream)
     7873     (clear-stream $_test-error-buffered-file->buffer)
     7874     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     7875     68/push 0/imm32
     7876     68/push 0/imm32
     7877     89/<- %edx 4/r32/esp
     7878     (tailor-exit-descriptor %edx 0x10)
     7879     #
     7880     (write _test-input-stream "fn foo {\n")
     7881     (write _test-input-stream "  var x/eax: int <- copy 0\n")
     7882     (write _test-input-stream "  var y/ecx: (addr int) <- copy x\n")
     7883     (write _test-input-stream "}\n")
     7884     # convert
     7885     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     7886     # registers except esp clobbered at this point
     7887     # restore ed
     7888     89/<- %edx 4/r32/esp
     7889     (flush _test-output-buffered-file)
     7890     (flush _test-error-buffered-file)
     7891 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
     7897     # check output
     7898     (check-stream-equal _test-output-stream  ""  "F - test-copy-invalid-value-to-address: output should be empty")
     7899     (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")
     7900     # check that stop(1) was called
     7901     (check-ints-equal *(edx+4) 2 "F - test-copy-invalid-value-to-address: exit status")
     7902     # don't restore from ebp
     7903     81 0/subop/add %esp 8/imm32
     7904     # . epilogue
     7905     5d/pop-to-ebp
     7906     c3/return
     7907
     7908 test-copy-null-value-to-address:
     7909     # . prologue
     7910     55/push-ebp
     7911     89/<- %ebp 4/r32/esp
     7912     # setup
     7913     (clear-stream _test-input-stream)
     7914     (clear-stream $_test-input-buffered-file->buffer)
     7915     (clear-stream _test-output-stream)
     7916     (clear-stream $_test-output-buffered-file->buffer)
     7917     #
     7918     (write _test-input-stream "fn foo {\n")
     7919     (write _test-input-stream "  var y/ecx: (addr int) <- copy 0\n")
     7920     (write _test-input-stream "}\n")
     7921     # convert
     7922     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     7923     (flush _test-output-buffered-file)
     7924     # no errors
     7925     # . epilogue
     7926     89/<- %esp 5/r32/ebp
     7927     5d/pop-to-ebp
     7928     c3/return
     7929
     7930 test-copy-invalid-value-to-offset:
     7931     # . prologue
     7932     55/push-ebp
     7933     89/<- %ebp 4/r32/esp
     7934     # setup
     7935     (clear-stream _test-input-stream)
     7936     (clear-stream $_test-input-buffered-file->buffer)
     7937     (clear-stream _test-output-stream)
     7938     (clear-stream $_test-output-buffered-file->buffer)
     7939     (clear-stream _test-error-stream)
     7940     (clear-stream $_test-error-buffered-file->buffer)
     7941     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     7942     68/push 0/imm32
     7943     68/push 0/imm32
     7944     89/<- %edx 4/r32/esp
     7945     (tailor-exit-descriptor %edx 0x10)
     7946     #
     7947     (write _test-input-stream "fn foo {\n")
     7948     (write _test-input-stream "  var x/eax: int <- copy 0\n")
     7949     (write _test-input-stream "  var y/ecx: (offset int) <- copy x\n")
     7950     (write _test-input-stream "}\n")
     7951     # convert
     7952     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     7953     # registers except esp clobbered at this point
     7954     # restore ed
     7955     89/<- %edx 4/r32/esp
     7956     (flush _test-output-buffered-file)
     7957     (flush _test-error-buffered-file)
     7958 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
     7964     # check output
     7965     (check-stream-equal _test-output-stream  ""  "F - test-copy-invalid-value-to-address: output should be empty")
     7966     (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")
     7967     # check that stop(1) was called
     7968     (check-ints-equal *(edx+4) 2 "F - test-copy-invalid-value-to-offset: exit status")
     7969     # don't restore from ebp
     7970     81 0/subop/add %esp 8/imm32
     7971     # . epilogue
     7972     5d/pop-to-ebp
     7973     c3/return
     7974
     7975 test-copy-null-value-to-offset:
     7976     # . prologue
     7977     55/push-ebp
     7978     89/<- %ebp 4/r32/esp
     7979     # setup
     7980     (clear-stream _test-input-stream)
     7981     (clear-stream $_test-input-buffered-file->buffer)
     7982     (clear-stream _test-output-stream)
     7983     (clear-stream $_test-output-buffered-file->buffer)
     7984     #
     7985     (write _test-input-stream "fn foo {\n")
     7986     (write _test-input-stream "  var y/ecx: (offset int) <- copy 0\n")
     7987     (write _test-input-stream "}\n")
     7988     # convert
     7989     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     7990     (flush _test-output-buffered-file)
     7991 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
     7997     # no errors
     7998     # . epilogue
     7999     89/<- %esp 5/r32/ebp
     8000     5d/pop-to-ebp
     8001     c3/return
     8002
     8003 test-copy-non-literal-to-byte:
     8004     # . prologue
     8005     55/push-ebp
     8006     89/<- %ebp 4/r32/esp
     8007     # setup
     8008     (clear-stream _test-input-stream)
     8009     (clear-stream $_test-input-buffered-file->buffer)
     8010     (clear-stream _test-output-stream)
     8011     (clear-stream $_test-output-buffered-file->buffer)
     8012     (clear-stream _test-error-stream)
     8013     (clear-stream $_test-error-buffered-file->buffer)
     8014     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     8015     68/push 0/imm32
     8016     68/push 0/imm32
     8017     89/<- %edx 4/r32/esp
     8018     (tailor-exit-descriptor %edx 0x10)
     8019     #
     8020     (write _test-input-stream "fn foo {\n")
     8021     (write _test-input-stream "  var x/ecx: int <- copy 3\n")
     8022     (write _test-input-stream "  var y/ecx: byte <- copy x\n")
     8023     (write _test-input-stream "}\n")
     8024     # convert
     8025     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     8026     # registers except esp clobbered at this point
     8027     # restore ed
     8028     89/<- %edx 4/r32/esp
     8029     (flush _test-output-buffered-file)
     8030     (flush _test-error-buffered-file)
     8031 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
     8037     # check output
     8038     (check-stream-equal _test-output-stream  ""  "F - test-copy-non-literal-to-byte: output should be empty")
     8039     (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")
     8040     # check that stop(1) was called
     8041     (check-ints-equal *(edx+4) 2 "F - test-copy-non-literal-to-byte: exit status")
     8042     # don't restore from ebp
     8043     81 0/subop/add %esp 8/imm32
     8044     # . epilogue
     8045     5d/pop-to-ebp
     8046     c3/return
     8047
     8048 test-copy-deref-address:
     8049     # . prologue
     8050     55/push-ebp
     8051     89/<- %ebp 4/r32/esp
     8052     # setup
     8053     (clear-stream _test-input-stream)
     8054     (clear-stream $_test-input-buffered-file->buffer)
     8055     (clear-stream _test-output-stream)
     8056     (clear-stream $_test-output-buffered-file->buffer)
     8057     #
     8058     (write _test-input-stream "fn foo {\n")
     8059     (write _test-input-stream "  var x/eax: (addr addr int) <- copy 0\n")
     8060     (write _test-input-stream "  var y/ecx: (addr int) <- copy *x\n")
     8061     (write _test-input-stream "}\n")
     8062     # convert
     8063     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     8064     (flush _test-output-buffered-file)
     8065     # no errors
     8066     # . epilogue
     8067     5d/pop-to-ebp
     8068     c3/return
     8069
     8070 test-copy-to-non-register:
     8071     # . prologue
     8072     55/push-ebp
     8073     89/<- %ebp 4/r32/esp
     8074     # setup
     8075     (clear-stream _test-input-stream)
     8076     (clear-stream $_test-input-buffered-file->buffer)
     8077     (clear-stream _test-output-stream)
     8078     (clear-stream $_test-output-buffered-file->buffer)
     8079     (clear-stream _test-error-stream)
     8080     (clear-stream $_test-error-buffered-file->buffer)
     8081     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     8082     68/push 0/imm32
     8083     68/push 0/imm32
     8084     89/<- %edx 4/r32/esp
     8085     (tailor-exit-descriptor %edx 0x10)
     8086     #
     8087     (write _test-input-stream "fn foo {\n")
     8088     (write _test-input-stream "  var x: int\n")
     8089     (write _test-input-stream "  x <- copy 0\n")
     8090     (write _test-input-stream "}\n")
     8091     # convert
     8092     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     8093     # registers except esp clobbered at this point
     8094     # restore ed
     8095     89/<- %edx 4/r32/esp
     8096     (flush _test-output-buffered-file)
     8097     (flush _test-error-buffered-file)
     8098 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
     8104     # check output
     8105     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-non-register: output should be empty")
     8106     (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")
     8107     # check that stop(1) was called
     8108     (check-ints-equal *(edx+4) 2 "F - test-copy-to-non-register: exit status")
     8109     # don't restore from ebp
     8110     81 0/subop/add %esp 8/imm32
     8111     # . epilogue
     8112     5d/pop-to-ebp
     8113     c3/return
     8114
     8115 test-copy-from-non-scalar-inout:
     8116     # . prologue
     8117     55/push-ebp
     8118     89/<- %ebp 4/r32/esp
     8119     # setup
     8120     (clear-stream _test-input-stream)
     8121     (clear-stream $_test-input-buffered-file->buffer)
     8122     (clear-stream _test-output-stream)
     8123     (clear-stream $_test-output-buffered-file->buffer)
     8124     (clear-stream _test-error-stream)
     8125     (clear-stream $_test-error-buffered-file->buffer)
     8126     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     8127     68/push 0/imm32
     8128     68/push 0/imm32
     8129     89/<- %edx 4/r32/esp
     8130     (tailor-exit-descriptor %edx 0x10)
     8131     #
     8132     (write _test-input-stream "fn foo {\n")
     8133     (write _test-input-stream "  var x: (handle int)\n")
     8134     (write _test-input-stream "  var y/eax: int <- copy x\n")
     8135     (write _test-input-stream "}\n")
     8136     # convert
     8137     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     8138     # registers except esp clobbered at this point
     8139     # restore ed
     8140     89/<- %edx 4/r32/esp
     8141     (flush _test-output-buffered-file)
     8142     (flush _test-error-buffered-file)
     8143 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
     8149     # check output
     8150     (check-stream-equal _test-output-stream  ""  "F - test-copy-from-non-scalar-inout: output should be empty")
     8151     (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")
     8152     # check that stop(1) was called
     8153     (check-ints-equal *(edx+4) 2 "F - test-copy-from-non-scalar-inout: exit status")
     8154     # don't restore from ebp
     8155     81 0/subop/add %esp 8/imm32
     8156     # . epilogue
     8157     5d/pop-to-ebp
     8158     c3/return
     8159
     8160 test-copy-to-with-no-inout:
     8161     # . prologue
     8162     55/push-ebp
     8163     89/<- %ebp 4/r32/esp
     8164     # setup
     8165     (clear-stream _test-input-stream)
     8166     (clear-stream $_test-input-buffered-file->buffer)
     8167     (clear-stream _test-output-stream)
     8168     (clear-stream $_test-output-buffered-file->buffer)
     8169     (clear-stream _test-error-stream)
     8170     (clear-stream $_test-error-buffered-file->buffer)
     8171     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     8172     68/push 0/imm32
     8173     68/push 0/imm32
     8174     89/<- %edx 4/r32/esp
     8175     (tailor-exit-descriptor %edx 0x10)
     8176     #
     8177     (write _test-input-stream "fn foo {\n")
     8178     (write _test-input-stream "  copy-to\n")
     8179     (write _test-input-stream "}\n")
     8180     # convert
     8181     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     8182     # registers except esp clobbered at this point
     8183     # restore ed
     8184     89/<- %edx 4/r32/esp
     8185     (flush _test-output-buffered-file)
     8186     (flush _test-error-buffered-file)
     8187 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
     8193     # check output
     8194     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-with-no-inout: output should be empty")
     8195     (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")
     8196     # check that stop(1) was called
     8197     (check-ints-equal *(edx+4) 2 "F - test-copy-to-with-no-inout: exit status")
     8198     # don't restore from ebp
     8199     81 0/subop/add %esp 8/imm32
     8200     # . epilogue
     8201     5d/pop-to-ebp
     8202     c3/return
     8203
     8204 test-copy-to-with-no-source:
     8205     # . prologue
     8206     55/push-ebp
     8207     89/<- %ebp 4/r32/esp
     8208     # setup
     8209     (clear-stream _test-input-stream)
     8210     (clear-stream $_test-input-buffered-file->buffer)
     8211     (clear-stream _test-output-stream)
     8212     (clear-stream $_test-output-buffered-file->buffer)
     8213     (clear-stream _test-error-stream)
     8214     (clear-stream $_test-error-buffered-file->buffer)
     8215     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     8216     68/push 0/imm32
     8217     68/push 0/imm32
     8218     89/<- %edx 4/r32/esp
     8219     (tailor-exit-descriptor %edx 0x10)
     8220     #
     8221     (write _test-input-stream "fn foo {\n")
     8222     (write _test-input-stream "  var x: boolean\n")
     8223     (write _test-input-stream "  copy-to x\n")
     8224     (write _test-input-stream "}\n")
     8225     # convert
     8226     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     8227     # registers except esp clobbered at this point
     8228     # restore ed
     8229     89/<- %edx 4/r32/esp
     8230     (flush _test-output-buffered-file)
     8231     (flush _test-error-buffered-file)
     8232 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
     8238     # check output
     8239     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-with-no-source: output should be empty")
     8240     (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")
     8241     # check that stop(1) was called
     8242     (check-ints-equal *(edx+4) 2 "F - test-copy-to-with-no-source: exit status")
     8243     # don't restore from ebp
     8244     81 0/subop/add %esp 8/imm32
     8245     # . epilogue
     8246     5d/pop-to-ebp
     8247     c3/return
     8248
     8249 test-copy-to-with-no-register:
     8250     # . prologue
     8251     55/push-ebp
     8252     89/<- %ebp 4/r32/esp
     8253     # setup
     8254     (clear-stream _test-input-stream)
     8255     (clear-stream $_test-input-buffered-file->buffer)
     8256     (clear-stream _test-output-stream)
     8257     (clear-stream $_test-output-buffered-file->buffer)
     8258     (clear-stream _test-error-stream)
     8259     (clear-stream $_test-error-buffered-file->buffer)
     8260     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     8261     68/push 0/imm32
     8262     68/push 0/imm32
     8263     89/<- %edx 4/r32/esp
     8264     (tailor-exit-descriptor %edx 0x10)
     8265     #
     8266     (write _test-input-stream "fn foo {\n")
     8267     (write _test-input-stream "  var x: boolean\n")
     8268     (write _test-input-stream "  copy-to x, x\n")
     8269     (write _test-input-stream "}\n")
     8270     # convert
     8271     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     8272     # registers except esp clobbered at this point
     8273     # restore ed
     8274     89/<- %edx 4/r32/esp
     8275     (flush _test-output-buffered-file)
     8276     (flush _test-error-buffered-file)
     8277 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
     8283     # check output
     8284     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-with-no-register: output should be empty")
     8285     (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")
     8286     # check that stop(1) was called
     8287     (check-ints-equal *(edx+4) 2 "F - test-copy-to-with-no-register: exit status")
     8288     # don't restore from ebp
     8289     81 0/subop/add %esp 8/imm32
     8290     # . epilogue
     8291     5d/pop-to-ebp
     8292     c3/return
     8293
     8294 test-copy-to-with-too-many-inouts:
     8295     # . prologue
     8296     55/push-ebp
     8297     89/<- %ebp 4/r32/esp
     8298     # setup
     8299     (clear-stream _test-input-stream)
     8300     (clear-stream $_test-input-buffered-file->buffer)
     8301     (clear-stream _test-output-stream)
     8302     (clear-stream $_test-output-buffered-file->buffer)
     8303     (clear-stream _test-error-stream)
     8304     (clear-stream $_test-error-buffered-file->buffer)
     8305     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     8306     68/push 0/imm32
     8307     68/push 0/imm32
     8308     89/<- %edx 4/r32/esp
     8309     (tailor-exit-descriptor %edx 0x10)
     8310     #
     8311     (write _test-input-stream "fn foo {\n")
     8312     (write _test-input-stream "  var x: boolean\n")
     8313     (write _test-input-stream "  copy-to x, 0, 0\n")
     8314     (write _test-input-stream "}\n")
     8315     # convert
     8316     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     8317     # registers except esp clobbered at this point
     8318     # restore ed
     8319     89/<- %edx 4/r32/esp
     8320     (flush _test-output-buffered-file)
     8321     (flush _test-error-buffered-file)
     8322 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
     8328     # check output
     8329     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-with-too-many-inouts: output should be empty")
     8330     (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")
     8331     # check that stop(1) was called
     8332     (check-ints-equal *(edx+4) 2 "F - test-copy-to-with-too-many-inouts: exit status")
     8333     # don't restore from ebp
     8334     81 0/subop/add %esp 8/imm32
     8335     # . epilogue
     8336     5d/pop-to-ebp
     8337     c3/return
     8338
     8339 test-copy-to-with-output:
     8340     # . prologue
     8341     55/push-ebp
     8342     89/<- %ebp 4/r32/esp
     8343     # setup
     8344     (clear-stream _test-input-stream)
     8345     (clear-stream $_test-input-buffered-file->buffer)
     8346     (clear-stream _test-output-stream)
     8347     (clear-stream $_test-output-buffered-file->buffer)
     8348     (clear-stream _test-error-stream)
     8349     (clear-stream $_test-error-buffered-file->buffer)
     8350     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     8351     68/push 0/imm32
     8352     68/push 0/imm32
     8353     89/<- %edx 4/r32/esp
     8354     (tailor-exit-descriptor %edx 0x10)
     8355     #
     8356     (write _test-input-stream "fn foo {\n")
     8357     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
     8358     (write _test-input-stream "  var y/ecx: boolean <- copy 0\n")
     8359     (write _test-input-stream "  x <- copy-to y, 0\n")
     8360     (write _test-input-stream "}\n")
     8361     # convert
     8362     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     8363     # registers except esp clobbered at this point
     8364     # restore ed
     8365     89/<- %edx 4/r32/esp
     8366     (flush _test-output-buffered-file)
     8367     (flush _test-error-buffered-file)
     8368 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
     8374     # check output
     8375     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-with-output: output should be empty")
     8376     (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")
     8377     # check that stop(1) was called
     8378     (check-ints-equal *(edx+4) 2 "F - test-copy-to-with-output: exit status")
     8379     # don't restore from ebp
     8380     81 0/subop/add %esp 8/imm32
     8381     # . epilogue
     8382     5d/pop-to-ebp
     8383     c3/return
     8384
     8385 test-copy-to-invalid-value-to-address:
     8386     # . prologue
     8387     55/push-ebp
     8388     89/<- %ebp 4/r32/esp
     8389     # setup
     8390     (clear-stream _test-input-stream)
     8391     (clear-stream $_test-input-buffered-file->buffer)
     8392     (clear-stream _test-output-stream)
     8393     (clear-stream $_test-output-buffered-file->buffer)
     8394     (clear-stream _test-error-stream)
     8395     (clear-stream $_test-error-buffered-file->buffer)
     8396     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     8397     68/push 0/imm32
     8398     68/push 0/imm32
     8399     89/<- %edx 4/r32/esp
     8400     (tailor-exit-descriptor %edx 0x10)
     8401     #
     8402     (write _test-input-stream "fn foo {\n")
     8403     (write _test-input-stream "  var x/eax: int <- copy 0\n")
     8404     (write _test-input-stream "  var y: (addr int)\n")
     8405     (write _test-input-stream "  copy-to y, x\n")
     8406     (write _test-input-stream "}\n")
     8407     # convert
     8408     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     8409     # registers except esp clobbered at this point
     8410     # restore ed
     8411     89/<- %edx 4/r32/esp
     8412     (flush _test-output-buffered-file)
     8413     (flush _test-error-buffered-file)
     8414 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
     8420     # check output
     8421     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-invalid-value-to-address: output should be empty")
     8422     (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")
     8423     # check that stop(1) was called
     8424     (check-ints-equal *(edx+4) 2 "F - test-copy-to-invalid-value-to-address: exit status")
     8425     # don't restore from ebp
     8426     81 0/subop/add %esp 8/imm32
     8427     # . epilogue
     8428     5d/pop-to-ebp
     8429     c3/return
     8430
     8431 test-copy-to-null-value-to-address:
     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     #
     8441     (write _test-input-stream "fn foo {\n")
     8442     (write _test-input-stream "  var y: (addr int)\n")
     8443     (write _test-input-stream "  copy-to y, 0\n")
     8444     (write _test-input-stream "}\n")
     8445     # convert
     8446     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     8447     (flush _test-output-buffered-file)
     8448     # no errors
     8449     # . epilogue
     8450     89/<- %esp 5/r32/ebp
     8451     5d/pop-to-ebp
     8452     c3/return
     8453
     8454 test-copy-to-invalid-value-to-offset:
     8455     # . prologue
     8456     55/push-ebp
     8457     89/<- %ebp 4/r32/esp
     8458     # setup
     8459     (clear-stream _test-input-stream)
     8460     (clear-stream $_test-input-buffered-file->buffer)
     8461     (clear-stream _test-output-stream)
     8462     (clear-stream $_test-output-buffered-file->buffer)
     8463     (clear-stream _test-error-stream)
     8464     (clear-stream $_test-error-buffered-file->buffer)
     8465     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     8466     68/push 0/imm32
     8467     68/push 0/imm32
     8468     89/<- %edx 4/r32/esp
     8469     (tailor-exit-descriptor %edx 0x10)
     8470     #
     8471     (write _test-input-stream "fn foo {\n")
     8472     (write _test-input-stream "  var x/eax: int <- copy 0\n")
     8473     (write _test-input-stream "  var y: (offset int)\n")
     8474     (write _test-input-stream "  copy-to y, x\n")
     8475     (write _test-input-stream "}\n")
     8476     # convert
     8477     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     8478     # registers except esp clobbered at this point
     8479     # restore ed
     8480     89/<- %edx 4/r32/esp
     8481     (flush _test-output-buffered-file)
     8482     (flush _test-error-buffered-file)
     8483 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
     8489     # check output
     8490     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-invalid-value-to-offset: output should be empty")
     8491     (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")
     8492     # check that stop(1) was called
     8493     (check-ints-equal *(edx+4) 2 "F - test-copy-to-invalid-value-to-offset: exit status")
     8494     # don't restore from ebp
     8495     81 0/subop/add %esp 8/imm32
     8496     # . epilogue
     8497     5d/pop-to-ebp
     8498     c3/return
     8499
     8500 test-copy-to-null-value-to-offset:
     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     #
     8510     (write _test-input-stream "fn foo {\n")
     8511     (write _test-input-stream "  var y: (offset int)\n")
     8512     (write _test-input-stream "  copy-to y, 0\n")
     8513     (write _test-input-stream "}\n")
     8514     # convert
     8515     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     8516     (flush _test-output-buffered-file)
     8517     # no errors
     8518     # . epilogue
     8519     89/<- %esp 5/r32/ebp
     8520     5d/pop-to-ebp
     8521     c3/return
     8522
     8523 test-copy-to-non-literal-to-byte:
     8524     # . prologue
     8525     55/push-ebp
     8526     89/<- %ebp 4/r32/esp
     8527     # setup
     8528     (clear-stream _test-input-stream)
     8529     (clear-stream $_test-input-buffered-file->buffer)
     8530     (clear-stream _test-output-stream)
     8531     (clear-stream $_test-output-buffered-file->buffer)
     8532     (clear-stream _test-error-stream)
     8533     (clear-stream $_test-error-buffered-file->buffer)
     8534     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     8535     68/push 0/imm32
     8536     68/push 0/imm32
     8537     89/<- %edx 4/r32/esp
     8538     (tailor-exit-descriptor %edx 0x10)
     8539     #
     8540     (write _test-input-stream "fn foo {\n")
     8541     (write _test-input-stream "  var x/ecx: byte <- copy 3\n")
     8542     (write _test-input-stream "  var y/eax: (addr byte) <- copy 0\n")
     8543     (write _test-input-stream "  copy-to *y, x\n")
     8544     (write _test-input-stream "}\n")
     8545     # convert
     8546     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     8547     # registers except esp clobbered at this point
     8548     # restore ed
     8549     89/<- %edx 4/r32/esp
     8550     (flush _test-output-buffered-file)
     8551     (flush _test-error-buffered-file)
     8552 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
     8558     # check output
     8559     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-non-literal-to-byte: output should be empty")
     8560     (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")
     8561     # check that stop(1) was called
     8562     (check-ints-equal *(edx+4) 2 "F - test-copy-to-non-literal-to-byte: exit status")
     8563     # don't restore from ebp
     8564     81 0/subop/add %esp 8/imm32
     8565     # . epilogue
     8566     5d/pop-to-ebp
     8567     c3/return
     8568
     8569 test-copy-to-deref-address:
     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     #
     8579     (write _test-input-stream "fn foo {\n")
     8580     (write _test-input-stream "  var x/eax: (addr int) <- copy 0\n")
     8581     (write _test-input-stream "  var y/ecx: (addr addr int) <- copy 0\n")
     8582     (write _test-input-stream "  copy-to *y, x\n")
     8583     (write _test-input-stream "}\n")
     8584     # convert
     8585     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     8586     (flush _test-output-buffered-file)
     8587     # no errors
     8588     # . epilogue
     8589     5d/pop-to-ebp
     8590     c3/return
     8591
     8592 test-copy-to-from-non-scalar-inout:
     8593     # . prologue
     8594     55/push-ebp
     8595     89/<- %ebp 4/r32/esp
     8596     # setup
     8597     (clear-stream _test-input-stream)
     8598     (clear-stream $_test-input-buffered-file->buffer)
     8599     (clear-stream _test-output-stream)
     8600     (clear-stream $_test-output-buffered-file->buffer)
     8601     (clear-stream _test-error-stream)
     8602     (clear-stream $_test-error-buffered-file->buffer)
     8603     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     8604     68/push 0/imm32
     8605     68/push 0/imm32
     8606     89/<- %edx 4/r32/esp
     8607     (tailor-exit-descriptor %edx 0x10)
     8608     #
     8609     (write _test-input-stream "fn foo {\n")
     8610     (write _test-input-stream "  var x: (handle int)\n")
     8611     (write _test-input-stream "  var y: int\n")
     8612     (write _test-input-stream "  copy-to y, x\n")
     8613     (write _test-input-stream "}\n")
     8614     # convert
     8615     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     8616     # registers except esp clobbered at this point
     8617     # restore ed
     8618     89/<- %edx 4/r32/esp
     8619     (flush _test-output-buffered-file)
     8620     (flush _test-error-buffered-file)
     8621 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
     8627     # check output
     8628     (check-stream-equal _test-output-stream  ""  "F - test-copy-to-from-non-scalar-inout: output should be empty")
     8629     (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")
     8630     # check that stop(1) was called
     8631     (check-ints-equal *(edx+4) 2 "F - test-copy-to-from-non-scalar-inout: exit status")
     8632     # don't restore from ebp
     8633     81 0/subop/add %esp 8/imm32
     8634     # . epilogue
     8635     5d/pop-to-ebp
     8636     c3/return
     8637
     8638 test-copy-byte-with-no-inout:
     8639     # . prologue
     8640     55/push-ebp
     8641     89/<- %ebp 4/r32/esp
     8642     # setup
     8643     (clear-stream _test-input-stream)
     8644     (clear-stream $_test-input-buffered-file->buffer)
     8645     (clear-stream _test-output-stream)
     8646     (clear-stream $_test-output-buffered-file->buffer)
     8647     (clear-stream _test-error-stream)
     8648     (clear-stream $_test-error-buffered-file->buffer)
     8649     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     8650     68/push 0/imm32
     8651     68/push 0/imm32
     8652     89/<- %edx 4/r32/esp
     8653     (tailor-exit-descriptor %edx 0x10)
     8654     #
     8655     (write _test-input-stream "fn foo {\n")
     8656     (write _test-input-stream "  var x/eax: byte <- copy-byte\n")
     8657     (write _test-input-stream "}\n")
     8658     # convert
     8659     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     8660     # registers except esp clobbered at this point
     8661     # restore ed
     8662     89/<- %edx 4/r32/esp
     8663     (flush _test-output-buffered-file)
     8664     (flush _test-error-buffered-file)
     8665 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
     8671     # check output
     8672     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-with-no-inout: output should be empty")
     8673     (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")
     8674     # check that stop(1) was called
     8675     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-with-no-inout: exit status")
     8676     # don't restore from ebp
     8677     81 0/subop/add %esp 8/imm32
     8678     # . epilogue
     8679     5d/pop-to-ebp
     8680     c3/return
     8681
     8682 test-copy-byte-with-multiple-inouts:
     8683     # . prologue
     8684     55/push-ebp
     8685     89/<- %ebp 4/r32/esp
     8686     # setup
     8687     (clear-stream _test-input-stream)
     8688     (clear-stream $_test-input-buffered-file->buffer)
     8689     (clear-stream _test-output-stream)
     8690     (clear-stream $_test-output-buffered-file->buffer)
     8691     (clear-stream _test-error-stream)
     8692     (clear-stream $_test-error-buffered-file->buffer)
     8693     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     8694     68/push 0/imm32
     8695     68/push 0/imm32
     8696     89/<- %edx 4/r32/esp
     8697     (tailor-exit-descriptor %edx 0x10)
     8698     #
     8699     (write _test-input-stream "fn foo {\n")
     8700     (write _test-input-stream "  var x/eax: byte <- copy-byte 0, 0\n")
     8701     (write _test-input-stream "}\n")
     8702     # convert
     8703     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     8704     # registers except esp clobbered at this point
     8705     # restore ed
     8706     89/<- %edx 4/r32/esp
     8707     (flush _test-output-buffered-file)
     8708     (flush _test-error-buffered-file)
     8709 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
     8715     # check output
     8716     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-with-multiple-inouts: output should be empty")
     8717     (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")
     8718     # check that stop(1) was called
     8719     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-with-multiple-inouts: exit status")
     8720     # don't restore from ebp
     8721     81 0/subop/add %esp 8/imm32
     8722     # . epilogue
     8723     5d/pop-to-ebp
     8724     c3/return
     8725
     8726 test-copy-byte-with-no-output:
     8727     # . prologue
     8728     55/push-ebp
     8729     89/<- %ebp 4/r32/esp
     8730     # setup
     8731     (clear-stream _test-input-stream)
     8732     (clear-stream $_test-input-buffered-file->buffer)
     8733     (clear-stream _test-output-stream)
     8734     (clear-stream $_test-output-buffered-file->buffer)
     8735     (clear-stream _test-error-stream)
     8736     (clear-stream $_test-error-buffered-file->buffer)
     8737     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     8738     68/push 0/imm32
     8739     68/push 0/imm32
     8740     89/<- %edx 4/r32/esp
     8741     (tailor-exit-descriptor %edx 0x10)
     8742     #
     8743     (write _test-input-stream "fn foo {\n")
     8744     (write _test-input-stream "  copy-byte 0\n")
     8745     (write _test-input-stream "}\n")
     8746     # convert
     8747     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     8748     # registers except esp clobbered at this point
     8749     # restore ed
     8750     89/<- %edx 4/r32/esp
     8751     (flush _test-output-buffered-file)
     8752     (flush _test-error-buffered-file)
     8753 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
     8759     # check output
     8760     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-with-no-output: output should be empty")
     8761     (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")
     8762     # check that stop(1) was called
     8763     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-with-no-output: exit status")
     8764     # don't restore from ebp
     8765     81 0/subop/add %esp 8/imm32
     8766     # . epilogue
     8767     5d/pop-to-ebp
     8768     c3/return
     8769
     8770 test-copy-byte-with-multiple-outputs:
     8771     # . prologue
     8772     55/push-ebp
     8773     89/<- %ebp 4/r32/esp
     8774     # setup
     8775     (clear-stream _test-input-stream)
     8776     (clear-stream $_test-input-buffered-file->buffer)
     8777     (clear-stream _test-output-stream)
     8778     (clear-stream $_test-output-buffered-file->buffer)
     8779     (clear-stream _test-error-stream)
     8780     (clear-stream $_test-error-buffered-file->buffer)
     8781     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     8782     68/push 0/imm32
     8783     68/push 0/imm32
     8784     89/<- %edx 4/r32/esp
     8785     (tailor-exit-descriptor %edx 0x10)
     8786     #
     8787     (write _test-input-stream "fn foo {\n")
     8788     (write _test-input-stream "  var x/eax: byte <- copy 0\n")
     8789     (write _test-input-stream "  var y/ecx: byte <- copy 0\n")
     8790     (write _test-input-stream "  x, y <- copy-byte 0\n")
     8791     (write _test-input-stream "}\n")
     8792     # convert
     8793     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     8794     # registers except esp clobbered at this point
     8795     # restore ed
     8796     89/<- %edx 4/r32/esp
     8797     (flush _test-output-buffered-file)
     8798     (flush _test-error-buffered-file)
     8799 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
     8805     # check output
     8806     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-with-multiple-outputs: output should be empty")
     8807     (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")
     8808     # check that stop(1) was called
     8809     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-with-multiple-outputs: exit status")
     8810     # don't restore from ebp
     8811     81 0/subop/add %esp 8/imm32
     8812     # . epilogue
     8813     5d/pop-to-ebp
     8814     c3/return
     8815
     8816 test-copy-byte-deref-address:
     8817     # . prologue
     8818     55/push-ebp
     8819     89/<- %ebp 4/r32/esp
     8820     # setup
     8821     (clear-stream _test-input-stream)
     8822     (clear-stream $_test-input-buffered-file->buffer)
     8823     (clear-stream _test-output-stream)
     8824     (clear-stream $_test-output-buffered-file->buffer)
     8825     #
     8826     (write _test-input-stream "fn foo {\n")
     8827     (write _test-input-stream "  var x/eax: (addr byte) <- copy 0\n")
     8828     (write _test-input-stream "  var y/ecx: byte <- copy-byte *x\n")
     8829     (write _test-input-stream "}\n")
     8830     # convert
     8831     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     8832     (flush _test-output-buffered-file)
     8833 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
     8839     # not bothering checking output
     8840     (check-next-stream-line-equal _test-error-stream  ""  "F - test-copy-byte-deref-address: error message")
     8841     # . epilogue
     8842     5d/pop-to-ebp
     8843     c3/return
     8844
     8845 test-copy-byte-with-invalid-output-type:
     8846     # . prologue
     8847     55/push-ebp
     8848     89/<- %ebp 4/r32/esp
     8849     # setup
     8850     (clear-stream _test-input-stream)
     8851     (clear-stream $_test-input-buffered-file->buffer)
     8852     (clear-stream _test-output-stream)
     8853     (clear-stream $_test-output-buffered-file->buffer)
     8854     (clear-stream _test-error-stream)
     8855     (clear-stream $_test-error-buffered-file->buffer)
     8856     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     8857     68/push 0/imm32
     8858     68/push 0/imm32
     8859     89/<- %edx 4/r32/esp
     8860     (tailor-exit-descriptor %edx 0x10)
     8861     #
     8862     (write _test-input-stream "fn foo {\n")
     8863     (write _test-input-stream "  var x/eax: (addr byte) <- copy 0\n")
     8864     (write _test-input-stream "  var y/eax: int <- copy-byte *x\n")
     8865     (write _test-input-stream "}\n")
     8866     # convert
     8867     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     8868     # registers except esp clobbered at this point
     8869     # restore ed
     8870     89/<- %edx 4/r32/esp
     8871     (flush _test-output-buffered-file)
     8872     (flush _test-error-buffered-file)
     8873 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
     8879     # check output
     8880     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-with-invalid-output-type: output should be empty")
     8881     (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")
     8882     # check that stop(1) was called
     8883     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-with-invalid-output-type: exit status")
     8884     # don't restore from ebp
     8885     81 0/subop/add %esp 8/imm32
     8886     # . epilogue
     8887     5d/pop-to-ebp
     8888     c3/return
     8889
     8890 test-copy-byte-from-non-scalar-inout:
     8891     # . prologue
     8892     55/push-ebp
     8893     89/<- %ebp 4/r32/esp
     8894     # setup
     8895     (clear-stream _test-input-stream)
     8896     (clear-stream $_test-input-buffered-file->buffer)
     8897     (clear-stream _test-output-stream)
     8898     (clear-stream $_test-output-buffered-file->buffer)
     8899     (clear-stream _test-error-stream)
     8900     (clear-stream $_test-error-buffered-file->buffer)
     8901     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     8902     68/push 0/imm32
     8903     68/push 0/imm32
     8904     89/<- %edx 4/r32/esp
     8905     (tailor-exit-descriptor %edx 0x10)
     8906     #
     8907     (write _test-input-stream "fn foo {\n")
     8908     (write _test-input-stream "  var x: (handle int)\n")
     8909     (write _test-input-stream "  var y/eax: byte <- copy-byte x\n")
     8910     (write _test-input-stream "}\n")
     8911     # convert
     8912     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     8913     # registers except esp clobbered at this point
     8914     # restore ed
     8915     89/<- %edx 4/r32/esp
     8916     (flush _test-output-buffered-file)
     8917     (flush _test-error-buffered-file)
     8918 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
     8924     # check output
     8925     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-from-non-scalar-inout: output should be empty")
     8926     (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")
     8927     # check that stop(1) was called
     8928     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-from-non-scalar-inout: exit status")
     8929     # don't restore from ebp
     8930     81 0/subop/add %esp 8/imm32
     8931     # . epilogue
     8932     5d/pop-to-ebp
     8933     c3/return
     8934
     8935 test-copy-byte-to-with-no-inout:
     8936     # . prologue
     8937     55/push-ebp
     8938     89/<- %ebp 4/r32/esp
     8939     # setup
     8940     (clear-stream _test-input-stream)
     8941     (clear-stream $_test-input-buffered-file->buffer)
     8942     (clear-stream _test-output-stream)
     8943     (clear-stream $_test-output-buffered-file->buffer)
     8944     (clear-stream _test-error-stream)
     8945     (clear-stream $_test-error-buffered-file->buffer)
     8946     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     8947     68/push 0/imm32
     8948     68/push 0/imm32
     8949     89/<- %edx 4/r32/esp
     8950     (tailor-exit-descriptor %edx 0x10)
     8951     #
     8952     (write _test-input-stream "fn foo {\n")
     8953     (write _test-input-stream "  copy-byte-to\n")
     8954     (write _test-input-stream "}\n")
     8955     # convert
     8956     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     8957     # registers except esp clobbered at this point
     8958     # restore ed
     8959     89/<- %edx 4/r32/esp
     8960     (flush _test-output-buffered-file)
     8961     (flush _test-error-buffered-file)
     8962 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
     8968     # check output
     8969     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-to-with-no-inout: output should be empty")
     8970     (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")
     8971     # check that stop(1) was called
     8972     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-to-with-no-inout: exit status")
     8973     # don't restore from ebp
     8974     81 0/subop/add %esp 8/imm32
     8975     # . epilogue
     8976     5d/pop-to-ebp
     8977     c3/return
     8978
     8979 test-copy-byte-to-with-no-source:
     8980     # . prologue
     8981     55/push-ebp
     8982     89/<- %ebp 4/r32/esp
     8983     # setup
     8984     (clear-stream _test-input-stream)
     8985     (clear-stream $_test-input-buffered-file->buffer)
     8986     (clear-stream _test-output-stream)
     8987     (clear-stream $_test-output-buffered-file->buffer)
     8988     (clear-stream _test-error-stream)
     8989     (clear-stream $_test-error-buffered-file->buffer)
     8990     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     8991     68/push 0/imm32
     8992     68/push 0/imm32
     8993     89/<- %edx 4/r32/esp
     8994     (tailor-exit-descriptor %edx 0x10)
     8995     #
     8996     (write _test-input-stream "fn foo {\n")
     8997     (write _test-input-stream "  var x/eax: (addr byte) <- copy 0\n")
     8998     (write _test-input-stream "  copy-byte-to *x\n")
     8999     (write _test-input-stream "}\n")
     9000     # convert
     9001     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     9002     # registers except esp clobbered at this point
     9003     # restore ed
     9004     89/<- %edx 4/r32/esp
     9005     (flush _test-output-buffered-file)
     9006     (flush _test-error-buffered-file)
     9007 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
     9013     # check output
     9014     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-to-with-no-source: output should be empty")
     9015     (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")
     9016     # check that stop(1) was called
     9017     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-to-with-no-source: exit status")
     9018     # don't restore from ebp
     9019     81 0/subop/add %esp 8/imm32
     9020     # . epilogue
     9021     5d/pop-to-ebp
     9022     c3/return
     9023
     9024 test-copy-byte-to-with-too-many-inouts:
     9025     # . prologue
     9026     55/push-ebp
     9027     89/<- %ebp 4/r32/esp
     9028     # setup
     9029     (clear-stream _test-input-stream)
     9030     (clear-stream $_test-input-buffered-file->buffer)
     9031     (clear-stream _test-output-stream)
     9032     (clear-stream $_test-output-buffered-file->buffer)
     9033     (clear-stream _test-error-stream)
     9034     (clear-stream $_test-error-buffered-file->buffer)
     9035     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     9036     68/push 0/imm32
     9037     68/push 0/imm32
     9038     89/<- %edx 4/r32/esp
     9039     (tailor-exit-descriptor %edx 0x10)
     9040     #
     9041     (write _test-input-stream "fn foo {\n")
     9042     (write _test-input-stream "  var x/eax: (addr byte) <- copy 0\n")
     9043     (write _test-input-stream "  copy-byte-to *x, 0, 0\n")
     9044     (write _test-input-stream "}\n")
     9045     # convert
     9046     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     9047     # registers except esp clobbered at this point
     9048     # restore ed
     9049     89/<- %edx 4/r32/esp
     9050     (flush _test-output-buffered-file)
     9051     (flush _test-error-buffered-file)
     9052 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
     9058     # check output
     9059     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-to-with-too-many-inouts: output should be empty")
     9060     (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")
     9061     # check that stop(1) was called
     9062     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-to-with-too-many-inouts: exit status")
     9063     # don't restore from ebp
     9064     81 0/subop/add %esp 8/imm32
     9065     # . epilogue
     9066     5d/pop-to-ebp
     9067     c3/return
     9068
     9069 test-copy-byte-to-with-output:
     9070     # . prologue
     9071     55/push-ebp
     9072     89/<- %ebp 4/r32/esp
     9073     # setup
     9074     (clear-stream _test-input-stream)
     9075     (clear-stream $_test-input-buffered-file->buffer)
     9076     (clear-stream _test-output-stream)
     9077     (clear-stream $_test-output-buffered-file->buffer)
     9078     (clear-stream _test-error-stream)
     9079     (clear-stream $_test-error-buffered-file->buffer)
     9080     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     9081     68/push 0/imm32
     9082     68/push 0/imm32
     9083     89/<- %edx 4/r32/esp
     9084     (tailor-exit-descriptor %edx 0x10)
     9085     #
     9086     (write _test-input-stream "fn foo {\n")
     9087     (write _test-input-stream "  var x/eax: byte <- copy 0\n")
     9088     (write _test-input-stream "  var y/ecx: (addr byte) <- copy 0\n")
     9089     (write _test-input-stream "  x <- copy-byte-to *y, 0\n")
     9090     (write _test-input-stream "}\n")
     9091     # convert
     9092     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     9093     # registers except esp clobbered at this point
     9094     # restore ed
     9095     89/<- %edx 4/r32/esp
     9096     (flush _test-output-buffered-file)
     9097     (flush _test-error-buffered-file)
     9098 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
     9104     # check output
     9105     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-to-with-output: output should be empty")
     9106     (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")
     9107     # check that stop(1) was called
     9108     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-to-with-output: exit status")
     9109     # don't restore from ebp
     9110     81 0/subop/add %esp 8/imm32
     9111     # . epilogue
     9112     5d/pop-to-ebp
     9113     c3/return
     9114
     9115 test-copy-byte-to-with-invalid-output-type:
     9116     # . prologue
     9117     55/push-ebp
     9118     89/<- %ebp 4/r32/esp
     9119     # setup
     9120     (clear-stream _test-input-stream)
     9121     (clear-stream $_test-input-buffered-file->buffer)
     9122     (clear-stream _test-output-stream)
     9123     (clear-stream $_test-output-buffered-file->buffer)
     9124     (clear-stream _test-error-stream)
     9125     (clear-stream $_test-error-buffered-file->buffer)
     9126     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     9127     68/push 0/imm32
     9128     68/push 0/imm32
     9129     89/<- %edx 4/r32/esp
     9130     (tailor-exit-descriptor %edx 0x10)
     9131     #
     9132     (write _test-input-stream "fn foo {\n")
     9133     (write _test-input-stream "  var x/eax: byte <- copy 0\n")
     9134     (write _test-input-stream "  var y: int\n")
     9135     (write _test-input-stream "  copy-byte-to y, x\n")
     9136     (write _test-input-stream "}\n")
     9137     # convert
     9138     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     9139     # registers except esp clobbered at this point
     9140     # restore ed
     9141     89/<- %edx 4/r32/esp
     9142     (flush _test-output-buffered-file)
     9143     (flush _test-error-buffered-file)
     9144 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
     9150     # check output
     9151     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-to-with-invalid-output-type: output should be empty")
     9152     (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")
     9153     # check that stop(1) was called
     9154     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-to-with-invalid-output-type: exit status")
     9155     # don't restore from ebp
     9156     81 0/subop/add %esp 8/imm32
     9157     # . epilogue
     9158     5d/pop-to-ebp
     9159     c3/return
     9160
     9161 test-copy-byte-to-with-literal-inout:
     9162     # . prologue
     9163     55/push-ebp
     9164     89/<- %ebp 4/r32/esp
     9165     # setup
     9166     (clear-stream _test-input-stream)
     9167     (clear-stream $_test-input-buffered-file->buffer)
     9168     (clear-stream _test-output-stream)
     9169     (clear-stream $_test-output-buffered-file->buffer)
     9170     (clear-stream _test-error-stream)
     9171     (clear-stream $_test-error-buffered-file->buffer)
     9172     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     9173     68/push 0/imm32
     9174     68/push 0/imm32
     9175     89/<- %edx 4/r32/esp
     9176     (tailor-exit-descriptor %edx 0x10)
     9177     #
     9178     (write _test-input-stream "fn foo {\n")
     9179     (write _test-input-stream "  var x/eax: (addr byte) <- copy 0\n")
     9180     (write _test-input-stream "  copy-byte-to *x, 0\n")
     9181     (write _test-input-stream "}\n")
     9182     # convert
     9183     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     9184     # registers except esp clobbered at this point
     9185     # restore ed
     9186     89/<- %edx 4/r32/esp
     9187     (flush _test-output-buffered-file)
     9188     (flush _test-error-buffered-file)
     9189 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
     9195     # check output
     9196     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-to-with-literal-inout: output should be empty")
     9197     (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")
     9198     # check that stop(1) was called
     9199     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-to-with-literal-inout: exit status")
     9200     # don't restore from ebp
     9201     81 0/subop/add %esp 8/imm32
     9202     # . epilogue
     9203     5d/pop-to-ebp
     9204     c3/return
     9205
     9206 test-copy-byte-to-deref-address:
     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     #
     9216     (write _test-input-stream "fn foo {\n")
     9217     (write _test-input-stream "  var x/eax: byte <- copy 0\n")
     9218     (write _test-input-stream "  var y/ecx: (addr byte) <- copy 0\n")
     9219     (write _test-input-stream "  copy-byte-to *y, x\n")
     9220     (write _test-input-stream "}\n")
     9221     # convert
     9222     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     9223     (flush _test-output-buffered-file)
     9224     # no errors
     9225     # . epilogue
     9226     5d/pop-to-ebp
     9227     c3/return
     9228
     9229 test-copy-byte-to-from-non-scalar-inout:
     9230     # . prologue
     9231     55/push-ebp
     9232     89/<- %ebp 4/r32/esp
     9233     # setup
     9234     (clear-stream _test-input-stream)
     9235     (clear-stream $_test-input-buffered-file->buffer)
     9236     (clear-stream _test-output-stream)
     9237     (clear-stream $_test-output-buffered-file->buffer)
     9238     (clear-stream _test-error-stream)
     9239     (clear-stream $_test-error-buffered-file->buffer)
     9240     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     9241     68/push 0/imm32
     9242     68/push 0/imm32
     9243     89/<- %edx 4/r32/esp
     9244     (tailor-exit-descriptor %edx 0x10)
     9245     #
     9246     (write _test-input-stream "fn foo {\n")
     9247     (write _test-input-stream "  var x: (handle int)\n")
     9248     (write _test-input-stream "  var y/eax: (addr byte) <- copy 0\n")
     9249     (write _test-input-stream "  copy-byte-to *y, x\n")
     9250     (write _test-input-stream "}\n")
     9251     # convert
     9252     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     9253     # registers except esp clobbered at this point
     9254     # restore ed
     9255     89/<- %edx 4/r32/esp
     9256     (flush _test-output-buffered-file)
     9257     (flush _test-error-buffered-file)
     9258 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
     9264     # check output
     9265     (check-stream-equal _test-output-stream  ""  "F - test-copy-byte-to-from-non-scalar-inout: output should be empty")
     9266     (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")
     9267     # check that stop(1) was called
     9268     (check-ints-equal *(edx+4) 2 "F - test-copy-byte-to-from-non-scalar-inout: exit status")
     9269     # don't restore from ebp
     9270     81 0/subop/add %esp 8/imm32
     9271     # . epilogue
     9272     5d/pop-to-ebp
     9273     c3/return
     9274
     9275 test-compare-with-no-inout:
     9276     # . prologue
     9277     55/push-ebp
     9278     89/<- %ebp 4/r32/esp
     9279     # setup
     9280     (clear-stream _test-input-stream)
     9281     (clear-stream $_test-input-buffered-file->buffer)
     9282     (clear-stream _test-output-stream)
     9283     (clear-stream $_test-output-buffered-file->buffer)
     9284     (clear-stream _test-error-stream)
     9285     (clear-stream $_test-error-buffered-file->buffer)
     9286     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     9287     68/push 0/imm32
     9288     68/push 0/imm32
     9289     89/<- %edx 4/r32/esp
     9290     (tailor-exit-descriptor %edx 0x10)
     9291     #
     9292     (write _test-input-stream "fn foo {\n")
     9293     (write _test-input-stream "  var x: boolean\n")
     9294     (write _test-input-stream "  compare\n")
     9295     (write _test-input-stream "}\n")
     9296     # convert
     9297     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     9298     # registers except esp clobbered at this point
     9299     # restore ed
     9300     89/<- %edx 4/r32/esp
     9301     (flush _test-output-buffered-file)
     9302     (flush _test-error-buffered-file)
     9303 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
     9309     # check output
     9310     (check-stream-equal _test-output-stream  ""  "F - test-compare-with-no-inout: output should be empty")
     9311     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'compare' must have two inouts"  "F - test-compare-with-no-inout: error message")
     9312     # check that stop(1) was called
     9313     (check-ints-equal *(edx+4) 2 "F - test-compare-with-no-inout: exit status")
     9314     # don't restore from ebp
     9315     81 0/subop/add %esp 8/imm32
     9316     # . epilogue
     9317     5d/pop-to-ebp
     9318     c3/return
     9319
     9320 test-compare-with-just-one-inout:
     9321     # . prologue
     9322     55/push-ebp
     9323     89/<- %ebp 4/r32/esp
     9324     # setup
     9325     (clear-stream _test-input-stream)
     9326     (clear-stream $_test-input-buffered-file->buffer)
     9327     (clear-stream _test-output-stream)
     9328     (clear-stream $_test-output-buffered-file->buffer)
     9329     (clear-stream _test-error-stream)
     9330     (clear-stream $_test-error-buffered-file->buffer)
     9331     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     9332     68/push 0/imm32
     9333     68/push 0/imm32
     9334     89/<- %edx 4/r32/esp
     9335     (tailor-exit-descriptor %edx 0x10)
     9336     #
     9337     (write _test-input-stream "fn foo {\n")
     9338     (write _test-input-stream "  var x: boolean\n")
     9339     (write _test-input-stream "  compare x\n")
     9340     (write _test-input-stream "}\n")
     9341     # convert
     9342     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     9343     # registers except esp clobbered at this point
     9344     # restore ed
     9345     89/<- %edx 4/r32/esp
     9346     (flush _test-output-buffered-file)
     9347     (flush _test-error-buffered-file)
     9348 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
     9354     # check output
     9355     (check-stream-equal _test-output-stream  ""  "F - test-compare-with-just-one-inout: output should be empty")
     9356     (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")
     9357     # check that stop(1) was called
     9358     (check-ints-equal *(edx+4) 2 "F - test-compare-with-just-one-inout: exit status")
     9359     # don't restore from ebp
     9360     81 0/subop/add %esp 8/imm32
     9361     # . epilogue
     9362     5d/pop-to-ebp
     9363     c3/return
     9364
     9365 test-compare-with-too-many-inouts:
     9366     # . prologue
     9367     55/push-ebp
     9368     89/<- %ebp 4/r32/esp
     9369     # setup
     9370     (clear-stream _test-input-stream)
     9371     (clear-stream $_test-input-buffered-file->buffer)
     9372     (clear-stream _test-output-stream)
     9373     (clear-stream $_test-output-buffered-file->buffer)
     9374     (clear-stream _test-error-stream)
     9375     (clear-stream $_test-error-buffered-file->buffer)
     9376     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     9377     68/push 0/imm32
     9378     68/push 0/imm32
     9379     89/<- %edx 4/r32/esp
     9380     (tailor-exit-descriptor %edx 0x10)
     9381     #
     9382     (write _test-input-stream "fn foo {\n")
     9383     (write _test-input-stream "  var x: boolean\n")
     9384     (write _test-input-stream "  compare x, 0, 0\n")
     9385     (write _test-input-stream "}\n")
     9386     # convert
     9387     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     9388     # registers except esp clobbered at this point
     9389     # restore ed
     9390     89/<- %edx 4/r32/esp
     9391     (flush _test-output-buffered-file)
     9392     (flush _test-error-buffered-file)
     9393 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
     9399     # check output
     9400     (check-stream-equal _test-output-stream  ""  "F - test-compare-with-too-many-inouts: output should be empty")
     9401     (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")
     9402     # check that stop(1) was called
     9403     (check-ints-equal *(edx+4) 2 "F - test-compare-with-too-many-inouts: exit status")
     9404     # don't restore from ebp
     9405     81 0/subop/add %esp 8/imm32
     9406     # . epilogue
     9407     5d/pop-to-ebp
     9408     c3/return
     9409
     9410 test-compare-with-output:
     9411     # . prologue
     9412     55/push-ebp
     9413     89/<- %ebp 4/r32/esp
     9414     # setup
     9415     (clear-stream _test-input-stream)
     9416     (clear-stream $_test-input-buffered-file->buffer)
     9417     (clear-stream _test-output-stream)
     9418     (clear-stream $_test-output-buffered-file->buffer)
     9419     (clear-stream _test-error-stream)
     9420     (clear-stream $_test-error-buffered-file->buffer)
     9421     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     9422     68/push 0/imm32
     9423     68/push 0/imm32
     9424     89/<- %edx 4/r32/esp
     9425     (tailor-exit-descriptor %edx 0x10)
     9426     #
     9427     (write _test-input-stream "fn foo {\n")
     9428     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
     9429     (write _test-input-stream "  var y/ecx: boolean <- copy 0\n")
     9430     (write _test-input-stream "  x <- compare y, 0\n")
     9431     (write _test-input-stream "}\n")
     9432     # convert
     9433     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     9434     # registers except esp clobbered at this point
     9435     # restore ed
     9436     89/<- %edx 4/r32/esp
     9437     (flush _test-output-buffered-file)
     9438     (flush _test-error-buffered-file)
     9439 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
     9445     # check output
     9446     (check-stream-equal _test-output-stream  ""  "F - test-compare-with-output: output should be empty")
     9447     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'compare' must not have any outputs"  "F - test-compare-with-output: error message")
     9448     # check that stop(1) was called
     9449     (check-ints-equal *(edx+4) 2 "F - test-compare-with-output: exit status")
     9450     # don't restore from ebp
     9451     81 0/subop/add %esp 8/imm32
     9452     # . epilogue
     9453     5d/pop-to-ebp
     9454     c3/return
     9455
     9456 test-compare-invalid-value-to-address:
     9457     # . prologue
     9458     55/push-ebp
     9459     89/<- %ebp 4/r32/esp
     9460     # setup
     9461     (clear-stream _test-input-stream)
     9462     (clear-stream $_test-input-buffered-file->buffer)
     9463     (clear-stream _test-output-stream)
     9464     (clear-stream $_test-output-buffered-file->buffer)
     9465     (clear-stream _test-error-stream)
     9466     (clear-stream $_test-error-buffered-file->buffer)
     9467     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     9468     68/push 0/imm32
     9469     68/push 0/imm32
     9470     89/<- %edx 4/r32/esp
     9471     (tailor-exit-descriptor %edx 0x10)
     9472     #
     9473     (write _test-input-stream "fn foo {\n")
     9474     (write _test-input-stream "  var x/eax: int <- copy 0\n")
     9475     (write _test-input-stream "  var y: (addr int)\n")
     9476     (write _test-input-stream "  compare y, x\n")
     9477     (write _test-input-stream "}\n")
     9478     # convert
     9479     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     9480     # registers except esp clobbered at this point
     9481     # restore ed
     9482     89/<- %edx 4/r32/esp
     9483     (flush _test-output-buffered-file)
     9484     (flush _test-error-buffered-file)
     9485 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
     9491     # check output
     9492     (check-stream-equal _test-output-stream  ""  "F - test-compare-invalid-value-to-address: output should be empty")
     9493     (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")
     9494     # check that stop(1) was called
     9495     (check-ints-equal *(edx+4) 2 "F - test-compare-invalid-value-to-address: exit status")
     9496     # don't restore from ebp
     9497     81 0/subop/add %esp 8/imm32
     9498     # . epilogue
     9499     5d/pop-to-ebp
     9500     c3/return
     9501
     9502 test-compare-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 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-deref-address:
     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     #
     9535     (write _test-input-stream "fn foo {\n")
     9536     (write _test-input-stream "  var x/eax: (addr int) <- copy 0\n")
     9537     (write _test-input-stream "  var y/ecx: (addr addr int) <- copy 0\n")
     9538     (write _test-input-stream "  compare *y, x\n")
     9539     (write _test-input-stream "}\n")
     9540     # convert
     9541     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     9542     (flush _test-output-buffered-file)
     9543     # no errors
     9544     # . epilogue
     9545     5d/pop-to-ebp
     9546     c3/return
     9547
     9548 test-compare-two-vars-in-memory:
     9549     # . prologue
     9550     55/push-ebp
     9551     89/<- %ebp 4/r32/esp
     9552     # setup
     9553     (clear-stream _test-input-stream)
     9554     (clear-stream $_test-input-buffered-file->buffer)
     9555     (clear-stream _test-output-stream)
     9556     (clear-stream $_test-output-buffered-file->buffer)
     9557     (clear-stream _test-error-stream)
     9558     (clear-stream $_test-error-buffered-file->buffer)
     9559     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     9560     68/push 0/imm32
     9561     68/push 0/imm32
     9562     89/<- %edx 4/r32/esp
     9563     (tailor-exit-descriptor %edx 0x10)
     9564     #
     9565     (write _test-input-stream "fn foo {\n")
     9566     (write _test-input-stream "  var x: boolean\n")
     9567     (write _test-input-stream "  compare x, x\n")
     9568     (write _test-input-stream "}\n")
     9569     # convert
     9570     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     9571     # registers except esp clobbered at this point
     9572     # restore ed
     9573     89/<- %edx 4/r32/esp
     9574     (flush _test-output-buffered-file)
     9575     (flush _test-error-buffered-file)
     9576 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
     9582     # check output
     9583     (check-stream-equal _test-output-stream  ""  "F - test-compare-two-vars-in-memory: output should be empty")
     9584     (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")
     9585     # check that stop(1) was called
     9586     (check-ints-equal *(edx+4) 2 "F - test-compare-two-vars-in-memory: exit status")
     9587     # don't restore from ebp
     9588     81 0/subop/add %esp 8/imm32
     9589     # . epilogue
     9590     5d/pop-to-ebp
     9591     c3/return
     9592
     9593 test-compare-non-scalar:
     9594     # . prologue
     9595     55/push-ebp
     9596     89/<- %ebp 4/r32/esp
     9597     # setup
     9598     (clear-stream _test-input-stream)
     9599     (clear-stream $_test-input-buffered-file->buffer)
     9600     (clear-stream _test-output-stream)
     9601     (clear-stream $_test-output-buffered-file->buffer)
     9602     (clear-stream _test-error-stream)
     9603     (clear-stream $_test-error-buffered-file->buffer)
     9604     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     9605     68/push 0/imm32
     9606     68/push 0/imm32
     9607     89/<- %edx 4/r32/esp
     9608     (tailor-exit-descriptor %edx 0x10)
     9609     #
     9610     (write _test-input-stream "fn foo {\n")
     9611     (write _test-input-stream "  var x: (handle int)\n")
     9612     (write _test-input-stream "  var y: int\n")
     9613     (write _test-input-stream "  compare y, x\n")
     9614     (write _test-input-stream "}\n")
     9615     # convert
     9616     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     9617     # registers except esp clobbered at this point
     9618     # restore ed
     9619     89/<- %edx 4/r32/esp
     9620     (flush _test-output-buffered-file)
     9621     (flush _test-error-buffered-file)
     9622 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
     9628     # check output
     9629     (check-stream-equal _test-output-stream  ""  "F - test-compare-non-scalar: output should be empty")
     9630 #?     (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")
     9631     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt compare: both inouts are in memory"  "F - test-compare-non-scalar: error message")
     9632     # check that stop(1) was called
     9633     (check-ints-equal *(edx+4) 2 "F - test-compare-non-scalar: exit status")
     9634     # don't restore from ebp
     9635     81 0/subop/add %esp 8/imm32
     9636     # . epilogue
     9637     5d/pop-to-ebp
     9638     c3/return
     9639
     9640 test-compare-with-string-literal:
     9641     # . prologue
     9642     55/push-ebp
     9643     89/<- %ebp 4/r32/esp
     9644     # setup
     9645     (clear-stream _test-input-stream)
     9646     (clear-stream $_test-input-buffered-file->buffer)
     9647     (clear-stream _test-output-stream)
     9648     (clear-stream $_test-output-buffered-file->buffer)
     9649     (clear-stream _test-error-stream)
     9650     (clear-stream $_test-error-buffered-file->buffer)
     9651     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     9652     68/push 0/imm32
     9653     68/push 0/imm32
     9654     89/<- %edx 4/r32/esp
     9655     (tailor-exit-descriptor %edx 0x10)
     9656     #
     9657     (write _test-input-stream "fn foo {\n")
     9658     (write _test-input-stream "  var x/eax: (addr array byte) <- copy 0\n")
     9659     (write _test-input-stream "  compare x, \"abc\"\n")
     9660     (write _test-input-stream "}\n")
     9661     # convert
     9662     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     9663     # registers except esp clobbered at this point
     9664     # restore ed
     9665     89/<- %edx 4/r32/esp
     9666     (flush _test-output-buffered-file)
     9667     (flush _test-error-buffered-file)
     9668 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
     9674     # check output
     9675     (check-stream-equal _test-output-stream  ""  "F - test-compare-with-string-literal: output should be empty")
     9676     (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")
     9677     # check that stop(1) was called
     9678     (check-ints-equal *(edx+4) 2 "F - test-compare-with-string-literal: exit status")
     9679     # don't restore from ebp
     9680     81 0/subop/add %esp 8/imm32
     9681     # . epilogue
     9682     5d/pop-to-ebp
     9683     c3/return
     9684
     9685 test-address-with-no-inout:
     9686     # . prologue
     9687     55/push-ebp
     9688     89/<- %ebp 4/r32/esp
     9689     # setup
     9690     (clear-stream _test-input-stream)
     9691     (clear-stream $_test-input-buffered-file->buffer)
     9692     (clear-stream _test-output-stream)
     9693     (clear-stream $_test-output-buffered-file->buffer)
     9694     (clear-stream _test-error-stream)
     9695     (clear-stream $_test-error-buffered-file->buffer)
     9696     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     9697     68/push 0/imm32
     9698     68/push 0/imm32
     9699     89/<- %edx 4/r32/esp
     9700     (tailor-exit-descriptor %edx 0x10)
     9701     #
     9702     (write _test-input-stream "fn foo {\n")
     9703     (write _test-input-stream "  var x/eax: boolean <- address\n")
     9704     (write _test-input-stream "}\n")
     9705     # convert
     9706     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     9707     # registers except esp clobbered at this point
     9708     # restore ed
     9709     89/<- %edx 4/r32/esp
     9710     (flush _test-output-buffered-file)
     9711     (flush _test-error-buffered-file)
     9712 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
     9718     # check output
     9719     (check-stream-equal _test-output-stream  ""  "F - test-address-with-no-inout: output should be empty")
     9720     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'address' expects an inout"  "F - test-address-with-no-inout: error message")
     9721     # check that stop(1) was called
     9722     (check-ints-equal *(edx+4) 2 "F - test-address-with-no-inout: exit status")
     9723     # don't restore from ebp
     9724     81 0/subop/add %esp 8/imm32
     9725     # . epilogue
     9726     5d/pop-to-ebp
     9727     c3/return
     9728
     9729 test-address-with-multiple-inouts:
     9730     # . prologue
     9731     55/push-ebp
     9732     89/<- %ebp 4/r32/esp
     9733     # setup
     9734     (clear-stream _test-input-stream)
     9735     (clear-stream $_test-input-buffered-file->buffer)
     9736     (clear-stream _test-output-stream)
     9737     (clear-stream $_test-output-buffered-file->buffer)
     9738     (clear-stream _test-error-stream)
     9739     (clear-stream $_test-error-buffered-file->buffer)
     9740     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     9741     68/push 0/imm32
     9742     68/push 0/imm32
     9743     89/<- %edx 4/r32/esp
     9744     (tailor-exit-descriptor %edx 0x10)
     9745     #
     9746     (write _test-input-stream "fn foo {\n")
     9747     (write _test-input-stream "  var x/eax: boolean <- address 0, 0\n")
     9748     (write _test-input-stream "}\n")
     9749     # convert
     9750     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     9751     # registers except esp clobbered at this point
     9752     # restore ed
     9753     89/<- %edx 4/r32/esp
     9754     (flush _test-output-buffered-file)
     9755     (flush _test-error-buffered-file)
     9756 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
     9762     # check output
     9763     (check-stream-equal _test-output-stream  ""  "F - test-address-with-multiple-inouts: output should be empty")
     9764     (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")
     9765     # check that stop(1) was called
     9766     (check-ints-equal *(edx+4) 2 "F - test-address-with-multiple-inouts: exit status")
     9767     # don't restore from ebp
     9768     81 0/subop/add %esp 8/imm32
     9769     # . epilogue
     9770     5d/pop-to-ebp
     9771     c3/return
     9772
     9773 test-address-with-no-output:
     9774     # . prologue
     9775     55/push-ebp
     9776     89/<- %ebp 4/r32/esp
     9777     # setup
     9778     (clear-stream _test-input-stream)
     9779     (clear-stream $_test-input-buffered-file->buffer)
     9780     (clear-stream _test-output-stream)
     9781     (clear-stream $_test-output-buffered-file->buffer)
     9782     (clear-stream _test-error-stream)
     9783     (clear-stream $_test-error-buffered-file->buffer)
     9784     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     9785     68/push 0/imm32
     9786     68/push 0/imm32
     9787     89/<- %edx 4/r32/esp
     9788     (tailor-exit-descriptor %edx 0x10)
     9789     #
     9790     (write _test-input-stream "fn foo {\n")
     9791     (write _test-input-stream "  address 0\n")
     9792     (write _test-input-stream "}\n")
     9793     # convert
     9794     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     9795     # registers except esp clobbered at this point
     9796     # restore ed
     9797     89/<- %edx 4/r32/esp
     9798     (flush _test-output-buffered-file)
     9799     (flush _test-error-buffered-file)
     9800 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
     9806     # check output
     9807     (check-stream-equal _test-output-stream  ""  "F - test-address-with-no-output: output should be empty")
     9808     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'address' expects an output"  "F - test-address-with-no-output: error message")
     9809     # check that stop(1) was called
     9810     (check-ints-equal *(edx+4) 2 "F - test-address-with-no-output: exit status")
     9811     # don't restore from ebp
     9812     81 0/subop/add %esp 8/imm32
     9813     # . epilogue
     9814     5d/pop-to-ebp
     9815     c3/return
     9816
     9817 test-address-with-multiple-outputs:
     9818     # . prologue
     9819     55/push-ebp
     9820     89/<- %ebp 4/r32/esp
     9821     # setup
     9822     (clear-stream _test-input-stream)
     9823     (clear-stream $_test-input-buffered-file->buffer)
     9824     (clear-stream _test-output-stream)
     9825     (clear-stream $_test-output-buffered-file->buffer)
     9826     (clear-stream _test-error-stream)
     9827     (clear-stream $_test-error-buffered-file->buffer)
     9828     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     9829     68/push 0/imm32
     9830     68/push 0/imm32
     9831     89/<- %edx 4/r32/esp
     9832     (tailor-exit-descriptor %edx 0x10)
     9833     #
     9834     (write _test-input-stream "fn foo {\n")
     9835     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
     9836     (write _test-input-stream "  var y/ecx: boolean <- copy 0\n")
     9837     (write _test-input-stream "  x, y <- address 0\n")
     9838     (write _test-input-stream "}\n")
     9839     # convert
     9840     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     9841     # registers except esp clobbered at this point
     9842     # restore ed
     9843     89/<- %edx 4/r32/esp
     9844     (flush _test-output-buffered-file)
     9845     (flush _test-error-buffered-file)
     9846 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
     9852     # check output
     9853     (check-stream-equal _test-output-stream  ""  "F - test-address-with-multiple-outputs: output should be empty")
     9854     (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")
     9855     # check that stop(1) was called
     9856     (check-ints-equal *(edx+4) 2 "F - test-address-with-multiple-outputs: exit status")
     9857     # don't restore from ebp
     9858     81 0/subop/add %esp 8/imm32
     9859     # . epilogue
     9860     5d/pop-to-ebp
     9861     c3/return
     9862
     9863 # silly but it works
     9864 test-address-of-deref:
     9865     # . prologue
     9866     55/push-ebp
     9867     89/<- %ebp 4/r32/esp
     9868     # setup
     9869     (clear-stream _test-input-stream)
     9870     (clear-stream $_test-input-buffered-file->buffer)
     9871     (clear-stream _test-output-stream)
     9872     (clear-stream $_test-output-buffered-file->buffer)
     9873     #
     9874     (write _test-input-stream "fn foo {\n")
     9875     (write _test-input-stream "  var x/eax: (addr int) <- copy 0\n")
     9876     (write _test-input-stream "  var y/ecx: (addr int) <- address *x\n")
     9877     (write _test-input-stream "}\n")
     9878     # convert
     9879     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
     9880     (flush _test-output-buffered-file)
     9881     # no errors
     9882     # . epilogue
     9883     5d/pop-to-ebp
     9884     c3/return
     9885
     9886 test-address-to-non-register:
     9887     # . prologue
     9888     55/push-ebp
     9889     89/<- %ebp 4/r32/esp
     9890     # setup
     9891     (clear-stream _test-input-stream)
     9892     (clear-stream $_test-input-buffered-file->buffer)
     9893     (clear-stream _test-output-stream)
     9894     (clear-stream $_test-output-buffered-file->buffer)
     9895     (clear-stream _test-error-stream)
     9896     (clear-stream $_test-error-buffered-file->buffer)
     9897     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     9898     68/push 0/imm32
     9899     68/push 0/imm32
     9900     89/<- %edx 4/r32/esp
     9901     (tailor-exit-descriptor %edx 0x10)
     9902     #
     9903     (write _test-input-stream "fn foo {\n")
     9904     (write _test-input-stream "  var x: (addr int)\n")
     9905     (write _test-input-stream "  x <- address 0\n")
     9906     (write _test-input-stream "}\n")
     9907     # convert
     9908     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     9909     # registers except esp clobbered at this point
     9910     # restore ed
     9911     89/<- %edx 4/r32/esp
     9912     (flush _test-output-buffered-file)
     9913     (flush _test-error-buffered-file)
     9914 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
     9920     # check output
     9921     (check-stream-equal _test-output-stream  ""  "F - test-address-to-non-register: output should be empty")
     9922     (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")
     9923     # check that stop(1) was called
     9924     (check-ints-equal *(edx+4) 2 "F - test-address-to-non-register: exit status")
     9925     # don't restore from ebp
     9926     81 0/subop/add %esp 8/imm32
     9927     # . epilogue
     9928     5d/pop-to-ebp
     9929     c3/return
     9930
     9931 test-address-with-wrong-type:
     9932     # . prologue
     9933     55/push-ebp
     9934     89/<- %ebp 4/r32/esp
     9935     # setup
     9936     (clear-stream _test-input-stream)
     9937     (clear-stream $_test-input-buffered-file->buffer)
     9938     (clear-stream _test-output-stream)
     9939     (clear-stream $_test-output-buffered-file->buffer)
     9940     (clear-stream _test-error-stream)
     9941     (clear-stream $_test-error-buffered-file->buffer)
     9942     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
     9943     68/push 0/imm32
     9944     68/push 0/imm32
     9945     89/<- %edx 4/r32/esp
     9946     (tailor-exit-descriptor %edx 0x10)
     9947     #
     9948     (write _test-input-stream "fn foo {\n")
     9949     (write _test-input-stream "  var x: int\n")
     9950     (write _test-input-stream "  var y/eax: (addr boolean) <- address x\n")
     9951     (write _test-input-stream "}\n")
     9952     # convert
     9953     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
     9954     # registers except esp clobbered at this point
     9955     # restore ed
     9956     89/<- %edx 4/r32/esp
     9957     (flush _test-output-buffered-file)
     9958     (flush _test-error-buffered-file)
     9959 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
     9965     # check output
     9966     (check-stream-equal _test-output-stream  ""  "F - test-address-with-wrong-type: output should be empty")
     9967     (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")
     9968     # check that stop(1) was called
     9969     (check-ints-equal *(edx+4) 2 "F - test-address-with-wrong-type: exit status")
     9970     # don't restore from ebp
     9971     81 0/subop/add %esp 8/imm32
     9972     # . epilogue
     9973     5d/pop-to-ebp
     9974     c3/return
     9975
     9976 test-address-with-right-type-for-array:
     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: (array int 3)\n")
     9988     (write _test-input-stream "  var y/eax: (addr array 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-address-with-right-type-for-stream:
    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     #
    10009     (write _test-input-stream "fn foo {\n")
    10010     (write _test-input-stream "  var x: (stream int 3)\n")
    10011     (write _test-input-stream "  var y/eax: (addr stream int) <- address x\n")
    10012     (write _test-input-stream "}\n")
    10013     # convert
    10014     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
    10015     (flush _test-output-buffered-file)
    10016     # no errors
    10017     # . epilogue
    10018     89/<- %esp 5/r32/ebp
    10019     5d/pop-to-ebp
    10020     c3/return
    10021
    10022 test-get-with-wrong-field:
    10023     # . prologue
    10024     55/push-ebp
    10025     89/<- %ebp 4/r32/esp
    10026     # setup
    10027     (clear-stream _test-input-stream)
    10028     (clear-stream $_test-input-buffered-file->buffer)
    10029     (clear-stream _test-output-stream)
    10030     (clear-stream $_test-output-buffered-file->buffer)
    10031     (clear-stream _test-error-stream)
    10032     (clear-stream $_test-error-buffered-file->buffer)
    10033     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    10034     68/push 0/imm32
    10035     68/push 0/imm32
    10036     89/<- %edx 4/r32/esp
    10037     (tailor-exit-descriptor %edx 0x10)
    10038     #
    10039     (write _test-input-stream "fn foo {\n")
    10040     (write _test-input-stream "  var a: t\n")
    10041     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
    10042     (write _test-input-stream "}\n")
    10043     (write _test-input-stream "type t {\n")
    10044     (write _test-input-stream "  x: int\n")
    10045     (write _test-input-stream "}\n")
    10046     # convert
    10047     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    10048     # registers except esp clobbered at this point
    10049     # restore ed
    10050     89/<- %edx 4/r32/esp
    10051     (flush _test-output-buffered-file)
    10052     (flush _test-error-buffered-file)
    10053 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
    10059     # check output
    10060     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-field: output should be empty")
    10061     (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")
    10062     # check that stop(1) was called
    10063     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-field: exit status")
    10064     # don't restore from ebp
    10065     81 0/subop/add %esp 8/imm32
    10066     # . epilogue
    10067     5d/pop-to-ebp
    10068     c3/return
    10069
    10070 test-get-with-wrong-base-type:
    10071     # . prologue
    10072     55/push-ebp
    10073     89/<- %ebp 4/r32/esp
    10074     # setup
    10075     (clear-stream _test-input-stream)
    10076     (clear-stream $_test-input-buffered-file->buffer)
    10077     (clear-stream _test-output-stream)
    10078     (clear-stream $_test-output-buffered-file->buffer)
    10079     (clear-stream _test-error-stream)
    10080     (clear-stream $_test-error-buffered-file->buffer)
    10081     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    10082     68/push 0/imm32
    10083     68/push 0/imm32
    10084     89/<- %edx 4/r32/esp
    10085     (tailor-exit-descriptor %edx 0x10)
    10086     #
    10087     (write _test-input-stream "fn foo {\n")
    10088     (write _test-input-stream "  var a: int\n")
    10089     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
    10090     (write _test-input-stream "}\n")
    10091     # convert
    10092     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    10093     # registers except esp clobbered at this point
    10094     # restore ed
    10095     89/<- %edx 4/r32/esp
    10096     (flush _test-output-buffered-file)
    10097     (flush _test-error-buffered-file)
    10098 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
    10104     # check output
    10105     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-base-type: output should be empty")
    10106     (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")
    10107     # check that stop(1) was called
    10108     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-base-type: exit status")
    10109     # don't restore from ebp
    10110     81 0/subop/add %esp 8/imm32
    10111     # . epilogue
    10112     5d/pop-to-ebp
    10113     c3/return
    10114
    10115 test-get-with-wrong-base-type-2:
    10116     # . prologue
    10117     55/push-ebp
    10118     89/<- %ebp 4/r32/esp
    10119     # setup
    10120     (clear-stream _test-input-stream)
    10121     (clear-stream $_test-input-buffered-file->buffer)
    10122     (clear-stream _test-output-stream)
    10123     (clear-stream $_test-output-buffered-file->buffer)
    10124     (clear-stream _test-error-stream)
    10125     (clear-stream $_test-error-buffered-file->buffer)
    10126     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    10127     68/push 0/imm32
    10128     68/push 0/imm32
    10129     89/<- %edx 4/r32/esp
    10130     (tailor-exit-descriptor %edx 0x10)
    10131     #
    10132     (write _test-input-stream "fn foo {\n")
    10133     (write _test-input-stream "  var a: (addr t)\n")
    10134     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
    10135     (write _test-input-stream "}\n")
    10136     (write _test-input-stream "type t {\n")
    10137     (write _test-input-stream "  x: int\n")
    10138     (write _test-input-stream "}\n")
    10139     # convert
    10140     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    10141     # registers except esp clobbered at this point
    10142     # restore ed
    10143     89/<- %edx 4/r32/esp
    10144     (flush _test-output-buffered-file)
    10145     (flush _test-error-buffered-file)
    10146 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
    10152     # check output
    10153     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-base-type-2: output should be empty")
    10154     (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")
    10155     # check that stop(1) was called
    10156     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-base-type-2: exit status")
    10157     # don't restore from ebp
    10158     81 0/subop/add %esp 8/imm32
    10159     # . epilogue
    10160     5d/pop-to-ebp
    10161     c3/return
    10162
    10163 test-get-with-wrong-base-type-3:
    10164     # . prologue
    10165     55/push-ebp
    10166     89/<- %ebp 4/r32/esp
    10167     # setup
    10168     (clear-stream _test-input-stream)
    10169     (clear-stream $_test-input-buffered-file->buffer)
    10170     (clear-stream _test-output-stream)
    10171     (clear-stream $_test-output-buffered-file->buffer)
    10172     (clear-stream _test-error-stream)
    10173     (clear-stream $_test-error-buffered-file->buffer)
    10174     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    10175     68/push 0/imm32
    10176     68/push 0/imm32
    10177     89/<- %edx 4/r32/esp
    10178     (tailor-exit-descriptor %edx 0x10)
    10179     #
    10180     (write _test-input-stream "fn foo {\n")
    10181     (write _test-input-stream "  var a: (handle int)\n")
    10182     (write _test-input-stream "  var c/ecx: (addr int) <- get a, y\n")
    10183     (write _test-input-stream "}\n")
    10184     # convert
    10185     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    10186     # registers except esp clobbered at this point
    10187     # restore ed
    10188     89/<- %edx 4/r32/esp
    10189     (flush _test-output-buffered-file)
    10190     (flush _test-error-buffered-file)
    10191 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
    10197     # check output
    10198     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-base-type-3: output should be empty")
    10199     (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")
    10200     # check that stop(1) was called
    10201     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-base-type-3: exit status")
    10202     # don't restore from ebp
    10203     81 0/subop/add %esp 8/imm32
    10204     # . epilogue
    10205     5d/pop-to-ebp
    10206     c3/return
    10207
    10208 test-get-with-wrong-offset-type:
    10209     # . prologue
    10210     55/push-ebp
    10211     89/<- %ebp 4/r32/esp
    10212     # setup
    10213     (clear-stream _test-input-stream)
    10214     (clear-stream $_test-input-buffered-file->buffer)
    10215     (clear-stream _test-output-stream)
    10216     (clear-stream $_test-output-buffered-file->buffer)
    10217     (clear-stream _test-error-stream)
    10218     (clear-stream $_test-error-buffered-file->buffer)
    10219     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    10220     68/push 0/imm32
    10221     68/push 0/imm32
    10222     89/<- %edx 4/r32/esp
    10223     (tailor-exit-descriptor %edx 0x10)
    10224     #
    10225     (write _test-input-stream "fn foo {\n")
    10226     (write _test-input-stream "  var a: t\n")
    10227     (write _test-input-stream "  var b: int\n")
    10228     (write _test-input-stream "  var c/ecx: (addr int) <- get a, b\n")
    10229     (write _test-input-stream "}\n")
    10230     (write _test-input-stream "type t {\n")
    10231     (write _test-input-stream "  x: int\n")
    10232     (write _test-input-stream "}\n")
    10233     # convert
    10234     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    10235     # registers except esp clobbered at this point
    10236     # restore ed
    10237     89/<- %edx 4/r32/esp
    10238     (flush _test-output-buffered-file)
    10239     (flush _test-error-buffered-file)
    10240 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
    10246     # check output
    10247     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-offset-type: output should be empty")
    10248     (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")
    10249     # check that stop(1) was called
    10250     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-offset-type: exit status")
    10251     # don't restore from ebp
    10252     81 0/subop/add %esp 8/imm32
    10253     # . epilogue
    10254     5d/pop-to-ebp
    10255     c3/return
    10256
    10257 test-get-with-wrong-output-type:
    10258     # . prologue
    10259     55/push-ebp
    10260     89/<- %ebp 4/r32/esp
    10261     # setup
    10262     (clear-stream _test-input-stream)
    10263     (clear-stream $_test-input-buffered-file->buffer)
    10264     (clear-stream _test-output-stream)
    10265     (clear-stream $_test-output-buffered-file->buffer)
    10266     (clear-stream _test-error-stream)
    10267     (clear-stream $_test-error-buffered-file->buffer)
    10268     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    10269     68/push 0/imm32
    10270     68/push 0/imm32
    10271     89/<- %edx 4/r32/esp
    10272     (tailor-exit-descriptor %edx 0x10)
    10273     #
    10274     (write _test-input-stream "fn foo {\n")
    10275     (write _test-input-stream "  var a: t\n")
    10276     (write _test-input-stream "  var c: (addr int)\n")
    10277     (write _test-input-stream "  c <- get a, x\n")
    10278     (write _test-input-stream "}\n")
    10279     (write _test-input-stream "type t {\n")
    10280     (write _test-input-stream "  x: int\n")
    10281     (write _test-input-stream "}\n")
    10282     # convert
    10283     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    10284     # registers except esp clobbered at this point
    10285     # restore ed
    10286     89/<- %edx 4/r32/esp
    10287     (flush _test-output-buffered-file)
    10288     (flush _test-error-buffered-file)
    10289 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
    10295     # check output
    10296     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-output-type: output should be empty")
    10297     (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")
    10298     # check that stop(1) was called
    10299     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-output-type: exit status")
    10300     # don't restore from ebp
    10301     81 0/subop/add %esp 8/imm32
    10302     # . epilogue
    10303     5d/pop-to-ebp
    10304     c3/return
    10305
    10306 test-get-with-wrong-output-type-2:
    10307     # . prologue
    10308     55/push-ebp
    10309     89/<- %ebp 4/r32/esp
    10310     # setup
    10311     (clear-stream _test-input-stream)
    10312     (clear-stream $_test-input-buffered-file->buffer)
    10313     (clear-stream _test-output-stream)
    10314     (clear-stream $_test-output-buffered-file->buffer)
    10315     (clear-stream _test-error-stream)
    10316     (clear-stream $_test-error-buffered-file->buffer)
    10317     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    10318     68/push 0/imm32
    10319     68/push 0/imm32
    10320     89/<- %edx 4/r32/esp
    10321     (tailor-exit-descriptor %edx 0x10)
    10322     #
    10323     (write _test-input-stream "fn foo {\n")
    10324     (write _test-input-stream "  var a: t\n")
    10325     (write _test-input-stream "  var c/ecx: int <- get a, x\n")
    10326     (write _test-input-stream "}\n")
    10327     (write _test-input-stream "type t {\n")
    10328     (write _test-input-stream "  x: int\n")
    10329     (write _test-input-stream "}\n")
    10330     # convert
    10331     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    10332     # registers except esp clobbered at this point
    10333     # restore ed
    10334     89/<- %edx 4/r32/esp
    10335     (flush _test-output-buffered-file)
    10336     (flush _test-error-buffered-file)
    10337 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
    10343     # check output
    10344     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-output-type-2: output should be empty")
    10345     (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")
    10346     # check that stop(1) was called
    10347     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-output-type-2: exit status")
    10348     # don't restore from ebp
    10349     81 0/subop/add %esp 8/imm32
    10350     # . epilogue
    10351     5d/pop-to-ebp
    10352     c3/return
    10353
    10354 test-get-with-wrong-output-type-3:
    10355     # . prologue
    10356     55/push-ebp
    10357     89/<- %ebp 4/r32/esp
    10358     # setup
    10359     (clear-stream _test-input-stream)
    10360     (clear-stream $_test-input-buffered-file->buffer)
    10361     (clear-stream _test-output-stream)
    10362     (clear-stream $_test-output-buffered-file->buffer)
    10363     (clear-stream _test-error-stream)
    10364     (clear-stream $_test-error-buffered-file->buffer)
    10365     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    10366     68/push 0/imm32
    10367     68/push 0/imm32
    10368     89/<- %edx 4/r32/esp
    10369     (tailor-exit-descriptor %edx 0x10)
    10370     #
    10371     (write _test-input-stream "fn foo {\n")
    10372     (write _test-input-stream "  var a: t\n")
    10373     (write _test-input-stream "  var c/ecx: (array int) <- get a, x\n")
    10374     (write _test-input-stream "}\n")
    10375     (write _test-input-stream "type t {\n")
    10376     (write _test-input-stream "  x: int\n")
    10377     (write _test-input-stream "}\n")
    10378     # convert
    10379     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    10380     # registers except esp clobbered at this point
    10381     # restore ed
    10382     89/<- %edx 4/r32/esp
    10383     (flush _test-output-buffered-file)
    10384     (flush _test-error-buffered-file)
    10385 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
    10391     # check output
    10392     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-output-type-3: output should be empty")
    10393     (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")
    10394     # check that stop(1) was called
    10395     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-output-type-3: exit status")
    10396     # don't restore from ebp
    10397     81 0/subop/add %esp 8/imm32
    10398     # . epilogue
    10399     5d/pop-to-ebp
    10400     c3/return
    10401
    10402 test-get-with-wrong-output-type-4:
    10403     # . prologue
    10404     55/push-ebp
    10405     89/<- %ebp 4/r32/esp
    10406     # setup
    10407     (clear-stream _test-input-stream)
    10408     (clear-stream $_test-input-buffered-file->buffer)
    10409     (clear-stream _test-output-stream)
    10410     (clear-stream $_test-output-buffered-file->buffer)
    10411     (clear-stream _test-error-stream)
    10412     (clear-stream $_test-error-buffered-file->buffer)
    10413     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    10414     68/push 0/imm32
    10415     68/push 0/imm32
    10416     89/<- %edx 4/r32/esp
    10417     (tailor-exit-descriptor %edx 0x10)
    10418     #
    10419     (write _test-input-stream "fn foo {\n")
    10420     (write _test-input-stream "  var a: t\n")
    10421     (write _test-input-stream "  var c/ecx: (addr boolean) <- get a, x\n")
    10422     (write _test-input-stream "}\n")
    10423     (write _test-input-stream "type t {\n")
    10424     (write _test-input-stream "  x: int\n")
    10425     (write _test-input-stream "}\n")
    10426     # convert
    10427     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    10428     # registers except esp clobbered at this point
    10429     # restore ed
    10430     89/<- %edx 4/r32/esp
    10431     (flush _test-output-buffered-file)
    10432     (flush _test-error-buffered-file)
    10433 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
    10439     # check output
    10440     (check-stream-equal _test-output-stream  ""  "F - test-get-with-wrong-output-type-4: output should be empty")
    10441     (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")
    10442     # check that stop(1) was called
    10443     (check-ints-equal *(edx+4) 2 "F - test-get-with-wrong-output-type-4: exit status")
    10444     # don't restore from ebp
    10445     81 0/subop/add %esp 8/imm32
    10446     # . epilogue
    10447     5d/pop-to-ebp
    10448     c3/return
    10449
    10450 test-get-with-wrong-output-type-5:
    10451     # . prologue
    10452     55/push-ebp
    10453     89/<- %ebp 4/r32/esp
    10454     # setup
    10455     (clear-stream _test-input-stream)
    10456     (clear-stream $_test-input-buffered-file->buffer)
    10457     (clear-stream _test-output-stream)
    10458     (clear-stream $_test-output-buffered-file->buffer)
    10459     #
    10460     (write _test-input-stream "fn foo {\n")
    10461     (write _test-input-stream "  var a: t\n")
    10462     (write _test-input-stream "  var c/ecx: (addr handle int) <- get a, x\n")
    10463     (write _test-input-stream "}\n")
    10464     (write _test-input-stream "type t {\n")
    10465     (write _test-input-stream "  x: (handle int)\n")
    10466     (write _test-input-stream "}\n")
    10467     # convert
    10468     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
    10469     (flush _test-output-buffered-file)
    10470     # no errors
    10471     # . epilogue
    10472     89/<- %esp 5/r32/ebp
    10473     5d/pop-to-ebp
    10474     c3/return
    10475
    10476 test-get-with-too-few-inouts:
    10477     # . prologue
    10478     55/push-ebp
    10479     89/<- %ebp 4/r32/esp
    10480     # setup
    10481     (clear-stream _test-input-stream)
    10482     (clear-stream $_test-input-buffered-file->buffer)
    10483     (clear-stream _test-output-stream)
    10484     (clear-stream $_test-output-buffered-file->buffer)
    10485     (clear-stream _test-error-stream)
    10486     (clear-stream $_test-error-buffered-file->buffer)
    10487     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    10488     68/push 0/imm32
    10489     68/push 0/imm32
    10490     89/<- %edx 4/r32/esp
    10491     (tailor-exit-descriptor %edx 0x10)
    10492     #
    10493     (write _test-input-stream "fn foo {\n")
    10494     (write _test-input-stream "  var a: t\n")
    10495     (write _test-input-stream "  var c/ecx: (addr int) <- get a\n")
    10496     (write _test-input-stream "}\n")
    10497     (write _test-input-stream "type t {\n")
    10498     (write _test-input-stream "  x: int\n")
    10499     (write _test-input-stream "}\n")
    10500     # convert
    10501     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    10502     # registers except esp clobbered at this point
    10503     # restore ed
    10504     89/<- %edx 4/r32/esp
    10505     (flush _test-output-buffered-file)
    10506     (flush _test-error-buffered-file)
    10507 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
    10513     # check output
    10514     (check-stream-equal _test-output-stream  ""  "F - test-get-with-too-few-inouts: output should be empty")
    10515     (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")
    10516     # check that stop(1) was called
    10517     (check-ints-equal *(edx+4) 2 "F - test-get-with-too-few-inouts: exit status")
    10518     # don't restore from ebp
    10519     81 0/subop/add %esp 8/imm32
    10520     # . epilogue
    10521     5d/pop-to-ebp
    10522     c3/return
    10523
    10524 test-get-with-too-many-inouts:
    10525     # . prologue
    10526     55/push-ebp
    10527     89/<- %ebp 4/r32/esp
    10528     # setup
    10529     (clear-stream _test-input-stream)
    10530     (clear-stream $_test-input-buffered-file->buffer)
    10531     (clear-stream _test-output-stream)
    10532     (clear-stream $_test-output-buffered-file->buffer)
    10533     (clear-stream _test-error-stream)
    10534     (clear-stream $_test-error-buffered-file->buffer)
    10535     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    10536     68/push 0/imm32
    10537     68/push 0/imm32
    10538     89/<- %edx 4/r32/esp
    10539     (tailor-exit-descriptor %edx 0x10)
    10540     #
    10541     (write _test-input-stream "fn foo {\n")
    10542     (write _test-input-stream "  var a: t\n")
    10543     (write _test-input-stream "  var c/ecx: (addr int) <- get a, x, 0\n")
    10544     (write _test-input-stream "}\n")
    10545     (write _test-input-stream "type t {\n")
    10546     (write _test-input-stream "  x: int\n")
    10547     (write _test-input-stream "}\n")
    10548     # convert
    10549     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    10550     # registers except esp clobbered at this point
    10551     # restore ed
    10552     89/<- %edx 4/r32/esp
    10553     (flush _test-output-buffered-file)
    10554     (flush _test-error-buffered-file)
    10555 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
    10561     # check output
    10562     (check-stream-equal _test-output-stream  ""  "F - test-get-with-too-many-inouts: output should be empty")
    10563     (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")
    10564     # check that stop(1) was called
    10565     (check-ints-equal *(edx+4) 2 "F - test-get-with-too-many-inouts: exit status")
    10566     # don't restore from ebp
    10567     81 0/subop/add %esp 8/imm32
    10568     # . epilogue
    10569     5d/pop-to-ebp
    10570     c3/return
    10571
    10572 test-get-with-no-output:
    10573     # . prologue
    10574     55/push-ebp
    10575     89/<- %ebp 4/r32/esp
    10576     # setup
    10577     (clear-stream _test-input-stream)
    10578     (clear-stream $_test-input-buffered-file->buffer)
    10579     (clear-stream _test-output-stream)
    10580     (clear-stream $_test-output-buffered-file->buffer)
    10581     (clear-stream _test-error-stream)
    10582     (clear-stream $_test-error-buffered-file->buffer)
    10583     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    10584     68/push 0/imm32
    10585     68/push 0/imm32
    10586     89/<- %edx 4/r32/esp
    10587     (tailor-exit-descriptor %edx 0x10)
    10588     #
    10589     (write _test-input-stream "fn foo {\n")
    10590     (write _test-input-stream "  var a: t\n")
    10591     (write _test-input-stream "  get a, x\n")
    10592     (write _test-input-stream "}\n")
    10593     (write _test-input-stream "type t {\n")
    10594     (write _test-input-stream "  x: int\n")
    10595     (write _test-input-stream "}\n")
    10596     # convert
    10597     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    10598     # registers except esp clobbered at this point
    10599     # restore ed
    10600     89/<- %edx 4/r32/esp
    10601     (flush _test-output-buffered-file)
    10602     (flush _test-error-buffered-file)
    10603 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
    10609     # check output
    10610     (check-stream-equal _test-output-stream  ""  "F - test-get-with-no-output: output should be empty")
    10611     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt get: must have an output"  "F - test-get-with-no-output: error message")
    10612     # check that stop(1) was called
    10613     (check-ints-equal *(edx+4) 2 "F - test-get-with-no-output: exit status")
    10614     # don't restore from ebp
    10615     81 0/subop/add %esp 8/imm32
    10616     # . epilogue
    10617     5d/pop-to-ebp
    10618     c3/return
    10619
    10620 test-get-with-too-many-outputs:
    10621     # . prologue
    10622     55/push-ebp
    10623     89/<- %ebp 4/r32/esp
    10624     # setup
    10625     (clear-stream _test-input-stream)
    10626     (clear-stream $_test-input-buffered-file->buffer)
    10627     (clear-stream _test-output-stream)
    10628     (clear-stream $_test-output-buffered-file->buffer)
    10629     (clear-stream _test-error-stream)
    10630     (clear-stream $_test-error-buffered-file->buffer)
    10631     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    10632     68/push 0/imm32
    10633     68/push 0/imm32
    10634     89/<- %edx 4/r32/esp
    10635     (tailor-exit-descriptor %edx 0x10)
    10636     #
    10637     (write _test-input-stream "fn foo {\n")
    10638     (write _test-input-stream "  var a: t\n")
    10639     (write _test-input-stream "  var b: int\n")
    10640     (write _test-input-stream "  var c/eax: (addr int) <- copy 0\n")
    10641     (write _test-input-stream "  c, b <- get a, x\n")
    10642     (write _test-input-stream "}\n")
    10643     (write _test-input-stream "type t {\n")
    10644     (write _test-input-stream "  x: int\n")
    10645     (write _test-input-stream "}\n")
    10646     # convert
    10647     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    10648     # registers except esp clobbered at this point
    10649     # restore ed
    10650     89/<- %edx 4/r32/esp
    10651     (flush _test-output-buffered-file)
    10652     (flush _test-error-buffered-file)
    10653 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
    10659     # check output
    10660     (check-stream-equal _test-output-stream  ""  "F - test-get-with-too-many-outputs: output should be empty")
    10661     (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")
    10662     # check that stop(1) was called
    10663     (check-ints-equal *(edx+4) 2 "F - test-get-with-too-many-outputs: exit status")
    10664     # don't restore from ebp
    10665     81 0/subop/add %esp 8/imm32
    10666     # . epilogue
    10667     5d/pop-to-ebp
    10668     c3/return
    10669
    10670 test-convert-array-of-user-defined-types:
    10671     # . prologue
    10672     55/push-ebp
    10673     89/<- %ebp 4/r32/esp
    10674     # setup
    10675     (clear-stream _test-input-stream)
    10676     (clear-stream $_test-input-buffered-file->buffer)
    10677     (clear-stream _test-output-stream)
    10678     (clear-stream $_test-output-buffered-file->buffer)
    10679     #
    10680     (write _test-input-stream "type t {\n")  # each t is 8 bytes, which is a power of 2
    10681     (write _test-input-stream "  x: int\n")
    10682     (write _test-input-stream "  y: int\n")
    10683     (write _test-input-stream "}\n")
    10684     (write _test-input-stream "fn foo {\n")
    10685     (write _test-input-stream "  var arr/eax: (addr array t) <- copy 0\n")
    10686     (write _test-input-stream "  var idx/ecx: int <- copy 3\n")
    10687     (write _test-input-stream "  var x/eax: (addr t) <- index arr, idx\n")
    10688     (write _test-input-stream "}\n")
    10689     # convert
    10690     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
    10691     (flush _test-output-buffered-file)
    10692 +--  6 lines: #?     # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------
    10698     # check output
    10699     (check-next-stream-line-equal _test-output-stream "foo:"                                        "F - test-convert-array-of-user-defined-types/0")
    10700     (check-next-stream-line-equal _test-output-stream "  # . prologue"                              "F - test-convert-array-of-user-defined-types/1")
    10701     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                               "F - test-convert-array-of-user-defined-types/2")
    10702     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"                      "F - test-convert-array-of-user-defined-types/3")
    10703     (check-next-stream-line-equal _test-output-stream "  {"                                         "F - test-convert-array-of-user-defined-types/4")
    10704     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"                       "F - test-convert-array-of-user-defined-types/5")
    10705     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"                    "F - test-convert-array-of-user-defined-types/6")
    10706     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 0/imm32"                  "F - test-convert-array-of-user-defined-types/7")
    10707     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"                    "F - test-convert-array-of-user-defined-types/8")
    10708     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 3/imm32"                  "F - test-convert-array-of-user-defined-types/9")
    10709     (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")
    10710     (check-next-stream-line-equal _test-output-stream "    81 7/subop/compare %eax 0/imm32"  "F - test-convert-array-of-user-defined-types/12")
    10711     (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")
    10712     (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")
    10713     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"                     "F - test-convert-array-of-user-defined-types/15")
    10714     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"                     "F - test-convert-array-of-user-defined-types/16")
    10715     (check-next-stream-line-equal _test-output-stream "  }"                                         "F - test-convert-array-of-user-defined-types/17")
    10716     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"                      "F - test-convert-array-of-user-defined-types/18")
    10717     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                              "F - test-convert-array-of-user-defined-types/19")
    10718     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"                      "F - test-convert-array-of-user-defined-types/20")
    10719     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                             "F - test-convert-array-of-user-defined-types/21")
    10720     (check-next-stream-line-equal _test-output-stream "  c3/return"                                 "F - test-convert-array-of-user-defined-types/22")
    10721     # . epilogue
    10722     89/<- %esp 5/r32/ebp
    10723     5d/pop-to-ebp
    10724     c3/return
    10725
    10726 test-convert-length-of-array-of-user-defined-types-to-eax:
    10727     # . prologue
    10728     55/push-ebp
    10729     89/<- %ebp 4/r32/esp
    10730     # setup
    10731     (clear-stream _test-input-stream)
    10732     (clear-stream $_test-input-buffered-file->buffer)
    10733     (clear-stream _test-output-stream)
    10734     (clear-stream $_test-output-buffered-file->buffer)
    10735     #
    10736     (write _test-input-stream "type t {\n")  # size = 12, which is not a power of 2
    10737     (write _test-input-stream "  x: int\n")
    10738     (write _test-input-stream "  y: int\n")
    10739     (write _test-input-stream "  z: int\n")
    10740     (write _test-input-stream "}\n")
    10741     (write _test-input-stream "fn foo {\n")
    10742     (write _test-input-stream "  var arr/eax: (addr array t) <- copy 0\n")
    10743     (write _test-input-stream "  var x/eax: int <- length arr\n")
    10744     (write _test-input-stream "}\n")
    10745     # convert
    10746     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
    10747     (flush _test-output-buffered-file)
    10748 +--  6 lines: #?     # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------
    10754     # check output
    10755     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array-of-user-defined-types-to-eax/0")
    10756     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array-of-user-defined-types-to-eax/1")
    10757     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array-of-user-defined-types-to-eax/2")
    10758     (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")
    10759     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array-of-user-defined-types-to-eax/4")
    10760     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array-of-user-defined-types-to-eax/5")
    10761     # var arr
    10762     (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")
    10763     (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")
    10764     # length instruction
    10765     (check-next-stream-line-equal _test-output-stream "    51/push-ecx"         "F - test-convert-length-of-array-of-user-defined-types-to-eax/8")
    10766     (check-next-stream-line-equal _test-output-stream "    52/push-edx"         "F - test-convert-length-of-array-of-user-defined-types-to-eax/9")
    10767     (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")
    10768     (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")
    10769     (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")
    10770     (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")
    10771     (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")
    10772     (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")
    10773     # reclaim arr
    10774     (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")
    10775     #
    10776     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array-of-user-defined-types-to-eax/17")
    10777     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array-of-user-defined-types-to-eax/18")
    10778     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array-of-user-defined-types-to-eax/19")
    10779     (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")
    10780     (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")
    10781     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array-of-user-defined-types-to-eax/22")
    10782     # . epilogue
    10783     89/<- %esp 5/r32/ebp
    10784     5d/pop-to-ebp
    10785     c3/return
    10786
    10787 test-convert-length-of-array-of-user-defined-types-to-ecx:
    10788     # . prologue
    10789     55/push-ebp
    10790     89/<- %ebp 4/r32/esp
    10791     # setup
    10792     (clear-stream _test-input-stream)
    10793     (clear-stream $_test-input-buffered-file->buffer)
    10794     (clear-stream _test-output-stream)
    10795     (clear-stream $_test-output-buffered-file->buffer)
    10796     #
    10797     (write _test-input-stream "type t {\n")  # size = 12, which is not a power of 2
    10798     (write _test-input-stream "  x: int\n")
    10799     (write _test-input-stream "  y: int\n")
    10800     (write _test-input-stream "  z: int\n")
    10801     (write _test-input-stream "}\n")
    10802     (write _test-input-stream "fn foo {\n")
    10803     (write _test-input-stream "  var arr/eax: (addr array t) <- copy 0\n")
    10804     (write _test-input-stream "  var x/ecx: int <- length arr\n")
    10805     (write _test-input-stream "}\n")
    10806     # convert
    10807     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
    10808     (flush _test-output-buffered-file)
    10809 +--  6 lines: #?     # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------
    10815     # check output
    10816     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array-of-user-defined-types-to-ecx/0")
    10817     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array-of-user-defined-types-to-ecx/1")
    10818     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array-of-user-defined-types-to-ecx/2")
    10819     (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")
    10820     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array-of-user-defined-types-to-ecx/4")
    10821     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array-of-user-defined-types-to-ecx/5")
    10822     # var a
    10823     (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")
    10824     (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")
    10825     # var x
    10826     (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")
    10827     # length instruction
    10828     (check-next-stream-line-equal _test-output-stream "    50/push-eax"         "F - test-convert-length-of-array-of-user-defined-types-to-ecx/9")
    10829     (check-next-stream-line-equal _test-output-stream "    52/push-edx"         "F - test-convert-length-of-array-of-user-defined-types-to-ecx/10")
    10830     (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")
    10831     (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")
    10832     (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")
    10833     (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")
    10834     (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")
    10835     (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")
    10836     (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")
    10837     # reclaim x
    10838     (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")
    10839     # reclaim a
    10840     (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")
    10841     #
    10842     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array-of-user-defined-types-to-ecx/20")
    10843     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array-of-user-defined-types-to-ecx/21")
    10844     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array-of-user-defined-types-to-ecx/22")
    10845     (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")
    10846     (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")
    10847     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array-of-user-defined-types-to-ecx/25")
    10848     # . epilogue
    10849     89/<- %esp 5/r32/ebp
    10850     5d/pop-to-ebp
    10851     c3/return
    10852
    10853 test-convert-length-of-array-of-user-defined-types-to-edx:
    10854     # . prologue
    10855     55/push-ebp
    10856     89/<- %ebp 4/r32/esp
    10857     # setup
    10858     (clear-stream _test-input-stream)
    10859     (clear-stream $_test-input-buffered-file->buffer)
    10860     (clear-stream _test-output-stream)
    10861     (clear-stream $_test-output-buffered-file->buffer)
    10862     #
    10863     (write _test-input-stream "type t {\n")  # size = 12, which is not a power of 2
    10864     (write _test-input-stream "  x: int\n")
    10865     (write _test-input-stream "  y: int\n")
    10866     (write _test-input-stream "  z: int\n")
    10867     (write _test-input-stream "}\n")
    10868     (write _test-input-stream "fn foo {\n")
    10869     (write _test-input-stream "  var arr/eax: (addr array t) <- copy 0\n")
    10870     (write _test-input-stream "  var x/edx: int <- length arr\n")
    10871     (write _test-input-stream "}\n")
    10872     # convert
    10873     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
    10874     (flush _test-output-buffered-file)
    10875 +--  6 lines: #?     # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------
    10881     # check output
    10882     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array-of-user-defined-types-to-edx/0")
    10883     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array-of-user-defined-types-to-edx/1")
    10884     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array-of-user-defined-types-to-edx/2")
    10885     (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")
    10886     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array-of-user-defined-types-to-edx/4")
    10887     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array-of-user-defined-types-to-edx/5")
    10888     # var a
    10889     (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")
    10890     (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")
    10891     # var x
    10892     (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")
    10893     # length instruction
    10894     (check-next-stream-line-equal _test-output-stream "    50/push-eax"         "F - test-convert-length-of-array-of-user-defined-types-to-edx/9")
    10895     (check-next-stream-line-equal _test-output-stream "    51/push-ecx"         "F - test-convert-length-of-array-of-user-defined-types-to-edx/10")
    10896     (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")
    10897     (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")
    10898     (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")
    10899     (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")
    10900     (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")
    10901     (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")
    10902     (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")
    10903     # reclaim x
    10904     (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")
    10905     # reclaim a
    10906     (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")
    10907     #
    10908     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array-of-user-defined-types-to-edx/20")
    10909     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array-of-user-defined-types-to-edx/21")
    10910     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array-of-user-defined-types-to-edx/22")
    10911     (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")
    10912     (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")
    10913     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array-of-user-defined-types-to-edx/25")
    10914     # . epilogue
    10915     89/<- %esp 5/r32/ebp
    10916     5d/pop-to-ebp
    10917     c3/return
    10918
    10919 test-convert-length-of-array-of-user-defined-types:
    10920     # . prologue
    10921     55/push-ebp
    10922     89/<- %ebp 4/r32/esp
    10923     # setup
    10924     (clear-stream _test-input-stream)
    10925     (clear-stream $_test-input-buffered-file->buffer)
    10926     (clear-stream _test-output-stream)
    10927     (clear-stream $_test-output-buffered-file->buffer)
    10928     #
    10929     (write _test-input-stream "type t {\n")  # each t is 8 bytes, which is a power of 2
    10930     (write _test-input-stream "  x: int\n")
    10931     (write _test-input-stream "  y: int\n")
    10932     (write _test-input-stream "  z: int\n")
    10933     (write _test-input-stream "}\n")
    10934     (write _test-input-stream "fn foo {\n")
    10935     (write _test-input-stream "  var arr/eax: (addr array t) <- copy 0\n")
    10936     (write _test-input-stream "  var x/ebx: int <- length arr\n")
    10937     (write _test-input-stream "}\n")
    10938     # convert
    10939     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
    10940     (flush _test-output-buffered-file)
    10941 +--  6 lines: #?     # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------
    10947     # check output
    10948     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-length-of-array-of-user-defined-types/0")
    10949     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-length-of-array-of-user-defined-types/1")
    10950     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-length-of-array-of-user-defined-types/2")
    10951     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-length-of-array-of-user-defined-types/3")
    10952     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-length-of-array-of-user-defined-types/4")
    10953     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-length-of-array-of-user-defined-types/5")
    10954     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-length-of-array-of-user-defined-types/6")
    10955     (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")
    10956     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ebx"  "F - test-convert-length-of-array-of-user-defined-types/8")
    10957     (check-next-stream-line-equal _test-output-stream "    50/push-eax"         "F - test-convert-length-of-array-of-user-defined-types/9")
    10958     (check-next-stream-line-equal _test-output-stream "    51/push-ecx"         "F - test-convert-length-of-array-of-user-defined-types/10")
    10959     (check-next-stream-line-equal _test-output-stream "    52/push-edx"         "F - test-convert-length-of-array-of-user-defined-types/11")
    10960     (check-next-stream-line-equal _test-output-stream "    8b/-> *eax 0x00000000/r32"  "F - test-convert-length-of-array-of-user-defined-types/12")
    10961     (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")
    10962     (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")
    10963     (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")
    10964     (check-next-stream-line-equal _test-output-stream "    89/<- %ebx 0/r32/eax"  "F - test-convert-length-of-array-of-user-defined-types/16")
    10965     (check-next-stream-line-equal _test-output-stream "    5a/pop-to-edx"       "F - test-convert-length-of-array-of-user-defined-types/17")
    10966     (check-next-stream-line-equal _test-output-stream "    59/pop-to-ecx"       "F - test-convert-length-of-array-of-user-defined-types/18")
    10967     (check-next-stream-line-equal _test-output-stream "    58/pop-to-eax"       "F - test-convert-length-of-array-of-user-defined-types/19")
    10968     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ebx"  "F - test-convert-length-of-array-of-user-defined-types/20")
    10969     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %eax"  "F - test-convert-length-of-array-of-user-defined-types/21")
    10970     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-length-of-array-of-user-defined-types/22")
    10971     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-length-of-array-of-user-defined-types/23")
    10972     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-length-of-array-of-user-defined-types/24")
    10973     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-length-of-array-of-user-defined-types/25")
    10974     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-length-of-array-of-user-defined-types/26")
    10975     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-length-of-array-of-user-defined-types/27")
    10976     # . epilogue
    10977     89/<- %esp 5/r32/ebp
    10978     5d/pop-to-ebp
    10979     c3/return
    10980
    10981 test-index-with-non-array-atom-base-type:
    10982     # . prologue
    10983     55/push-ebp
    10984     89/<- %ebp 4/r32/esp
    10985     # setup
    10986     (clear-stream _test-input-stream)
    10987     (clear-stream $_test-input-buffered-file->buffer)
    10988     (clear-stream _test-output-stream)
    10989     (clear-stream $_test-output-buffered-file->buffer)
    10990     (clear-stream _test-error-stream)
    10991     (clear-stream $_test-error-buffered-file->buffer)
    10992     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    10993     68/push 0/imm32
    10994     68/push 0/imm32
    10995     89/<- %edx 4/r32/esp
    10996     (tailor-exit-descriptor %edx 0x10)
    10997     #
    10998     (write _test-input-stream "fn foo {\n")
    10999     (write _test-input-stream "  var a: int\n")
    11000     (write _test-input-stream "  var c/ecx: (addr int) <- index a, 0\n")
    11001     (write _test-input-stream "}\n")
    11002     # convert
    11003     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    11004     # registers except esp clobbered at this point
    11005     # restore ed
    11006     89/<- %edx 4/r32/esp
    11007     (flush _test-output-buffered-file)
    11008     (flush _test-error-buffered-file)
    11009 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
    11015     # check output
    11016     (check-stream-equal _test-output-stream  ""  "F - test-index-with-non-array-atom-base-type: output should be empty")
    11017     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt index: var 'a' is not an array"  "F - test-index-with-non-array-atom-base-type: error message")
    11018     # check that stop(1) was called
    11019     (check-ints-equal *(edx+4) 2 "F - test-index-with-non-array-atom-base-type: exit status")
    11020     # don't restore from ebp
    11021     81 0/subop/add %esp 8/imm32
    11022     # . epilogue
    11023     5d/pop-to-ebp
    11024     c3/return
    11025
    11026 test-index-with-non-array-compound-base-type:
    11027     # . prologue
    11028     55/push-ebp
    11029     89/<- %ebp 4/r32/esp
    11030     # setup
    11031     (clear-stream _test-input-stream)
    11032     (clear-stream $_test-input-buffered-file->buffer)
    11033     (clear-stream _test-output-stream)
    11034     (clear-stream $_test-output-buffered-file->buffer)
    11035     (clear-stream _test-error-stream)
    11036     (clear-stream $_test-error-buffered-file->buffer)
    11037     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    11038     68/push 0/imm32
    11039     68/push 0/imm32
    11040     89/<- %edx 4/r32/esp
    11041     (tailor-exit-descriptor %edx 0x10)
    11042     #
    11043     (write _test-input-stream "fn foo {\n")
    11044     (write _test-input-stream "  var a: (handle int)\n")
    11045     (write _test-input-stream "  var c/ecx: (addr int) <- index a, 0\n")
    11046     (write _test-input-stream "}\n")
    11047     # convert
    11048     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    11049     # registers except esp clobbered at this point
    11050     # restore ed
    11051     89/<- %edx 4/r32/esp
    11052     (flush _test-output-buffered-file)
    11053     (flush _test-error-buffered-file)
    11054 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
    11060     # check output
    11061     (check-stream-equal _test-output-stream  ""  "F - test-index-with-non-array-compound-base-type: output should be empty")
    11062     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt index: var 'a' is not an array"  "F - test-index-with-non-array-compound-base-type: error message")
    11063     # check that stop(1) was called
    11064     (check-ints-equal *(edx+4) 2 "F - test-index-with-non-array-compound-base-type: exit status")
    11065     # don't restore from ebp
    11066     81 0/subop/add %esp 8/imm32
    11067     # . epilogue
    11068     5d/pop-to-ebp
    11069     c3/return
    11070
    11071 test-index-with-non-array-compound-base-type-2:
    11072     # . prologue
    11073     55/push-ebp
    11074     89/<- %ebp 4/r32/esp
    11075     # setup
    11076     (clear-stream _test-input-stream)
    11077     (clear-stream $_test-input-buffered-file->buffer)
    11078     (clear-stream _test-output-stream)
    11079     (clear-stream $_test-output-buffered-file->buffer)
    11080     (clear-stream _test-error-stream)
    11081     (clear-stream $_test-error-buffered-file->buffer)
    11082     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    11083     68/push 0/imm32
    11084     68/push 0/imm32
    11085     89/<- %edx 4/r32/esp
    11086     (tailor-exit-descriptor %edx 0x10)
    11087     #
    11088     (write _test-input-stream "fn foo {\n")
    11089     (write _test-input-stream "  var a: (addr int)\n")
    11090     (write _test-input-stream "  var c/ecx: (addr int) <- index a, 0\n")
    11091     (write _test-input-stream "}\n")
    11092     # convert
    11093     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    11094     # registers except esp clobbered at this point
    11095     # restore ed
    11096     89/<- %edx 4/r32/esp
    11097     (flush _test-output-buffered-file)
    11098     (flush _test-error-buffered-file)
    11099 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
    11105     # check output
    11106     (check-stream-equal _test-output-stream  ""  "F - test-index-with-non-array-compound-base-type-2: output should be empty")
    11107     (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")
    11108     # check that stop(1) was called
    11109     (check-ints-equal *(edx+4) 2 "F - test-index-with-non-array-compound-base-type-2: exit status")
    11110     # don't restore from ebp
    11111     81 0/subop/add %esp 8/imm32
    11112     # . epilogue
    11113     5d/pop-to-ebp
    11114     c3/return
    11115
    11116 test-index-with-array-atom-base-type:
    11117     # . prologue
    11118     55/push-ebp
    11119     89/<- %ebp 4/r32/esp
    11120     # setup
    11121     (clear-stream _test-input-stream)
    11122     (clear-stream $_test-input-buffered-file->buffer)
    11123     (clear-stream _test-output-stream)
    11124     (clear-stream $_test-output-buffered-file->buffer)
    11125     (clear-stream _test-error-stream)
    11126     (clear-stream $_test-error-buffered-file->buffer)
    11127     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    11128     68/push 0/imm32
    11129     68/push 0/imm32
    11130     89/<- %edx 4/r32/esp
    11131     (tailor-exit-descriptor %edx 0x10)
    11132     #
    11133     (write _test-input-stream "fn foo {\n")
    11134     (write _test-input-stream "  var a: array\n")
    11135     (write _test-input-stream "  var c/ecx: (addr int) <- index a, 0\n")
    11136     (write _test-input-stream "}\n")
    11137     # convert
    11138     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    11139     # registers except esp clobbered at this point
    11140     # restore ed
    11141     89/<- %edx 4/r32/esp
    11142     (flush _test-output-buffered-file)
    11143     (flush _test-error-buffered-file)
    11144 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
    11150     # check output
    11151     (check-stream-equal _test-output-stream  ""  "F - test-index-with-array-atom-base-type: output should be empty")
    11152     (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")
    11153     # check that stop(1) was called
    11154     (check-ints-equal *(edx+4) 2 "F - test-index-with-array-atom-base-type: exit status")
    11155     # don't restore from ebp
    11156     81 0/subop/add %esp 8/imm32
    11157     # . epilogue
    11158     5d/pop-to-ebp
    11159     c3/return
    11160
    11161 test-index-with-addr-base-on-stack:
    11162     # . prologue
    11163     55/push-ebp
    11164     89/<- %ebp 4/r32/esp
    11165     # setup
    11166     (clear-stream _test-input-stream)
    11167     (clear-stream $_test-input-buffered-file->buffer)
    11168     (clear-stream _test-output-stream)
    11169     (clear-stream $_test-output-buffered-file->buffer)
    11170     (clear-stream _test-error-stream)
    11171     (clear-stream $_test-error-buffered-file->buffer)
    11172     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    11173     68/push 0/imm32
    11174     68/push 0/imm32
    11175     89/<- %edx 4/r32/esp
    11176     (tailor-exit-descriptor %edx 0x10)
    11177     #
    11178     (write _test-input-stream "fn foo {\n")
    11179     (write _test-input-stream "  var a: (addr array int)\n")
    11180     (write _test-input-stream "  var c/ecx: (addr int) <- index a, 0\n")
    11181     (write _test-input-stream "}\n")
    11182     # convert
    11183     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    11184     # registers except esp clobbered at this point
    11185     # restore ed
    11186     89/<- %edx 4/r32/esp
    11187     (flush _test-output-buffered-file)
    11188     (flush _test-error-buffered-file)
    11189 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
    11195     # check output
    11196     (check-stream-equal _test-output-stream  ""  "F - test-index-with-addr-base-on-stack: output should be empty")
    11197     (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")
    11198     # check that stop(1) was called
    11199     (check-ints-equal *(edx+4) 2 "F - test-index-with-addr-base-on-stack: exit status")
    11200     # don't restore from ebp
    11201     81 0/subop/add %esp 8/imm32
    11202     # . epilogue
    11203     5d/pop-to-ebp
    11204     c3/return
    11205
    11206 test-index-with-wrong-index-type:
    11207     # . prologue
    11208     55/push-ebp
    11209     89/<- %ebp 4/r32/esp
    11210     # setup
    11211     (clear-stream _test-input-stream)
    11212     (clear-stream $_test-input-buffered-file->buffer)
    11213     (clear-stream _test-output-stream)
    11214     (clear-stream $_test-output-buffered-file->buffer)
    11215     (clear-stream _test-error-stream)
    11216     (clear-stream $_test-error-buffered-file->buffer)
    11217     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    11218     68/push 0/imm32
    11219     68/push 0/imm32
    11220     89/<- %edx 4/r32/esp
    11221     (tailor-exit-descriptor %edx 0x10)
    11222     #
    11223     (write _test-input-stream "fn foo {\n")
    11224     (write _test-input-stream "  var a/eax: (addr array int) <- copy 0\n")
    11225     (write _test-input-stream "  var b: boolean\n")
    11226     (write _test-input-stream "  var c/ecx: (addr int) <- index a, b\n")
    11227     (write _test-input-stream "}\n")
    11228     # convert
    11229     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    11230     # registers except esp clobbered at this point
    11231     # restore ed
    11232     89/<- %edx 4/r32/esp
    11233     (flush _test-output-buffered-file)
    11234     (flush _test-error-buffered-file)
    11235 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
    11241     # check output
    11242     (check-stream-equal _test-output-stream  ""  "F - test-index-with-wrong-index-type: output should be empty")
    11243     (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")
    11244     # check that stop(1) was called
    11245     (check-ints-equal *(edx+4) 2 "F - test-index-with-wrong-index-type: exit status")
    11246     # don't restore from ebp
    11247     81 0/subop/add %esp 8/imm32
    11248     # . epilogue
    11249     5d/pop-to-ebp
    11250     c3/return
    11251
    11252 test-index-with-offset-atom-index-type:
    11253     # . prologue
    11254     55/push-ebp
    11255     89/<- %ebp 4/r32/esp
    11256     # setup
    11257     (clear-stream _test-input-stream)
    11258     (clear-stream $_test-input-buffered-file->buffer)
    11259     (clear-stream _test-output-stream)
    11260     (clear-stream $_test-output-buffered-file->buffer)
    11261     (clear-stream _test-error-stream)
    11262     (clear-stream $_test-error-buffered-file->buffer)
    11263     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    11264     68/push 0/imm32
    11265     68/push 0/imm32
    11266     89/<- %edx 4/r32/esp
    11267     (tailor-exit-descriptor %edx 0x10)
    11268     #
    11269     (write _test-input-stream "fn foo {\n")
    11270     (write _test-input-stream "  var a/eax: (addr array int) <- copy 0\n")
    11271     (write _test-input-stream "  var b: offset\n")
    11272     (write _test-input-stream "  var c/ecx: (addr int) <- index a, b\n")
    11273     (write _test-input-stream "}\n")
    11274     # convert
    11275     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    11276     # registers except esp clobbered at this point
    11277     # restore ed
    11278     89/<- %edx 4/r32/esp
    11279     (flush _test-output-buffered-file)
    11280     (flush _test-error-buffered-file)
    11281 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
    11287     # check output
    11288     (check-stream-equal _test-output-stream  ""  "F - test-index-with-offset-atom-index-type: output should be empty")
    11289     (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")
    11290     # check that stop(1) was called
    11291     (check-ints-equal *(edx+4) 2 "F - test-index-with-offset-atom-index-type: exit status")
    11292     # don't restore from ebp
    11293     81 0/subop/add %esp 8/imm32
    11294     # . epilogue
    11295     5d/pop-to-ebp
    11296     c3/return
    11297
    11298 test-index-with-offset-on-stack:
    11299     # . prologue
    11300     55/push-ebp
    11301     89/<- %ebp 4/r32/esp
    11302     # setup
    11303     (clear-stream _test-input-stream)
    11304     (clear-stream $_test-input-buffered-file->buffer)
    11305     (clear-stream _test-output-stream)
    11306     (clear-stream $_test-output-buffered-file->buffer)
    11307     (clear-stream _test-error-stream)
    11308     (clear-stream $_test-error-buffered-file->buffer)
    11309     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    11310     68/push 0/imm32
    11311     68/push 0/imm32
    11312     89/<- %edx 4/r32/esp
    11313     (tailor-exit-descriptor %edx 0x10)
    11314     #
    11315     (write _test-input-stream "fn foo {\n")
    11316     (write _test-input-stream "  var a/eax: (addr array int) <- copy 0\n")
    11317     (write _test-input-stream "  var b: int\n")
    11318     (write _test-input-stream "  var c/ecx: (addr int) <- index a, b\n")
    11319     (write _test-input-stream "}\n")
    11320     # convert
    11321     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    11322     # registers except esp clobbered at this point
    11323     # restore ed
    11324     89/<- %edx 4/r32/esp
    11325     (flush _test-output-buffered-file)
    11326     (flush _test-error-buffered-file)
    11327 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
    11333     # check output
    11334     (check-stream-equal _test-output-stream  ""  "F - test-index-with-offset-on-stack: output should be empty")
    11335     (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")
    11336     # check that stop(1) was called
    11337     (check-ints-equal *(edx+4) 2 "F - test-index-with-offset-on-stack: exit status")
    11338     # don't restore from ebp
    11339     81 0/subop/add %esp 8/imm32
    11340     # . epilogue
    11341     5d/pop-to-ebp
    11342     c3/return
    11343
    11344 test-index-needs-offset-type:
    11345     # . prologue
    11346     55/push-ebp
    11347     89/<- %ebp 4/r32/esp
    11348     # setup
    11349     (clear-stream _test-input-stream)
    11350     (clear-stream $_test-input-buffered-file->buffer)
    11351     (clear-stream _test-output-stream)
    11352     (clear-stream $_test-output-buffered-file->buffer)
    11353     (clear-stream _test-error-stream)
    11354     (clear-stream $_test-error-buffered-file->buffer)
    11355     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    11356     68/push 0/imm32
    11357     68/push 0/imm32
    11358     89/<- %edx 4/r32/esp
    11359     (tailor-exit-descriptor %edx 0x10)
    11360     #
    11361     (write _test-input-stream "fn foo {\n")
    11362     (write _test-input-stream "  var a/eax: (addr array t) <- copy 0\n")
    11363     (write _test-input-stream "  var b/ebx: int <- copy 0\n")
    11364     (write _test-input-stream "  var c/ecx: (addr int) <- index a, b\n")
    11365     (write _test-input-stream "}\n")
    11366     (write _test-input-stream "type t {\n")  # size 12 is not a power of two
    11367     (write _test-input-stream "  x: int\n")
    11368     (write _test-input-stream "  y: int\n")
    11369     (write _test-input-stream "  z: int\n")
    11370     (write _test-input-stream "}\n")
    11371     # convert
    11372     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    11373     # registers except esp clobbered at this point
    11374     # restore ed
    11375     89/<- %edx 4/r32/esp
    11376     (flush _test-output-buffered-file)
    11377     (flush _test-error-buffered-file)
    11378 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
    11384     # check output
    11385     (check-stream-equal _test-output-stream  ""  "F - test-index-needs-offset-type: output should be empty")
    11386     (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")
    11387     # check that stop(1) was called
    11388     (check-ints-equal *(edx+4) 2 "F - test-index-needs-offset-type: exit status")
    11389     # don't restore from ebp
    11390     81 0/subop/add %esp 8/imm32
    11391     # . epilogue
    11392     5d/pop-to-ebp
    11393     c3/return
    11394
    11395 test-index-with-output-not-address:
    11396     # . prologue
    11397     55/push-ebp
    11398     89/<- %ebp 4/r32/esp
    11399     # setup
    11400     (clear-stream _test-input-stream)
    11401     (clear-stream $_test-input-buffered-file->buffer)
    11402     (clear-stream _test-output-stream)
    11403     (clear-stream $_test-output-buffered-file->buffer)
    11404     (clear-stream _test-error-stream)
    11405     (clear-stream $_test-error-buffered-file->buffer)
    11406     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    11407     68/push 0/imm32
    11408     68/push 0/imm32
    11409     89/<- %edx 4/r32/esp
    11410     (tailor-exit-descriptor %edx 0x10)
    11411     #
    11412     (write _test-input-stream "fn foo {\n")
    11413     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
    11414     (write _test-input-stream "  var o/edi: int <- index a, 0\n")
    11415     (write _test-input-stream "}\n")
    11416     # convert
    11417     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    11418     # registers except esp clobbered at this point
    11419     # restore ed
    11420     89/<- %edx 4/r32/esp
    11421     (flush _test-output-buffered-file)
    11422     (flush _test-error-buffered-file)
    11423 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
    11429     # check output
    11430     (check-stream-equal _test-output-stream  ""  "F - test-index-with-output-not-address: output should be empty")
    11431     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt index: output 'o' must be an addr"  "F - test-index-with-output-not-address: error message")
    11432     # check that stop(1) was called
    11433     (check-ints-equal *(edx+4) 2 "F - test-index-with-output-not-address: exit status")
    11434     # don't restore from ebp
    11435     81 0/subop/add %esp 8/imm32
    11436     # . epilogue
    11437     5d/pop-to-ebp
    11438     c3/return
    11439
    11440 test-index-with-output-not-address-2:
    11441     # . prologue
    11442     55/push-ebp
    11443     89/<- %ebp 4/r32/esp
    11444     # setup
    11445     (clear-stream _test-input-stream)
    11446     (clear-stream $_test-input-buffered-file->buffer)
    11447     (clear-stream _test-output-stream)
    11448     (clear-stream $_test-output-buffered-file->buffer)
    11449     (clear-stream _test-error-stream)
    11450     (clear-stream $_test-error-buffered-file->buffer)
    11451     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    11452     68/push 0/imm32
    11453     68/push 0/imm32
    11454     89/<- %edx 4/r32/esp
    11455     (tailor-exit-descriptor %edx 0x10)
    11456     #
    11457     (write _test-input-stream "fn foo {\n")
    11458     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
    11459     (write _test-input-stream "  var o/edi: (int) <- index a, 0\n")
    11460     (write _test-input-stream "}\n")
    11461     # convert
    11462     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    11463     # registers except esp clobbered at this point
    11464     # restore ed
    11465     89/<- %edx 4/r32/esp
    11466     (flush _test-output-buffered-file)
    11467     (flush _test-error-buffered-file)
    11468 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
    11474     # check output
    11475     (check-stream-equal _test-output-stream  ""  "F - test-index-with-output-not-address-2: output should be empty")
    11476     (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")
    11477     # check that stop(1) was called
    11478     (check-ints-equal *(edx+4) 2 "F - test-index-with-output-not-address-2: exit status")
    11479     # don't restore from ebp
    11480     81 0/subop/add %esp 8/imm32
    11481     # . epilogue
    11482     5d/pop-to-ebp
    11483     c3/return
    11484
    11485 test-index-with-wrong-output-type:
    11486     # . prologue
    11487     55/push-ebp
    11488     89/<- %ebp 4/r32/esp
    11489     # setup
    11490     (clear-stream _test-input-stream)
    11491     (clear-stream $_test-input-buffered-file->buffer)
    11492     (clear-stream _test-output-stream)
    11493     (clear-stream $_test-output-buffered-file->buffer)
    11494     (clear-stream _test-error-stream)
    11495     (clear-stream $_test-error-buffered-file->buffer)
    11496     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    11497     68/push 0/imm32
    11498     68/push 0/imm32
    11499     89/<- %edx 4/r32/esp
    11500     (tailor-exit-descriptor %edx 0x10)
    11501     #
    11502     (write _test-input-stream "fn foo {\n")
    11503     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
    11504     (write _test-input-stream "  var o/edi: (addr int) <- index a, 0\n")
    11505     (write _test-input-stream "}\n")
    11506     # convert
    11507     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    11508     # registers except esp clobbered at this point
    11509     # restore ed
    11510     89/<- %edx 4/r32/esp
    11511     (flush _test-output-buffered-file)
    11512     (flush _test-error-buffered-file)
    11513 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
    11519     # check output
    11520     (check-stream-equal _test-output-stream  ""  "F - test-index-with-wrong-output-type: output should be empty")
    11521     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt index: output 'o' does not have the right type"  "F - test-index-with-wrong-output-type: error message")
    11522     # check that stop(1) was called
    11523     (check-ints-equal *(edx+4) 2 "F - test-index-with-wrong-output-type: exit status")
    11524     # don't restore from ebp
    11525     81 0/subop/add %esp 8/imm32
    11526     # . epilogue
    11527     5d/pop-to-ebp
    11528     c3/return
    11529
    11530 test-index-with-wrong-output-compound-type:
    11531     # . prologue
    11532     55/push-ebp
    11533     89/<- %ebp 4/r32/esp
    11534     # setup
    11535     (clear-stream _test-input-stream)
    11536     (clear-stream $_test-input-buffered-file->buffer)
    11537     (clear-stream _test-output-stream)
    11538     (clear-stream $_test-output-buffered-file->buffer)
    11539     (clear-stream _test-error-stream)
    11540     (clear-stream $_test-error-buffered-file->buffer)
    11541     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    11542     68/push 0/imm32
    11543     68/push 0/imm32
    11544     89/<- %edx 4/r32/esp
    11545     (tailor-exit-descriptor %edx 0x10)
    11546     #
    11547     (write _test-input-stream "fn foo {\n")
    11548     (write _test-input-stream "  var a/ebx: (addr array handle boolean) <- copy 0\n")
    11549     (write _test-input-stream "  var o/edi: (addr handle int) <- index a, 0\n")
    11550     (write _test-input-stream "}\n")
    11551     # convert
    11552     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    11553     # registers except esp clobbered at this point
    11554     # restore ed
    11555     89/<- %edx 4/r32/esp
    11556     (flush _test-output-buffered-file)
    11557     (flush _test-error-buffered-file)
    11558 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
    11564     # check output
    11565     (check-stream-equal _test-output-stream  ""  "F - test-index-with-wrong-output-compound-type: output should be empty")
    11566     (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")
    11567     # check that stop(1) was called
    11568     (check-ints-equal *(edx+4) 2 "F - test-index-with-wrong-output-compound-type: exit status")
    11569     # don't restore from ebp
    11570     81 0/subop/add %esp 8/imm32
    11571     # . epilogue
    11572     5d/pop-to-ebp
    11573     c3/return
    11574
    11575 test-index-with-no-inouts:
    11576     # . prologue
    11577     55/push-ebp
    11578     89/<- %ebp 4/r32/esp
    11579     # setup
    11580     (clear-stream _test-input-stream)
    11581     (clear-stream $_test-input-buffered-file->buffer)
    11582     (clear-stream _test-output-stream)
    11583     (clear-stream $_test-output-buffered-file->buffer)
    11584     (clear-stream _test-error-stream)
    11585     (clear-stream $_test-error-buffered-file->buffer)
    11586     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    11587     68/push 0/imm32
    11588     68/push 0/imm32
    11589     89/<- %edx 4/r32/esp
    11590     (tailor-exit-descriptor %edx 0x10)
    11591     #
    11592     (write _test-input-stream "fn foo {\n")
    11593     (write _test-input-stream "  var c/ecx: (addr int) <- index\n")
    11594     (write _test-input-stream "}\n")
    11595     # convert
    11596     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    11597     # registers except esp clobbered at this point
    11598     # restore ed
    11599     89/<- %edx 4/r32/esp
    11600     (flush _test-output-buffered-file)
    11601     (flush _test-error-buffered-file)
    11602 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
    11608     # check output
    11609     (check-stream-equal _test-output-stream  ""  "F - test-index-with-no-inouts: output should be empty")
    11610     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt index: too few inouts (2 required)"  "F - test-index-with-no-inouts: error message")
    11611     # check that stop(1) was called
    11612     (check-ints-equal *(edx+4) 2 "F - test-index-with-no-inouts: exit status")
    11613     # don't restore from ebp
    11614     81 0/subop/add %esp 8/imm32
    11615     # . epilogue
    11616     5d/pop-to-ebp
    11617     c3/return
    11618
    11619 test-index-with-too-few-inouts:
    11620     # . prologue
    11621     55/push-ebp
    11622     89/<- %ebp 4/r32/esp
    11623     # setup
    11624     (clear-stream _test-input-stream)
    11625     (clear-stream $_test-input-buffered-file->buffer)
    11626     (clear-stream _test-output-stream)
    11627     (clear-stream $_test-output-buffered-file->buffer)
    11628     (clear-stream _test-error-stream)
    11629     (clear-stream $_test-error-buffered-file->buffer)
    11630     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    11631     68/push 0/imm32
    11632     68/push 0/imm32
    11633     89/<- %edx 4/r32/esp
    11634     (tailor-exit-descriptor %edx 0x10)
    11635     #
    11636     (write _test-input-stream "fn foo {\n")
    11637     (write _test-input-stream "  var a: (array int 3)\n")
    11638     (write _test-input-stream "  var c/ecx: (addr int) <- index a\n")
    11639     (write _test-input-stream "}\n")
    11640     # convert
    11641     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    11642     # registers except esp clobbered at this point
    11643     # restore ed
    11644     89/<- %edx 4/r32/esp
    11645     (flush _test-output-buffered-file)
    11646     (flush _test-error-buffered-file)
    11647 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
    11653     # check output
    11654     (check-stream-equal _test-output-stream  ""  "F - test-index-with-too-few-inouts: output should be empty")
    11655     (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")
    11656     # check that stop(1) was called
    11657     (check-ints-equal *(edx+4) 2 "F - test-index-with-too-few-inouts: exit status")
    11658     # don't restore from ebp
    11659     81 0/subop/add %esp 8/imm32
    11660     # . epilogue
    11661     5d/pop-to-ebp
    11662     c3/return
    11663
    11664 test-index-with-too-many-inouts:
    11665     # . prologue
    11666     55/push-ebp
    11667     89/<- %ebp 4/r32/esp
    11668     # setup
    11669     (clear-stream _test-input-stream)
    11670     (clear-stream $_test-input-buffered-file->buffer)
    11671     (clear-stream _test-output-stream)
    11672     (clear-stream $_test-output-buffered-file->buffer)
    11673     (clear-stream _test-error-stream)
    11674     (clear-stream $_test-error-buffered-file->buffer)
    11675     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    11676     68/push 0/imm32
    11677     68/push 0/imm32
    11678     89/<- %edx 4/r32/esp
    11679     (tailor-exit-descriptor %edx 0x10)
    11680     #
    11681     (write _test-input-stream "fn foo {\n")
    11682     (write _test-input-stream "  var a: (array int 3)\n")
    11683     (write _test-input-stream "  var c/ecx: (addr int) <- index a, 0, 0\n")
    11684     (write _test-input-stream "}\n")
    11685     # convert
    11686     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    11687     # registers except esp clobbered at this point
    11688     # restore ed
    11689     89/<- %edx 4/r32/esp
    11690     (flush _test-output-buffered-file)
    11691     (flush _test-error-buffered-file)
    11692 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
    11698     # check output
    11699     (check-stream-equal _test-output-stream  ""  "F - test-index-with-too-many-inouts: output should be empty")
    11700     (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")
    11701     # check that stop(1) was called
    11702     (check-ints-equal *(edx+4) 2 "F - test-index-with-too-many-inouts: exit status")
    11703     # don't restore from ebp
    11704     81 0/subop/add %esp 8/imm32
    11705     # . epilogue
    11706     5d/pop-to-ebp
    11707     c3/return
    11708
    11709 test-index-with-no-output:
    11710     # . prologue
    11711     55/push-ebp
    11712     89/<- %ebp 4/r32/esp
    11713     # setup
    11714     (clear-stream _test-input-stream)
    11715     (clear-stream $_test-input-buffered-file->buffer)
    11716     (clear-stream _test-output-stream)
    11717     (clear-stream $_test-output-buffered-file->buffer)
    11718     (clear-stream _test-error-stream)
    11719     (clear-stream $_test-error-buffered-file->buffer)
    11720     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    11721     68/push 0/imm32
    11722     68/push 0/imm32
    11723     89/<- %edx 4/r32/esp
    11724     (tailor-exit-descriptor %edx 0x10)
    11725     #
    11726     (write _test-input-stream "fn foo {\n")
    11727     (write _test-input-stream "  var a: (array int 3)\n")
    11728     (write _test-input-stream "  index a, 0\n")
    11729     (write _test-input-stream "}\n")
    11730     # convert
    11731     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    11732     # registers except esp clobbered at this point
    11733     # restore ed
    11734     89/<- %edx 4/r32/esp
    11735     (flush _test-output-buffered-file)
    11736     (flush _test-error-buffered-file)
    11737 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
    11743     # check output
    11744     (check-stream-equal _test-output-stream  ""  "F - test-index-with-no-output: output should be empty")
    11745     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt index: must have an output"  "F - test-index-with-no-output: error message")
    11746     # check that stop(1) was called
    11747     (check-ints-equal *(edx+4) 2 "F - test-index-with-no-output: exit status")
    11748     # don't restore from ebp
    11749     81 0/subop/add %esp 8/imm32
    11750     # . epilogue
    11751     5d/pop-to-ebp
    11752     c3/return
    11753
    11754 test-index-with-too-many-outputs:
    11755     # . prologue
    11756     55/push-ebp
    11757     89/<- %ebp 4/r32/esp
    11758     # setup
    11759     (clear-stream _test-input-stream)
    11760     (clear-stream $_test-input-buffered-file->buffer)
    11761     (clear-stream _test-output-stream)
    11762     (clear-stream $_test-output-buffered-file->buffer)
    11763     (clear-stream _test-error-stream)
    11764     (clear-stream $_test-error-buffered-file->buffer)
    11765     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    11766     68/push 0/imm32
    11767     68/push 0/imm32
    11768     89/<- %edx 4/r32/esp
    11769     (tailor-exit-descriptor %edx 0x10)
    11770     #
    11771     (write _test-input-stream "fn foo {\n")
    11772     (write _test-input-stream "  var a: (array int 3)\n")
    11773     (write _test-input-stream "  var b/eax: (addr int) <- copy 0\n")
    11774     (write _test-input-stream "  var c/ecx: (addr int) <- copy 0\n")
    11775     (write _test-input-stream "  b, c <- index a, 0\n")
    11776     (write _test-input-stream "}\n")
    11777     # convert
    11778     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    11779     # registers except esp clobbered at this point
    11780     # restore ed
    11781     89/<- %edx 4/r32/esp
    11782     (flush _test-output-buffered-file)
    11783     (flush _test-error-buffered-file)
    11784 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
    11790     # check output
    11791     (check-stream-equal _test-output-stream  ""  "F - test-index-with-too-many-outputs: output should be empty")
    11792     (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")
    11793     # check that stop(1) was called
    11794     (check-ints-equal *(edx+4) 2 "F - test-index-with-too-many-outputs: exit status")
    11795     # don't restore from ebp
    11796     81 0/subop/add %esp 8/imm32
    11797     # . epilogue
    11798     5d/pop-to-ebp
    11799     c3/return
    11800
    11801 test-compute-offset-with-non-array-atom-base-type:
    11802     # . prologue
    11803     55/push-ebp
    11804     89/<- %ebp 4/r32/esp
    11805     # setup
    11806     (clear-stream _test-input-stream)
    11807     (clear-stream $_test-input-buffered-file->buffer)
    11808     (clear-stream _test-output-stream)
    11809     (clear-stream $_test-output-buffered-file->buffer)
    11810     (clear-stream _test-error-stream)
    11811     (clear-stream $_test-error-buffered-file->buffer)
    11812     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    11813     68/push 0/imm32
    11814     68/push 0/imm32
    11815     89/<- %edx 4/r32/esp
    11816     (tailor-exit-descriptor %edx 0x10)
    11817     #
    11818     (write _test-input-stream "fn foo {\n")
    11819     (write _test-input-stream "  var a: int\n")
    11820     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a, 0\n")
    11821     (write _test-input-stream "}\n")
    11822     # convert
    11823     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    11824     # registers except esp clobbered at this point
    11825     # restore ed
    11826     89/<- %edx 4/r32/esp
    11827     (flush _test-output-buffered-file)
    11828     (flush _test-error-buffered-file)
    11829 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
    11835     # check output
    11836     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-non-array-atom-base-type: output should be empty")
    11837     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt compute-offset: var 'a' is not an array"  "F - test-compute-offset-with-non-array-atom-base-type: error message")
    11838     # check that stop(1) was called
    11839     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-non-array-atom-base-type: exit status")
    11840     # don't restore from ebp
    11841     81 0/subop/add %esp 8/imm32
    11842     # . epilogue
    11843     5d/pop-to-ebp
    11844     c3/return
    11845
    11846 test-compute-offset-with-non-array-compound-base-type:
    11847     # . prologue
    11848     55/push-ebp
    11849     89/<- %ebp 4/r32/esp
    11850     # setup
    11851     (clear-stream _test-input-stream)
    11852     (clear-stream $_test-input-buffered-file->buffer)
    11853     (clear-stream _test-output-stream)
    11854     (clear-stream $_test-output-buffered-file->buffer)
    11855     (clear-stream _test-error-stream)
    11856     (clear-stream $_test-error-buffered-file->buffer)
    11857     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    11858     68/push 0/imm32
    11859     68/push 0/imm32
    11860     89/<- %edx 4/r32/esp
    11861     (tailor-exit-descriptor %edx 0x10)
    11862     #
    11863     (write _test-input-stream "fn foo {\n")
    11864     (write _test-input-stream "  var a: (handle int)\n")
    11865     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a, 0\n")
    11866     (write _test-input-stream "}\n")
    11867     # convert
    11868     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    11869     # registers except esp clobbered at this point
    11870     # restore ed
    11871     89/<- %edx 4/r32/esp
    11872     (flush _test-output-buffered-file)
    11873     (flush _test-error-buffered-file)
    11874 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
    11880     # check output
    11881     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-non-array-compound-base-type: output should be empty")
    11882     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt compute-offset: var 'a' is not an array"  "F - test-compute-offset-with-non-array-compound-base-type: error message")
    11883     # check that stop(1) was called
    11884     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-non-array-compound-base-type: exit status")
    11885     # don't restore from ebp
    11886     81 0/subop/add %esp 8/imm32
    11887     # . epilogue
    11888     5d/pop-to-ebp
    11889     c3/return
    11890
    11891 test-compute-offset-with-non-array-compound-base-type-2:
    11892     # . prologue
    11893     55/push-ebp
    11894     89/<- %ebp 4/r32/esp
    11895     # setup
    11896     (clear-stream _test-input-stream)
    11897     (clear-stream $_test-input-buffered-file->buffer)
    11898     (clear-stream _test-output-stream)
    11899     (clear-stream $_test-output-buffered-file->buffer)
    11900     (clear-stream _test-error-stream)
    11901     (clear-stream $_test-error-buffered-file->buffer)
    11902     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    11903     68/push 0/imm32
    11904     68/push 0/imm32
    11905     89/<- %edx 4/r32/esp
    11906     (tailor-exit-descriptor %edx 0x10)
    11907     #
    11908     (write _test-input-stream "fn foo {\n")
    11909     (write _test-input-stream "  var a: (addr int)\n")
    11910     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a, 0\n")
    11911     (write _test-input-stream "}\n")
    11912     # convert
    11913     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    11914     # registers except esp clobbered at this point
    11915     # restore ed
    11916     89/<- %edx 4/r32/esp
    11917     (flush _test-output-buffered-file)
    11918     (flush _test-error-buffered-file)
    11919 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
    11925     # check output
    11926     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-non-array-compound-base-type-2: output should be empty")
    11927     (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")
    11928     # check that stop(1) was called
    11929     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-non-array-compound-base-type-2: exit status")
    11930     # don't restore from ebp
    11931     81 0/subop/add %esp 8/imm32
    11932     # . epilogue
    11933     5d/pop-to-ebp
    11934     c3/return
    11935
    11936 test-compute-offset-with-array-atom-base-type:
    11937     # . prologue
    11938     55/push-ebp
    11939     89/<- %ebp 4/r32/esp
    11940     # setup
    11941     (clear-stream _test-input-stream)
    11942     (clear-stream $_test-input-buffered-file->buffer)
    11943     (clear-stream _test-output-stream)
    11944     (clear-stream $_test-output-buffered-file->buffer)
    11945     (clear-stream _test-error-stream)
    11946     (clear-stream $_test-error-buffered-file->buffer)
    11947     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    11948     68/push 0/imm32
    11949     68/push 0/imm32
    11950     89/<- %edx 4/r32/esp
    11951     (tailor-exit-descriptor %edx 0x10)
    11952     #
    11953     (write _test-input-stream "fn foo {\n")
    11954     (write _test-input-stream "  var a: array\n")
    11955     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a, 0\n")
    11956     (write _test-input-stream "}\n")
    11957     # convert
    11958     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    11959     # registers except esp clobbered at this point
    11960     # restore ed
    11961     89/<- %edx 4/r32/esp
    11962     (flush _test-output-buffered-file)
    11963     (flush _test-error-buffered-file)
    11964 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
    11970     # check output
    11971     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-array-atom-base-type: output should be empty")
    11972     (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")
    11973     # check that stop(1) was called
    11974     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-array-atom-base-type: exit status")
    11975     # don't restore from ebp
    11976     81 0/subop/add %esp 8/imm32
    11977     # . epilogue
    11978     5d/pop-to-ebp
    11979     c3/return
    11980
    11981 test-compute-offset-with-wrong-index-type:
    11982     # . prologue
    11983     55/push-ebp
    11984     89/<- %ebp 4/r32/esp
    11985     # setup
    11986     (clear-stream _test-input-stream)
    11987     (clear-stream $_test-input-buffered-file->buffer)
    11988     (clear-stream _test-output-stream)
    11989     (clear-stream $_test-output-buffered-file->buffer)
    11990     (clear-stream _test-error-stream)
    11991     (clear-stream $_test-error-buffered-file->buffer)
    11992     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    11993     68/push 0/imm32
    11994     68/push 0/imm32
    11995     89/<- %edx 4/r32/esp
    11996     (tailor-exit-descriptor %edx 0x10)
    11997     #
    11998     (write _test-input-stream "fn foo {\n")
    11999     (write _test-input-stream "  var a/eax: (addr array int) <- copy 0\n")
    12000     (write _test-input-stream "  var b: boolean\n")
    12001     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a, b\n")
    12002     (write _test-input-stream "}\n")
    12003     # convert
    12004     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    12005     # registers except esp clobbered at this point
    12006     # restore ed
    12007     89/<- %edx 4/r32/esp
    12008     (flush _test-output-buffered-file)
    12009     (flush _test-error-buffered-file)
    12010 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
    12016     # check output
    12017     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-wrong-index-type: output should be empty")
    12018     (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")
    12019     # check that stop(1) was called
    12020     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-wrong-index-type: exit status")
    12021     # don't restore from ebp
    12022     81 0/subop/add %esp 8/imm32
    12023     # . epilogue
    12024     5d/pop-to-ebp
    12025     c3/return
    12026
    12027 test-compute-offset-with-output-not-offset:
    12028     # . prologue
    12029     55/push-ebp
    12030     89/<- %ebp 4/r32/esp
    12031     # setup
    12032     (clear-stream _test-input-stream)
    12033     (clear-stream $_test-input-buffered-file->buffer)
    12034     (clear-stream _test-output-stream)
    12035     (clear-stream $_test-output-buffered-file->buffer)
    12036     (clear-stream _test-error-stream)
    12037     (clear-stream $_test-error-buffered-file->buffer)
    12038     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    12039     68/push 0/imm32
    12040     68/push 0/imm32
    12041     89/<- %edx 4/r32/esp
    12042     (tailor-exit-descriptor %edx 0x10)
    12043     #
    12044     (write _test-input-stream "fn foo {\n")
    12045     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
    12046     (write _test-input-stream "  var o/edi: int <- compute-offset a, 0\n")
    12047     (write _test-input-stream "}\n")
    12048     # convert
    12049     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    12050     # registers except esp clobbered at this point
    12051     # restore ed
    12052     89/<- %edx 4/r32/esp
    12053     (flush _test-output-buffered-file)
    12054     (flush _test-error-buffered-file)
    12055 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
    12061     # check output
    12062     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-output-not-offset: output should be empty")
    12063     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt compute-offset: output 'o' must be an offset"  "F - test-compute-offset-with-output-not-offset: error message")
    12064     # check that stop(1) was called
    12065     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-output-not-offset: exit status")
    12066     # don't restore from ebp
    12067     81 0/subop/add %esp 8/imm32
    12068     # . epilogue
    12069     5d/pop-to-ebp
    12070     c3/return
    12071
    12072 test-compute-offset-with-output-not-address-2:
    12073     # . prologue
    12074     55/push-ebp
    12075     89/<- %ebp 4/r32/esp
    12076     # setup
    12077     (clear-stream _test-input-stream)
    12078     (clear-stream $_test-input-buffered-file->buffer)
    12079     (clear-stream _test-output-stream)
    12080     (clear-stream $_test-output-buffered-file->buffer)
    12081     (clear-stream _test-error-stream)
    12082     (clear-stream $_test-error-buffered-file->buffer)
    12083     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    12084     68/push 0/imm32
    12085     68/push 0/imm32
    12086     89/<- %edx 4/r32/esp
    12087     (tailor-exit-descriptor %edx 0x10)
    12088     #
    12089     (write _test-input-stream "fn foo {\n")
    12090     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
    12091     (write _test-input-stream "  var o/edi: (int) <- compute-offset a, 0\n")
    12092     (write _test-input-stream "}\n")
    12093     # convert
    12094     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    12095     # registers except esp clobbered at this point
    12096     # restore ed
    12097     89/<- %edx 4/r32/esp
    12098     (flush _test-output-buffered-file)
    12099     (flush _test-error-buffered-file)
    12100 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
    12106     # check output
    12107     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-output-not-address-2: output should be empty")
    12108     (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")
    12109     # check that stop(1) was called
    12110     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-output-not-address-2: exit status")
    12111     # don't restore from ebp
    12112     81 0/subop/add %esp 8/imm32
    12113     # . epilogue
    12114     5d/pop-to-ebp
    12115     c3/return
    12116
    12117 test-compute-offset-with-wrong-output-type:
    12118     # . prologue
    12119     55/push-ebp
    12120     89/<- %ebp 4/r32/esp
    12121     # setup
    12122     (clear-stream _test-input-stream)
    12123     (clear-stream $_test-input-buffered-file->buffer)
    12124     (clear-stream _test-output-stream)
    12125     (clear-stream $_test-output-buffered-file->buffer)
    12126     (clear-stream _test-error-stream)
    12127     (clear-stream $_test-error-buffered-file->buffer)
    12128     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    12129     68/push 0/imm32
    12130     68/push 0/imm32
    12131     89/<- %edx 4/r32/esp
    12132     (tailor-exit-descriptor %edx 0x10)
    12133     #
    12134     (write _test-input-stream "fn foo {\n")
    12135     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
    12136     (write _test-input-stream "  var o/edi: (offset int) <- compute-offset a, 0\n")
    12137     (write _test-input-stream "}\n")
    12138     # convert
    12139     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    12140     # registers except esp clobbered at this point
    12141     # restore ed
    12142     89/<- %edx 4/r32/esp
    12143     (flush _test-output-buffered-file)
    12144     (flush _test-error-buffered-file)
    12145 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
    12151     # check output
    12152     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-wrong-output-type: output should be empty")
    12153     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt compute-offset: output 'o' does not have the right type"  "F - test-compute-offset-with-wrong-output-type: error message")
    12154     # check that stop(1) was called
    12155     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-wrong-output-type: exit status")
    12156     # don't restore from ebp
    12157     81 0/subop/add %esp 8/imm32
    12158     # . epilogue
    12159     5d/pop-to-ebp
    12160     c3/return
    12161
    12162 test-compute-offset-with-wrong-output-compound-type:
    12163     # . prologue
    12164     55/push-ebp
    12165     89/<- %ebp 4/r32/esp
    12166     # setup
    12167     (clear-stream _test-input-stream)
    12168     (clear-stream $_test-input-buffered-file->buffer)
    12169     (clear-stream _test-output-stream)
    12170     (clear-stream $_test-output-buffered-file->buffer)
    12171     (clear-stream _test-error-stream)
    12172     (clear-stream $_test-error-buffered-file->buffer)
    12173     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    12174     68/push 0/imm32
    12175     68/push 0/imm32
    12176     89/<- %edx 4/r32/esp
    12177     (tailor-exit-descriptor %edx 0x10)
    12178     #
    12179     (write _test-input-stream "fn foo {\n")
    12180     (write _test-input-stream "  var a/ebx: (addr array handle boolean) <- copy 0\n")
    12181     (write _test-input-stream "  var o/edi: (offset handle int) <- compute-offset a, 0\n")
    12182     (write _test-input-stream "}\n")
    12183     # convert
    12184     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    12185     # registers except esp clobbered at this point
    12186     # restore ed
    12187     89/<- %edx 4/r32/esp
    12188     (flush _test-output-buffered-file)
    12189     (flush _test-error-buffered-file)
    12190 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
    12196     # check output
    12197     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-wrong-output-compound-type: output should be empty")
    12198     (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")
    12199     # check that stop(1) was called
    12200     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-wrong-output-compound-type: exit status")
    12201     # don't restore from ebp
    12202     81 0/subop/add %esp 8/imm32
    12203     # . epilogue
    12204     5d/pop-to-ebp
    12205     c3/return
    12206
    12207 test-compute-offset-with-no-inouts:
    12208     # . prologue
    12209     55/push-ebp
    12210     89/<- %ebp 4/r32/esp
    12211     # setup
    12212     (clear-stream _test-input-stream)
    12213     (clear-stream $_test-input-buffered-file->buffer)
    12214     (clear-stream _test-output-stream)
    12215     (clear-stream $_test-output-buffered-file->buffer)
    12216     (clear-stream _test-error-stream)
    12217     (clear-stream $_test-error-buffered-file->buffer)
    12218     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    12219     68/push 0/imm32
    12220     68/push 0/imm32
    12221     89/<- %edx 4/r32/esp
    12222     (tailor-exit-descriptor %edx 0x10)
    12223     #
    12224     (write _test-input-stream "fn foo {\n")
    12225     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset\n")
    12226     (write _test-input-stream "}\n")
    12227     # convert
    12228     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    12229     # registers except esp clobbered at this point
    12230     # restore ed
    12231     89/<- %edx 4/r32/esp
    12232     (flush _test-output-buffered-file)
    12233     (flush _test-error-buffered-file)
    12234 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
    12240     # check output
    12241     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-no-inouts: output should be empty")
    12242     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt compute-offset: too few inouts (2 required)"  "F - test-compute-offset-with-no-inouts: error message")
    12243     # check that stop(1) was called
    12244     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-no-inouts: exit status")
    12245     # don't restore from ebp
    12246     81 0/subop/add %esp 8/imm32
    12247     # . epilogue
    12248     5d/pop-to-ebp
    12249     c3/return
    12250
    12251 test-compute-offset-with-too-few-inouts:
    12252     # . prologue
    12253     55/push-ebp
    12254     89/<- %ebp 4/r32/esp
    12255     # setup
    12256     (clear-stream _test-input-stream)
    12257     (clear-stream $_test-input-buffered-file->buffer)
    12258     (clear-stream _test-output-stream)
    12259     (clear-stream $_test-output-buffered-file->buffer)
    12260     (clear-stream _test-error-stream)
    12261     (clear-stream $_test-error-buffered-file->buffer)
    12262     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    12263     68/push 0/imm32
    12264     68/push 0/imm32
    12265     89/<- %edx 4/r32/esp
    12266     (tailor-exit-descriptor %edx 0x10)
    12267     #
    12268     (write _test-input-stream "fn foo {\n")
    12269     (write _test-input-stream "  var a: (array int 3)\n")
    12270     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a\n")
    12271     (write _test-input-stream "}\n")
    12272     # convert
    12273     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    12274     # registers except esp clobbered at this point
    12275     # restore ed
    12276     89/<- %edx 4/r32/esp
    12277     (flush _test-output-buffered-file)
    12278     (flush _test-error-buffered-file)
    12279 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
    12285     # check output
    12286     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-too-few-inouts: output should be empty")
    12287     (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")
    12288     # check that stop(1) was called
    12289     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-too-few-inouts: exit status")
    12290     # don't restore from ebp
    12291     81 0/subop/add %esp 8/imm32
    12292     # . epilogue
    12293     5d/pop-to-ebp
    12294     c3/return
    12295
    12296 test-compute-offset-with-too-many-inouts:
    12297     # . prologue
    12298     55/push-ebp
    12299     89/<- %ebp 4/r32/esp
    12300     # setup
    12301     (clear-stream _test-input-stream)
    12302     (clear-stream $_test-input-buffered-file->buffer)
    12303     (clear-stream _test-output-stream)
    12304     (clear-stream $_test-output-buffered-file->buffer)
    12305     (clear-stream _test-error-stream)
    12306     (clear-stream $_test-error-buffered-file->buffer)
    12307     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    12308     68/push 0/imm32
    12309     68/push 0/imm32
    12310     89/<- %edx 4/r32/esp
    12311     (tailor-exit-descriptor %edx 0x10)
    12312     #
    12313     (write _test-input-stream "fn foo {\n")
    12314     (write _test-input-stream "  var a: (array int 3)\n")
    12315     (write _test-input-stream "  var c/ecx: (offset int) <- compute-offset a, 0, 0\n")
    12316     (write _test-input-stream "}\n")
    12317     # convert
    12318     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    12319     # registers except esp clobbered at this point
    12320     # restore ed
    12321     89/<- %edx 4/r32/esp
    12322     (flush _test-output-buffered-file)
    12323     (flush _test-error-buffered-file)
    12324 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
    12330     # check output
    12331     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-too-many-inouts: output should be empty")
    12332     (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")
    12333     # check that stop(1) was called
    12334     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-too-many-inouts: exit status")
    12335     # don't restore from ebp
    12336     81 0/subop/add %esp 8/imm32
    12337     # . epilogue
    12338     5d/pop-to-ebp
    12339     c3/return
    12340
    12341 test-compute-offset-with-no-output:
    12342     # . prologue
    12343     55/push-ebp
    12344     89/<- %ebp 4/r32/esp
    12345     # setup
    12346     (clear-stream _test-input-stream)
    12347     (clear-stream $_test-input-buffered-file->buffer)
    12348     (clear-stream _test-output-stream)
    12349     (clear-stream $_test-output-buffered-file->buffer)
    12350     (clear-stream _test-error-stream)
    12351     (clear-stream $_test-error-buffered-file->buffer)
    12352     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    12353     68/push 0/imm32
    12354     68/push 0/imm32
    12355     89/<- %edx 4/r32/esp
    12356     (tailor-exit-descriptor %edx 0x10)
    12357     #
    12358     (write _test-input-stream "fn foo {\n")
    12359     (write _test-input-stream "  var a: (array int 3)\n")
    12360     (write _test-input-stream "  compute-offset a, 0\n")
    12361     (write _test-input-stream "}\n")
    12362     # convert
    12363     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    12364     # registers except esp clobbered at this point
    12365     # restore ed
    12366     89/<- %edx 4/r32/esp
    12367     (flush _test-output-buffered-file)
    12368     (flush _test-error-buffered-file)
    12369 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
    12375     # check output
    12376     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-no-output: output should be empty")
    12377     (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")
    12378     # check that stop(1) was called
    12379     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-no-output: exit status")
    12380     # don't restore from ebp
    12381     81 0/subop/add %esp 8/imm32
    12382     # . epilogue
    12383     5d/pop-to-ebp
    12384     c3/return
    12385
    12386 test-compute-offset-with-too-many-outputs:
    12387     # . prologue
    12388     55/push-ebp
    12389     89/<- %ebp 4/r32/esp
    12390     # setup
    12391     (clear-stream _test-input-stream)
    12392     (clear-stream $_test-input-buffered-file->buffer)
    12393     (clear-stream _test-output-stream)
    12394     (clear-stream $_test-output-buffered-file->buffer)
    12395     (clear-stream _test-error-stream)
    12396     (clear-stream $_test-error-buffered-file->buffer)
    12397     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    12398     68/push 0/imm32
    12399     68/push 0/imm32
    12400     89/<- %edx 4/r32/esp
    12401     (tailor-exit-descriptor %edx 0x10)
    12402     #
    12403     (write _test-input-stream "fn foo {\n")
    12404     (write _test-input-stream "  var a: (array int 3)\n")
    12405     (write _test-input-stream "  var b/eax: (offset int) <- compute-offset a, 0\n")
    12406     (write _test-input-stream "  var c/ecx: (addr int) <- copy 0\n")
    12407     (write _test-input-stream "  b, c <- compute-offset a, 0\n")
    12408     (write _test-input-stream "}\n")
    12409     # convert
    12410     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    12411     # registers except esp clobbered at this point
    12412     # restore ed
    12413     89/<- %edx 4/r32/esp
    12414     (flush _test-output-buffered-file)
    12415     (flush _test-error-buffered-file)
    12416 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
    12422     # check output
    12423     (check-stream-equal _test-output-stream  ""  "F - test-compute-offset-with-too-many-outputs: output should be empty")
    12424     (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")
    12425     # check that stop(1) was called
    12426     (check-ints-equal *(edx+4) 2 "F - test-compute-offset-with-too-many-outputs: exit status")
    12427     # don't restore from ebp
    12428     81 0/subop/add %esp 8/imm32
    12429     # . epilogue
    12430     5d/pop-to-ebp
    12431     c3/return
    12432
    12433 test-convert-read-from-stream:
    12434     # . prologue
    12435     55/push-ebp
    12436     89/<- %ebp 4/r32/esp
    12437     # setup
    12438     (clear-stream _test-input-stream)
    12439     (clear-stream $_test-input-buffered-file->buffer)
    12440     (clear-stream _test-output-stream)
    12441     (clear-stream $_test-output-buffered-file->buffer)
    12442     #
    12443     (write _test-input-stream "fn foo {\n")
    12444     (write _test-input-stream "  var s/esi: (addr stream int) <- copy 0\n")
    12445     (write _test-input-stream "  var o/ecx: (addr int) <- copy 0\n")
    12446     (write _test-input-stream "  read-from-stream s, o\n")
    12447     (write _test-input-stream "}\n")
    12448     # convert
    12449     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
    12450     # registers except esp clobbered at this point
    12451     # restore ed
    12452     89/<- %edx 4/r32/esp
    12453     (flush _test-output-buffered-file)
    12454     (flush _test-error-buffered-file)
    12455 +--  6 lines: #?     # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------
    12461     # check output
    12462     (check-next-stream-line-equal _test-output-stream "foo:"                            "F - test-convert-read-from-stream/0")
    12463     (check-next-stream-line-equal _test-output-stream "  # . prologue"                  "F - test-convert-read-from-stream/1")
    12464     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                   "F - test-convert-read-from-stream/2")
    12465     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"          "F - test-convert-read-from-stream/3")
    12466     (check-next-stream-line-equal _test-output-stream "  {"                             "F - test-convert-read-from-stream/4")
    12467     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"           "F - test-convert-read-from-stream/5")
    12468     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %esi"        "F - test-convert-read-from-stream/6")
    12469     (check-next-stream-line-equal _test-output-stream "    be/copy-to-esi 0/imm32"      "F - test-convert-read-from-stream/7")
    12470     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"        "F - test-convert-read-from-stream/8")
    12471     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"      "F - test-convert-read-from-stream/9")
    12472     (check-next-stream-line-equal _test-output-stream "    (read-from-stream %esi %ecx 0x00000004)"  "F - test-convert-read-from-stream/10")
    12473     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"         "F - test-convert-read-from-stream/11")
    12474     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %esi"         "F - test-convert-read-from-stream/12")
    12475     (check-next-stream-line-equal _test-output-stream "  }"                             "F - test-convert-read-from-stream/13")
    12476     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"          "F - test-convert-read-from-stream/14")
    12477     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                  "F - test-convert-read-from-stream/15")
    12478     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"          "F - test-convert-read-from-stream/16")
    12479     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                 "F - test-convert-read-from-stream/17")
    12480     (check-next-stream-line-equal _test-output-stream "  c3/return"                     "F - test-convert-read-from-stream/18")
    12481     # . epilogue
    12482     89/<- %esp 5/r32/ebp
    12483     5d/pop-to-ebp
    12484     c3/return
    12485
    12486 test-convert-read-from-stream-with-correct-payload-size:
    12487     # . prologue
    12488     55/push-ebp
    12489     89/<- %ebp 4/r32/esp
    12490     # setup
    12491     (clear-stream _test-input-stream)
    12492     (clear-stream $_test-input-buffered-file->buffer)
    12493     (clear-stream _test-output-stream)
    12494     (clear-stream $_test-output-buffered-file->buffer)
    12495     #
    12496     (write _test-input-stream "fn foo {\n")
    12497     (write _test-input-stream "  var s/esi: (addr stream handle int) <- copy 0\n")
    12498     (write _test-input-stream "  var o/ecx: (addr handle int) <- copy 0\n")
    12499     (write _test-input-stream "  read-from-stream s, o\n")
    12500     (write _test-input-stream "}\n")
    12501     # convert
    12502     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
    12503     # registers except esp clobbered at this point
    12504     # restore ed
    12505     89/<- %edx 4/r32/esp
    12506     (flush _test-output-buffered-file)
    12507     (flush _test-error-buffered-file)
    12508 +--  6 lines: #?     # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------
    12514     # check output
    12515     (check-next-stream-line-equal _test-output-stream "foo:"                            "F - test-convert-read-from-stream-with-correct-payload-size/0")
    12516     (check-next-stream-line-equal _test-output-stream "  # . prologue"                  "F - test-convert-read-from-stream-with-correct-payload-size/1")
    12517     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                   "F - test-convert-read-from-stream-with-correct-payload-size/2")
    12518     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"          "F - test-convert-read-from-stream-with-correct-payload-size/3")
    12519     (check-next-stream-line-equal _test-output-stream "  {"                             "F - test-convert-read-from-stream-with-correct-payload-size/4")
    12520     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"           "F - test-convert-read-from-stream-with-correct-payload-size/5")
    12521     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %esi"        "F - test-convert-read-from-stream-with-correct-payload-size/6")
    12522     (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")
    12523     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"        "F - test-convert-read-from-stream-with-correct-payload-size/8")
    12524     (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")
    12525     (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")
    12526     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"         "F - test-convert-read-from-stream-with-correct-payload-size/11")
    12527     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %esi"         "F - test-convert-read-from-stream-with-correct-payload-size/12")
    12528     (check-next-stream-line-equal _test-output-stream "  }"                             "F - test-convert-read-from-stream-with-correct-payload-size/13")
    12529     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"          "F - test-convert-read-from-stream-with-correct-payload-size/14")
    12530     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                  "F - test-convert-read-from-stream-with-correct-payload-size/15")
    12531     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"          "F - test-convert-read-from-stream-with-correct-payload-size/16")
    12532     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                 "F - test-convert-read-from-stream-with-correct-payload-size/17")
    12533     (check-next-stream-line-equal _test-output-stream "  c3/return"                     "F - test-convert-read-from-stream-with-correct-payload-size/18")
    12534     # . epilogue
    12535     89/<- %esp 5/r32/ebp
    12536     5d/pop-to-ebp
    12537     c3/return
    12538
    12539 test-read-from-stream-with-non-stream-atom-base-type:
    12540     # . prologue
    12541     55/push-ebp
    12542     89/<- %ebp 4/r32/esp
    12543     # setup
    12544     (clear-stream _test-input-stream)
    12545     (clear-stream $_test-input-buffered-file->buffer)
    12546     (clear-stream _test-output-stream)
    12547     (clear-stream $_test-output-buffered-file->buffer)
    12548     (clear-stream _test-error-stream)
    12549     (clear-stream $_test-error-buffered-file->buffer)
    12550     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    12551     68/push 0/imm32
    12552     68/push 0/imm32
    12553     89/<- %edx 4/r32/esp
    12554     (tailor-exit-descriptor %edx 0x10)
    12555     #
    12556     (write _test-input-stream "fn foo {\n")
    12557     (write _test-input-stream "  var a: int\n")
    12558     (write _test-input-stream "  read-from-stream a, 0\n")
    12559     (write _test-input-stream "}\n")
    12560     # convert
    12561     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    12562     # registers except esp clobbered at this point
    12563     # restore ed
    12564     89/<- %edx 4/r32/esp
    12565     (flush _test-output-buffered-file)
    12566     (flush _test-error-buffered-file)
    12567 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
    12573     # check output
    12574     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-non-stream-atom-base-type: output should be empty")
    12575     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt read-from-stream: var 'a' must be an addr to a stream"  "F - test-read-from-stream-with-non-stream-atom-base-type: error message")
    12576     # check that stop(1) was called
    12577     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-non-stream-atom-base-type: exit status")
    12578     # don't restore from ebp
    12579     81 0/subop/add %esp 8/imm32
    12580     # . epilogue
    12581     5d/pop-to-ebp
    12582     c3/return
    12583
    12584 test-read-from-stream-with-non-stream-compound-base-type:
    12585     # . prologue
    12586     55/push-ebp
    12587     89/<- %ebp 4/r32/esp
    12588     # setup
    12589     (clear-stream _test-input-stream)
    12590     (clear-stream $_test-input-buffered-file->buffer)
    12591     (clear-stream _test-output-stream)
    12592     (clear-stream $_test-output-buffered-file->buffer)
    12593     (clear-stream _test-error-stream)
    12594     (clear-stream $_test-error-buffered-file->buffer)
    12595     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    12596     68/push 0/imm32
    12597     68/push 0/imm32
    12598     89/<- %edx 4/r32/esp
    12599     (tailor-exit-descriptor %edx 0x10)
    12600     #
    12601     (write _test-input-stream "fn foo {\n")
    12602     (write _test-input-stream "  var a: (handle int)\n")
    12603     (write _test-input-stream "  read-from-stream a, 0\n")
    12604     (write _test-input-stream "}\n")
    12605     # convert
    12606     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    12607     # registers except esp clobbered at this point
    12608     # restore ed
    12609     89/<- %edx 4/r32/esp
    12610     (flush _test-output-buffered-file)
    12611     (flush _test-error-buffered-file)
    12612 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
    12618     # check output
    12619     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-non-stream-compound-base-type: output should be empty")
    12620     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt read-from-stream: var 'a' must be an addr to a stream"  "F - test-read-from-stream-with-non-stream-compound-base-type: error message")
    12621     # check that stop(1) was called
    12622     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-non-stream-compound-base-type: exit status")
    12623     # don't restore from ebp
    12624     81 0/subop/add %esp 8/imm32
    12625     # . epilogue
    12626     5d/pop-to-ebp
    12627     c3/return
    12628
    12629 test-read-from-stream-with-non-stream-compound-base-type-2:
    12630     # . prologue
    12631     55/push-ebp
    12632     89/<- %ebp 4/r32/esp
    12633     # setup
    12634     (clear-stream _test-input-stream)
    12635     (clear-stream $_test-input-buffered-file->buffer)
    12636     (clear-stream _test-output-stream)
    12637     (clear-stream $_test-output-buffered-file->buffer)
    12638     (clear-stream _test-error-stream)
    12639     (clear-stream $_test-error-buffered-file->buffer)
    12640     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    12641     68/push 0/imm32
    12642     68/push 0/imm32
    12643     89/<- %edx 4/r32/esp
    12644     (tailor-exit-descriptor %edx 0x10)
    12645     #
    12646     (write _test-input-stream "fn foo {\n")
    12647     (write _test-input-stream "  var a: (addr int)\n")
    12648     (write _test-input-stream "  read-from-stream a, 0\n")
    12649     (write _test-input-stream "}\n")
    12650     # convert
    12651     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    12652     # registers except esp clobbered at this point
    12653     # restore ed
    12654     89/<- %edx 4/r32/esp
    12655     (flush _test-output-buffered-file)
    12656     (flush _test-error-buffered-file)
    12657 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
    12663     # check output
    12664     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-non-stream-compound-base-type-2: output should be empty")
    12665     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt read-from-stream: var 'a' must be an addr to a stream"  "F - test-read-from-stream-with-non-stream-compound-base-type-2: error message")
    12666     # check that stop(1) was called
    12667     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-non-stream-compound-base-type-2: exit status")
    12668     # don't restore from ebp
    12669     81 0/subop/add %esp 8/imm32
    12670     # . epilogue
    12671     5d/pop-to-ebp
    12672     c3/return
    12673
    12674 test-read-from-stream-with-stream-atom-base-type:
    12675     # . prologue
    12676     55/push-ebp
    12677     89/<- %ebp 4/r32/esp
    12678     # setup
    12679     (clear-stream _test-input-stream)
    12680     (clear-stream $_test-input-buffered-file->buffer)
    12681     (clear-stream _test-output-stream)
    12682     (clear-stream $_test-output-buffered-file->buffer)
    12683     (clear-stream _test-error-stream)
    12684     (clear-stream $_test-error-buffered-file->buffer)
    12685     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    12686     68/push 0/imm32
    12687     68/push 0/imm32
    12688     89/<- %edx 4/r32/esp
    12689     (tailor-exit-descriptor %edx 0x10)
    12690     #
    12691     (write _test-input-stream "fn foo {\n")
    12692     (write _test-input-stream "  var a: stream\n")
    12693     (write _test-input-stream "  read-from-stream a, 0\n")
    12694     (write _test-input-stream "}\n")
    12695     # convert
    12696     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    12697     # registers except esp clobbered at this point
    12698     # restore ed
    12699     89/<- %edx 4/r32/esp
    12700     (flush _test-output-buffered-file)
    12701     (flush _test-error-buffered-file)
    12702 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
    12708     # check output
    12709     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-stream-atom-base-type: output should be empty")
    12710     (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")
    12711     # check that stop(1) was called
    12712     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-stream-atom-base-type: exit status")
    12713     # don't restore from ebp
    12714     81 0/subop/add %esp 8/imm32
    12715     # . epilogue
    12716     5d/pop-to-ebp
    12717     c3/return
    12718
    12719 test-read-from-stream-with-wrong-index-type:
    12720     # . prologue
    12721     55/push-ebp
    12722     89/<- %ebp 4/r32/esp
    12723     # setup
    12724     (clear-stream _test-input-stream)
    12725     (clear-stream $_test-input-buffered-file->buffer)
    12726     (clear-stream _test-output-stream)
    12727     (clear-stream $_test-output-buffered-file->buffer)
    12728     (clear-stream _test-error-stream)
    12729     (clear-stream $_test-error-buffered-file->buffer)
    12730     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    12731     68/push 0/imm32
    12732     68/push 0/imm32
    12733     89/<- %edx 4/r32/esp
    12734     (tailor-exit-descriptor %edx 0x10)
    12735     #
    12736     (write _test-input-stream "fn foo {\n")
    12737     (write _test-input-stream "  var a/eax: (addr stream int) <- copy 0\n")
    12738     (write _test-input-stream "  var b: boolean\n")
    12739     (write _test-input-stream "  read-from-stream a, b\n")
    12740     (write _test-input-stream "}\n")
    12741     # convert
    12742     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    12743     # registers except esp clobbered at this point
    12744     # restore ed
    12745     89/<- %edx 4/r32/esp
    12746     (flush _test-output-buffered-file)
    12747     (flush _test-error-buffered-file)
    12748 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
    12754     # check output
    12755     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-wrong-index-type: output should be empty")
    12756     (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")
    12757     # check that stop(1) was called
    12758     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-wrong-index-type: exit status")
    12759     # don't restore from ebp
    12760     81 0/subop/add %esp 8/imm32
    12761     # . epilogue
    12762     5d/pop-to-ebp
    12763     c3/return
    12764
    12765 test-read-from-stream-with-no-inouts:
    12766     # . prologue
    12767     55/push-ebp
    12768     89/<- %ebp 4/r32/esp
    12769     # setup
    12770     (clear-stream _test-input-stream)
    12771     (clear-stream $_test-input-buffered-file->buffer)
    12772     (clear-stream _test-output-stream)
    12773     (clear-stream $_test-output-buffered-file->buffer)
    12774     (clear-stream _test-error-stream)
    12775     (clear-stream $_test-error-buffered-file->buffer)
    12776     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    12777     68/push 0/imm32
    12778     68/push 0/imm32
    12779     89/<- %edx 4/r32/esp
    12780     (tailor-exit-descriptor %edx 0x10)
    12781     #
    12782     (write _test-input-stream "fn foo {\n")
    12783     (write _test-input-stream "  read-from-stream\n")
    12784     (write _test-input-stream "}\n")
    12785     # convert
    12786     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    12787     # registers except esp clobbered at this point
    12788     # restore ed
    12789     89/<- %edx 4/r32/esp
    12790     (flush _test-output-buffered-file)
    12791     (flush _test-error-buffered-file)
    12792 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
    12798     # check output
    12799     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-no-inouts: output should be empty")
    12800     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt read-from-stream: too few inouts (2 required)"  "F - test-read-from-stream-with-no-inouts: error message")
    12801     # check that stop(1) was called
    12802     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-no-inouts: exit status")
    12803     # don't restore from ebp
    12804     81 0/subop/add %esp 8/imm32
    12805     # . epilogue
    12806     5d/pop-to-ebp
    12807     c3/return
    12808
    12809 test-read-from-stream-with-too-few-inouts:
    12810     # . prologue
    12811     55/push-ebp
    12812     89/<- %ebp 4/r32/esp
    12813     # setup
    12814     (clear-stream _test-input-stream)
    12815     (clear-stream $_test-input-buffered-file->buffer)
    12816     (clear-stream _test-output-stream)
    12817     (clear-stream $_test-output-buffered-file->buffer)
    12818     (clear-stream _test-error-stream)
    12819     (clear-stream $_test-error-buffered-file->buffer)
    12820     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    12821     68/push 0/imm32
    12822     68/push 0/imm32
    12823     89/<- %edx 4/r32/esp
    12824     (tailor-exit-descriptor %edx 0x10)
    12825     #
    12826     (write _test-input-stream "fn foo {\n")
    12827     (write _test-input-stream "  var a: (addr stream int)\n")
    12828     (write _test-input-stream "  read-from-stream a\n")
    12829     (write _test-input-stream "}\n")
    12830     # convert
    12831     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    12832     # registers except esp clobbered at this point
    12833     # restore ed
    12834     89/<- %edx 4/r32/esp
    12835     (flush _test-output-buffered-file)
    12836     (flush _test-error-buffered-file)
    12837 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
    12843     # check output
    12844     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-too-few-inouts: output should be empty")
    12845     (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")
    12846     # check that stop(1) was called
    12847     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-too-few-inouts: exit status")
    12848     # don't restore from ebp
    12849     81 0/subop/add %esp 8/imm32
    12850     # . epilogue
    12851     5d/pop-to-ebp
    12852     c3/return
    12853
    12854 test-read-from-stream-with-too-many-inouts:
    12855     # . prologue
    12856     55/push-ebp
    12857     89/<- %ebp 4/r32/esp
    12858     # setup
    12859     (clear-stream _test-input-stream)
    12860     (clear-stream $_test-input-buffered-file->buffer)
    12861     (clear-stream _test-output-stream)
    12862     (clear-stream $_test-output-buffered-file->buffer)
    12863     (clear-stream _test-error-stream)
    12864     (clear-stream $_test-error-buffered-file->buffer)
    12865     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    12866     68/push 0/imm32
    12867     68/push 0/imm32
    12868     89/<- %edx 4/r32/esp
    12869     (tailor-exit-descriptor %edx 0x10)
    12870     #
    12871     (write _test-input-stream "fn foo {\n")
    12872     (write _test-input-stream "  var a: (addr stream int)\n")
    12873     (write _test-input-stream "  var b: (addr int)\n")
    12874     (write _test-input-stream "  read-from-stream a, b, 0\n")
    12875     (write _test-input-stream "}\n")
    12876     # convert
    12877     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    12878     # registers except esp clobbered at this point
    12879     # restore ed
    12880     89/<- %edx 4/r32/esp
    12881     (flush _test-output-buffered-file)
    12882     (flush _test-error-buffered-file)
    12883 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
    12889     # check output
    12890     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-too-many-inouts: output should be empty")
    12891     (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")
    12892     # check that stop(1) was called
    12893     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-too-many-inouts: exit status")
    12894     # don't restore from ebp
    12895     81 0/subop/add %esp 8/imm32
    12896     # . epilogue
    12897     5d/pop-to-ebp
    12898     c3/return
    12899
    12900 test-read-from-stream-with-output:
    12901     # . prologue
    12902     55/push-ebp
    12903     89/<- %ebp 4/r32/esp
    12904     # setup
    12905     (clear-stream _test-input-stream)
    12906     (clear-stream $_test-input-buffered-file->buffer)
    12907     (clear-stream _test-output-stream)
    12908     (clear-stream $_test-output-buffered-file->buffer)
    12909     (clear-stream _test-error-stream)
    12910     (clear-stream $_test-error-buffered-file->buffer)
    12911     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    12912     68/push 0/imm32
    12913     68/push 0/imm32
    12914     89/<- %edx 4/r32/esp
    12915     (tailor-exit-descriptor %edx 0x10)
    12916     #
    12917     (write _test-input-stream "fn foo {\n")
    12918     (write _test-input-stream "  var a: (addr stream int)\n")
    12919     (write _test-input-stream "  var b/eax: (addr int) <- copy 0\n")
    12920     (write _test-input-stream "  b <- read-from-stream a, b\n")
    12921     (write _test-input-stream "}\n")
    12922     # convert
    12923     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    12924     # registers except esp clobbered at this point
    12925     # restore ed
    12926     89/<- %edx 4/r32/esp
    12927     (flush _test-output-buffered-file)
    12928     (flush _test-error-buffered-file)
    12929 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
    12935     # check output
    12936     (check-stream-equal _test-output-stream  ""  "F - test-read-from-stream-with-output: output should be empty")
    12937     (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")
    12938     # check that stop(1) was called
    12939     (check-ints-equal *(edx+4) 2 "F - test-read-from-stream-with-output: exit status")
    12940     # don't restore from ebp
    12941     81 0/subop/add %esp 8/imm32
    12942     # . epilogue
    12943     5d/pop-to-ebp
    12944     c3/return
    12945
    12946 test-convert-write-to-stream:
    12947     # . prologue
    12948     55/push-ebp
    12949     89/<- %ebp 4/r32/esp
    12950     # setup
    12951     (clear-stream _test-input-stream)
    12952     (clear-stream $_test-input-buffered-file->buffer)
    12953     (clear-stream _test-output-stream)
    12954     (clear-stream $_test-output-buffered-file->buffer)
    12955     #
    12956     (write _test-input-stream "fn foo {\n")
    12957     (write _test-input-stream "  var s/esi: (addr stream int) <- copy 0\n")
    12958     (write _test-input-stream "  var o/ecx: (addr int) <- copy 0\n")
    12959     (write _test-input-stream "  write-to-stream s, o\n")
    12960     (write _test-input-stream "}\n")
    12961     # convert
    12962     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
    12963     # registers except esp clobbered at this point
    12964     # restore ed
    12965     89/<- %edx 4/r32/esp
    12966     (flush _test-output-buffered-file)
    12967     (flush _test-error-buffered-file)
    12968 +--  6 lines: #?     # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------
    12974     # check output
    12975     (check-next-stream-line-equal _test-output-stream "foo:"                            "F - test-convert-write-to-stream/0")
    12976     (check-next-stream-line-equal _test-output-stream "  # . prologue"                  "F - test-convert-write-to-stream/1")
    12977     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                   "F - test-convert-write-to-stream/2")
    12978     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"          "F - test-convert-write-to-stream/3")
    12979     (check-next-stream-line-equal _test-output-stream "  {"                             "F - test-convert-write-to-stream/4")
    12980     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"           "F - test-convert-write-to-stream/5")
    12981     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %esi"        "F - test-convert-write-to-stream/6")
    12982     (check-next-stream-line-equal _test-output-stream "    be/copy-to-esi 0/imm32"      "F - test-convert-write-to-stream/7")
    12983     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"        "F - test-convert-write-to-stream/8")
    12984     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 0/imm32"      "F - test-convert-write-to-stream/9")
    12985     (check-next-stream-line-equal _test-output-stream "    (write-to-stream %esi %ecx 0x00000004)"  "F - test-convert-write-to-stream/10")
    12986     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"         "F - test-convert-write-to-stream/11")
    12987     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %esi"         "F - test-convert-write-to-stream/12")
    12988     (check-next-stream-line-equal _test-output-stream "  }"                             "F - test-convert-write-to-stream/13")
    12989     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"          "F - test-convert-write-to-stream/14")
    12990     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                  "F - test-convert-write-to-stream/15")
    12991     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"          "F - test-convert-write-to-stream/16")
    12992     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                 "F - test-convert-write-to-stream/17")
    12993     (check-next-stream-line-equal _test-output-stream "  c3/return"                     "F - test-convert-write-to-stream/18")
    12994     # . epilogue
    12995     89/<- %esp 5/r32/ebp
    12996     5d/pop-to-ebp
    12997     c3/return
    12998
    12999 test-convert-write-to-stream-with-correct-payload-size:
    13000     # . prologue
    13001     55/push-ebp
    13002     89/<- %ebp 4/r32/esp
    13003     # setup
    13004     (clear-stream _test-input-stream)
    13005     (clear-stream $_test-input-buffered-file->buffer)
    13006     (clear-stream _test-output-stream)
    13007     (clear-stream $_test-output-buffered-file->buffer)
    13008     #
    13009     (write _test-input-stream "fn foo {\n")
    13010     (write _test-input-stream "  var s/esi: (addr stream handle int) <- copy 0\n")
    13011     (write _test-input-stream "  var o/ecx: (addr handle int) <- copy 0\n")
    13012     (write _test-input-stream "  write-to-stream s, o\n")
    13013     (write _test-input-stream "}\n")
    13014     # convert
    13015     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
    13016     # registers except esp clobbered at this point
    13017     # restore ed
    13018     89/<- %edx 4/r32/esp
    13019     (flush _test-output-buffered-file)
    13020     (flush _test-error-buffered-file)
    13021 +--  6 lines: #?     # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------
    13027     # check output
    13028     (check-next-stream-line-equal _test-output-stream "foo:"                            "F - test-convert-write-to-stream-with-correct-payload-size/0")
    13029     (check-next-stream-line-equal _test-output-stream "  # . prologue"                  "F - test-convert-write-to-stream-with-correct-payload-size/1")
    13030     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"                   "F - test-convert-write-to-stream-with-correct-payload-size/2")
    13031     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"          "F - test-convert-write-to-stream-with-correct-payload-size/3")
    13032     (check-next-stream-line-equal _test-output-stream "  {"                             "F - test-convert-write-to-stream-with-correct-payload-size/4")
    13033     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"           "F - test-convert-write-to-stream-with-correct-payload-size/5")
    13034     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %esi"        "F - test-convert-write-to-stream-with-correct-payload-size/6")
    13035     (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")
    13036     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"        "F - test-convert-write-to-stream-with-correct-payload-size/8")
    13037     (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")
    13038     (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")
    13039     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"         "F - test-convert-write-to-stream-with-correct-payload-size/11")
    13040     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %esi"         "F - test-convert-write-to-stream-with-correct-payload-size/12")
    13041     (check-next-stream-line-equal _test-output-stream "  }"                             "F - test-convert-write-to-stream-with-correct-payload-size/13")
    13042     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"          "F - test-convert-write-to-stream-with-correct-payload-size/14")
    13043     (check-next-stream-line-equal _test-output-stream "  # . epilogue"                  "F - test-convert-write-to-stream-with-correct-payload-size/15")
    13044     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"          "F - test-convert-write-to-stream-with-correct-payload-size/16")
    13045     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"                 "F - test-convert-write-to-stream-with-correct-payload-size/17")
    13046     (check-next-stream-line-equal _test-output-stream "  c3/return"                     "F - test-convert-write-to-stream-with-correct-payload-size/18")
    13047     # . epilogue
    13048     89/<- %esp 5/r32/ebp
    13049     5d/pop-to-ebp
    13050     c3/return
    13051
    13052 test-write-to-stream-with-non-stream-atom-base-type:
    13053     # . prologue
    13054     55/push-ebp
    13055     89/<- %ebp 4/r32/esp
    13056     # setup
    13057     (clear-stream _test-input-stream)
    13058     (clear-stream $_test-input-buffered-file->buffer)
    13059     (clear-stream _test-output-stream)
    13060     (clear-stream $_test-output-buffered-file->buffer)
    13061     (clear-stream _test-error-stream)
    13062     (clear-stream $_test-error-buffered-file->buffer)
    13063     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    13064     68/push 0/imm32
    13065     68/push 0/imm32
    13066     89/<- %edx 4/r32/esp
    13067     (tailor-exit-descriptor %edx 0x10)
    13068     #
    13069     (write _test-input-stream "fn foo {\n")
    13070     (write _test-input-stream "  var a: int\n")
    13071     (write _test-input-stream "  write-to-stream a, 0\n")
    13072     (write _test-input-stream "}\n")
    13073     # convert
    13074     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    13075     # registers except esp clobbered at this point
    13076     # restore ed
    13077     89/<- %edx 4/r32/esp
    13078     (flush _test-output-buffered-file)
    13079     (flush _test-error-buffered-file)
    13080 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
    13086     # check output
    13087     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-non-stream-atom-base-type: output should be empty")
    13088     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt write-to-stream: var 'a' must be an addr to a stream"  "F - test-write-to-stream-with-non-stream-atom-base-type: error message")
    13089     # check that stop(1) was called
    13090     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-non-stream-atom-base-type: exit status")
    13091     # don't restore from ebp
    13092     81 0/subop/add %esp 8/imm32
    13093     # . epilogue
    13094     5d/pop-to-ebp
    13095     c3/return
    13096
    13097 test-write-to-stream-with-non-stream-compound-base-type:
    13098     # . prologue
    13099     55/push-ebp
    13100     89/<- %ebp 4/r32/esp
    13101     # setup
    13102     (clear-stream _test-input-stream)
    13103     (clear-stream $_test-input-buffered-file->buffer)
    13104     (clear-stream _test-output-stream)
    13105     (clear-stream $_test-output-buffered-file->buffer)
    13106     (clear-stream _test-error-stream)
    13107     (clear-stream $_test-error-buffered-file->buffer)
    13108     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    13109     68/push 0/imm32
    13110     68/push 0/imm32
    13111     89/<- %edx 4/r32/esp
    13112     (tailor-exit-descriptor %edx 0x10)
    13113     #
    13114     (write _test-input-stream "fn foo {\n")
    13115     (write _test-input-stream "  var a: (handle int)\n")
    13116     (write _test-input-stream "  write-to-stream a, 0\n")
    13117     (write _test-input-stream "}\n")
    13118     # convert
    13119     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    13120     # registers except esp clobbered at this point
    13121     # restore ed
    13122     89/<- %edx 4/r32/esp
    13123     (flush _test-output-buffered-file)
    13124     (flush _test-error-buffered-file)
    13125 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
    13131     # check output
    13132     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-non-stream-compound-base-type: output should be empty")
    13133     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt write-to-stream: var 'a' must be an addr to a stream"  "F - test-write-to-stream-with-non-stream-compound-base-type: error message")
    13134     # check that stop(1) was called
    13135     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-non-stream-compound-base-type: exit status")
    13136     # don't restore from ebp
    13137     81 0/subop/add %esp 8/imm32
    13138     # . epilogue
    13139     5d/pop-to-ebp
    13140     c3/return
    13141
    13142 test-write-to-stream-with-non-stream-compound-base-type-2:
    13143     # . prologue
    13144     55/push-ebp
    13145     89/<- %ebp 4/r32/esp
    13146     # setup
    13147     (clear-stream _test-input-stream)
    13148     (clear-stream $_test-input-buffered-file->buffer)
    13149     (clear-stream _test-output-stream)
    13150     (clear-stream $_test-output-buffered-file->buffer)
    13151     (clear-stream _test-error-stream)
    13152     (clear-stream $_test-error-buffered-file->buffer)
    13153     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    13154     68/push 0/imm32
    13155     68/push 0/imm32
    13156     89/<- %edx 4/r32/esp
    13157     (tailor-exit-descriptor %edx 0x10)
    13158     #
    13159     (write _test-input-stream "fn foo {\n")
    13160     (write _test-input-stream "  var a: (addr int)\n")
    13161     (write _test-input-stream "  write-to-stream a, 0\n")
    13162     (write _test-input-stream "}\n")
    13163     # convert
    13164     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    13165     # registers except esp clobbered at this point
    13166     # restore ed
    13167     89/<- %edx 4/r32/esp
    13168     (flush _test-output-buffered-file)
    13169     (flush _test-error-buffered-file)
    13170 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
    13176     # check output
    13177     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-non-stream-compound-base-type-2: output should be empty")
    13178     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt write-to-stream: var 'a' must be an addr to a stream"  "F - test-write-to-stream-with-non-stream-compound-base-type-2: error message")
    13179     # check that stop(1) was called
    13180     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-non-stream-compound-base-type-2: exit status")
    13181     # don't restore from ebp
    13182     81 0/subop/add %esp 8/imm32
    13183     # . epilogue
    13184     5d/pop-to-ebp
    13185     c3/return
    13186
    13187 test-write-to-stream-with-stream-atom-base-type:
    13188     # . prologue
    13189     55/push-ebp
    13190     89/<- %ebp 4/r32/esp
    13191     # setup
    13192     (clear-stream _test-input-stream)
    13193     (clear-stream $_test-input-buffered-file->buffer)
    13194     (clear-stream _test-output-stream)
    13195     (clear-stream $_test-output-buffered-file->buffer)
    13196     (clear-stream _test-error-stream)
    13197     (clear-stream $_test-error-buffered-file->buffer)
    13198     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    13199     68/push 0/imm32
    13200     68/push 0/imm32
    13201     89/<- %edx 4/r32/esp
    13202     (tailor-exit-descriptor %edx 0x10)
    13203     #
    13204     (write _test-input-stream "fn foo {\n")
    13205     (write _test-input-stream "  var a: stream\n")
    13206     (write _test-input-stream "  write-to-stream a, 0\n")
    13207     (write _test-input-stream "}\n")
    13208     # convert
    13209     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    13210     # registers except esp clobbered at this point
    13211     # restore ed
    13212     89/<- %edx 4/r32/esp
    13213     (flush _test-output-buffered-file)
    13214     (flush _test-error-buffered-file)
    13215 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
    13221     # check output
    13222     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-stream-atom-base-type: output should be empty")
    13223     (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")
    13224     # check that stop(1) was called
    13225     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-stream-atom-base-type: exit status")
    13226     # don't restore from ebp
    13227     81 0/subop/add %esp 8/imm32
    13228     # . epilogue
    13229     5d/pop-to-ebp
    13230     c3/return
    13231
    13232 test-write-to-stream-with-wrong-index-type:
    13233     # . prologue
    13234     55/push-ebp
    13235     89/<- %ebp 4/r32/esp
    13236     # setup
    13237     (clear-stream _test-input-stream)
    13238     (clear-stream $_test-input-buffered-file->buffer)
    13239     (clear-stream _test-output-stream)
    13240     (clear-stream $_test-output-buffered-file->buffer)
    13241     (clear-stream _test-error-stream)
    13242     (clear-stream $_test-error-buffered-file->buffer)
    13243     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    13244     68/push 0/imm32
    13245     68/push 0/imm32
    13246     89/<- %edx 4/r32/esp
    13247     (tailor-exit-descriptor %edx 0x10)
    13248     #
    13249     (write _test-input-stream "fn foo {\n")
    13250     (write _test-input-stream "  var a/eax: (addr stream int) <- copy 0\n")
    13251     (write _test-input-stream "  var b: boolean\n")
    13252     (write _test-input-stream "  write-to-stream a, b\n")
    13253     (write _test-input-stream "}\n")
    13254     # convert
    13255     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    13256     # registers except esp clobbered at this point
    13257     # restore ed
    13258     89/<- %edx 4/r32/esp
    13259     (flush _test-output-buffered-file)
    13260     (flush _test-error-buffered-file)
    13261 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
    13267     # check output
    13268     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-wrong-index-type: output should be empty")
    13269     (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")
    13270     # check that stop(1) was called
    13271     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-wrong-index-type: exit status")
    13272     # don't restore from ebp
    13273     81 0/subop/add %esp 8/imm32
    13274     # . epilogue
    13275     5d/pop-to-ebp
    13276     c3/return
    13277
    13278 test-write-to-stream-with-no-inouts:
    13279     # . prologue
    13280     55/push-ebp
    13281     89/<- %ebp 4/r32/esp
    13282     # setup
    13283     (clear-stream _test-input-stream)
    13284     (clear-stream $_test-input-buffered-file->buffer)
    13285     (clear-stream _test-output-stream)
    13286     (clear-stream $_test-output-buffered-file->buffer)
    13287     (clear-stream _test-error-stream)
    13288     (clear-stream $_test-error-buffered-file->buffer)
    13289     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    13290     68/push 0/imm32
    13291     68/push 0/imm32
    13292     89/<- %edx 4/r32/esp
    13293     (tailor-exit-descriptor %edx 0x10)
    13294     #
    13295     (write _test-input-stream "fn foo {\n")
    13296     (write _test-input-stream "  write-to-stream\n")
    13297     (write _test-input-stream "}\n")
    13298     # convert
    13299     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    13300     # registers except esp clobbered at this point
    13301     # restore ed
    13302     89/<- %edx 4/r32/esp
    13303     (flush _test-output-buffered-file)
    13304     (flush _test-error-buffered-file)
    13305 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
    13311     # check output
    13312     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-no-inouts: output should be empty")
    13313     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt write-to-stream: too few inouts (2 required)"  "F - test-write-to-stream-with-no-inouts: error message")
    13314     # check that stop(1) was called
    13315     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-no-inouts: exit status")
    13316     # don't restore from ebp
    13317     81 0/subop/add %esp 8/imm32
    13318     # . epilogue
    13319     5d/pop-to-ebp
    13320     c3/return
    13321
    13322 test-write-to-stream-with-too-few-inouts:
    13323     # . prologue
    13324     55/push-ebp
    13325     89/<- %ebp 4/r32/esp
    13326     # setup
    13327     (clear-stream _test-input-stream)
    13328     (clear-stream $_test-input-buffered-file->buffer)
    13329     (clear-stream _test-output-stream)
    13330     (clear-stream $_test-output-buffered-file->buffer)
    13331     (clear-stream _test-error-stream)
    13332     (clear-stream $_test-error-buffered-file->buffer)
    13333     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    13334     68/push 0/imm32
    13335     68/push 0/imm32
    13336     89/<- %edx 4/r32/esp
    13337     (tailor-exit-descriptor %edx 0x10)
    13338     #
    13339     (write _test-input-stream "fn foo {\n")
    13340     (write _test-input-stream "  var a: (addr stream int)\n")
    13341     (write _test-input-stream "  write-to-stream a\n")
    13342     (write _test-input-stream "}\n")
    13343     # convert
    13344     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    13345     # registers except esp clobbered at this point
    13346     # restore ed
    13347     89/<- %edx 4/r32/esp
    13348     (flush _test-output-buffered-file)
    13349     (flush _test-error-buffered-file)
    13350 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
    13356     # check output
    13357     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-too-few-inouts: output should be empty")
    13358     (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")
    13359     # check that stop(1) was called
    13360     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-too-few-inouts: exit status")
    13361     # don't restore from ebp
    13362     81 0/subop/add %esp 8/imm32
    13363     # . epilogue
    13364     5d/pop-to-ebp
    13365     c3/return
    13366
    13367 test-write-to-stream-with-too-many-inouts:
    13368     # . prologue
    13369     55/push-ebp
    13370     89/<- %ebp 4/r32/esp
    13371     # setup
    13372     (clear-stream _test-input-stream)
    13373     (clear-stream $_test-input-buffered-file->buffer)
    13374     (clear-stream _test-output-stream)
    13375     (clear-stream $_test-output-buffered-file->buffer)
    13376     (clear-stream _test-error-stream)
    13377     (clear-stream $_test-error-buffered-file->buffer)
    13378     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    13379     68/push 0/imm32
    13380     68/push 0/imm32
    13381     89/<- %edx 4/r32/esp
    13382     (tailor-exit-descriptor %edx 0x10)
    13383     #
    13384     (write _test-input-stream "fn foo {\n")
    13385     (write _test-input-stream "  var a: (addr stream int)\n")
    13386     (write _test-input-stream "  var b: (addr int)\n")
    13387     (write _test-input-stream "  write-to-stream a, b, 0\n")
    13388     (write _test-input-stream "}\n")
    13389     # convert
    13390     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    13391     # registers except esp clobbered at this point
    13392     # restore ed
    13393     89/<- %edx 4/r32/esp
    13394     (flush _test-output-buffered-file)
    13395     (flush _test-error-buffered-file)
    13396 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
    13402     # check output
    13403     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-too-many-inouts: output should be empty")
    13404     (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")
    13405     # check that stop(1) was called
    13406     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-too-many-inouts: exit status")
    13407     # don't restore from ebp
    13408     81 0/subop/add %esp 8/imm32
    13409     # . epilogue
    13410     5d/pop-to-ebp
    13411     c3/return
    13412
    13413 test-write-to-stream-with-output:
    13414     # . prologue
    13415     55/push-ebp
    13416     89/<- %ebp 4/r32/esp
    13417     # setup
    13418     (clear-stream _test-input-stream)
    13419     (clear-stream $_test-input-buffered-file->buffer)
    13420     (clear-stream _test-output-stream)
    13421     (clear-stream $_test-output-buffered-file->buffer)
    13422     (clear-stream _test-error-stream)
    13423     (clear-stream $_test-error-buffered-file->buffer)
    13424     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    13425     68/push 0/imm32
    13426     68/push 0/imm32
    13427     89/<- %edx 4/r32/esp
    13428     (tailor-exit-descriptor %edx 0x10)
    13429     #
    13430     (write _test-input-stream "fn foo {\n")
    13431     (write _test-input-stream "  var a: (addr stream int)\n")
    13432     (write _test-input-stream "  var b/eax: (addr int) <- copy 0\n")
    13433     (write _test-input-stream "  b <- write-to-stream a, b\n")
    13434     (write _test-input-stream "}\n")
    13435     # convert
    13436     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    13437     # registers except esp clobbered at this point
    13438     # restore ed
    13439     89/<- %edx 4/r32/esp
    13440     (flush _test-output-buffered-file)
    13441     (flush _test-error-buffered-file)
    13442 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
    13448     # check output
    13449     (check-stream-equal _test-output-stream  ""  "F - test-write-to-stream-with-output: output should be empty")
    13450     (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")
    13451     # check that stop(1) was called
    13452     (check-ints-equal *(edx+4) 2 "F - test-write-to-stream-with-output: exit status")
    13453     # don't restore from ebp
    13454     81 0/subop/add %esp 8/imm32
    13455     # . epilogue
    13456     5d/pop-to-ebp
    13457     c3/return
    13458
    13459 test-length-with-non-array-atom-base-type:
    13460     # . prologue
    13461     55/push-ebp
    13462     89/<- %ebp 4/r32/esp
    13463     # setup
    13464     (clear-stream _test-input-stream)
    13465     (clear-stream $_test-input-buffered-file->buffer)
    13466     (clear-stream _test-output-stream)
    13467     (clear-stream $_test-output-buffered-file->buffer)
    13468     (clear-stream _test-error-stream)
    13469     (clear-stream $_test-error-buffered-file->buffer)
    13470     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    13471     68/push 0/imm32
    13472     68/push 0/imm32
    13473     89/<- %edx 4/r32/esp
    13474     (tailor-exit-descriptor %edx 0x10)
    13475     #
    13476     (write _test-input-stream "fn foo {\n")
    13477     (write _test-input-stream "  var a: int\n")
    13478     (write _test-input-stream "  var c/ecx: int <- length a\n")
    13479     (write _test-input-stream "}\n")
    13480     # convert
    13481     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    13482     # registers except esp clobbered at this point
    13483     # restore ed
    13484     89/<- %edx 4/r32/esp
    13485     (flush _test-output-buffered-file)
    13486     (flush _test-error-buffered-file)
    13487 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
    13493     # check output
    13494     (check-stream-equal _test-output-stream  ""  "F - test-length-with-non-array-atom-base-type: output should be empty")
    13495     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt length: var 'a' is not an array"  "F - test-length-with-non-array-atom-base-type: error message")
    13496     # check that stop(1) was called
    13497     (check-ints-equal *(edx+4) 2 "F - test-length-with-non-array-atom-base-type: exit status")
    13498     # don't restore from ebp
    13499     81 0/subop/add %esp 8/imm32
    13500     # . epilogue
    13501     5d/pop-to-ebp
    13502     c3/return
    13503
    13504 test-length-with-non-array-compound-base-type:
    13505     # . prologue
    13506     55/push-ebp
    13507     89/<- %ebp 4/r32/esp
    13508     # setup
    13509     (clear-stream _test-input-stream)
    13510     (clear-stream $_test-input-buffered-file->buffer)
    13511     (clear-stream _test-output-stream)
    13512     (clear-stream $_test-output-buffered-file->buffer)
    13513     (clear-stream _test-error-stream)
    13514     (clear-stream $_test-error-buffered-file->buffer)
    13515     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    13516     68/push 0/imm32
    13517     68/push 0/imm32
    13518     89/<- %edx 4/r32/esp
    13519     (tailor-exit-descriptor %edx 0x10)
    13520     #
    13521     (write _test-input-stream "fn foo {\n")
    13522     (write _test-input-stream "  var a: (handle int)\n")
    13523     (write _test-input-stream "  var c/ecx: (addr int) <- length a, 0\n")
    13524     (write _test-input-stream "}\n")
    13525     # convert
    13526     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    13527     # registers except esp clobbered at this point
    13528     # restore ed
    13529     89/<- %edx 4/r32/esp
    13530     (flush _test-output-buffered-file)
    13531     (flush _test-error-buffered-file)
    13532 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
    13538     # check output
    13539     (check-stream-equal _test-output-stream  ""  "F - test-length-with-non-array-compound-base-type: output should be empty")
    13540     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt length: var 'a' is not an array"  "F - test-length-with-non-array-compound-base-type: error message")
    13541     # check that stop(1) was called
    13542     (check-ints-equal *(edx+4) 2 "F - test-length-with-non-array-compound-base-type: exit status")
    13543     # don't restore from ebp
    13544     81 0/subop/add %esp 8/imm32
    13545     # . epilogue
    13546     5d/pop-to-ebp
    13547     c3/return
    13548
    13549 test-length-with-non-array-compound-base-type-2:
    13550     # . prologue
    13551     55/push-ebp
    13552     89/<- %ebp 4/r32/esp
    13553     # setup
    13554     (clear-stream _test-input-stream)
    13555     (clear-stream $_test-input-buffered-file->buffer)
    13556     (clear-stream _test-output-stream)
    13557     (clear-stream $_test-output-buffered-file->buffer)
    13558     (clear-stream _test-error-stream)
    13559     (clear-stream $_test-error-buffered-file->buffer)
    13560     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    13561     68/push 0/imm32
    13562     68/push 0/imm32
    13563     89/<- %edx 4/r32/esp
    13564     (tailor-exit-descriptor %edx 0x10)
    13565     #
    13566     (write _test-input-stream "fn foo {\n")
    13567     (write _test-input-stream "  var a: (addr int)\n")
    13568     (write _test-input-stream "  var c/ecx: (addr int) <- length a, 0\n")
    13569     (write _test-input-stream "}\n")
    13570     # convert
    13571     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    13572     # registers except esp clobbered at this point
    13573     # restore ed
    13574     89/<- %edx 4/r32/esp
    13575     (flush _test-output-buffered-file)
    13576     (flush _test-error-buffered-file)
    13577 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
    13583     # check output
    13584     (check-stream-equal _test-output-stream  ""  "F - test-length-with-non-array-compound-base-type-2: output should be empty")
    13585     (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")
    13586     # check that stop(1) was called
    13587     (check-ints-equal *(edx+4) 2 "F - test-length-with-non-array-compound-base-type-2: exit status")
    13588     # don't restore from ebp
    13589     81 0/subop/add %esp 8/imm32
    13590     # . epilogue
    13591     5d/pop-to-ebp
    13592     c3/return
    13593
    13594 test-length-with-array-atom-base-type:
    13595     # . prologue
    13596     55/push-ebp
    13597     89/<- %ebp 4/r32/esp
    13598     # setup
    13599     (clear-stream _test-input-stream)
    13600     (clear-stream $_test-input-buffered-file->buffer)
    13601     (clear-stream _test-output-stream)
    13602     (clear-stream $_test-output-buffered-file->buffer)
    13603     (clear-stream _test-error-stream)
    13604     (clear-stream $_test-error-buffered-file->buffer)
    13605     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    13606     68/push 0/imm32
    13607     68/push 0/imm32
    13608     89/<- %edx 4/r32/esp
    13609     (tailor-exit-descriptor %edx 0x10)
    13610     #
    13611     (write _test-input-stream "fn foo {\n")
    13612     (write _test-input-stream "  var a: array\n")
    13613     (write _test-input-stream "  var c/ecx: (addr int) <- length a\n")
    13614     (write _test-input-stream "}\n")
    13615     # convert
    13616     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    13617     # registers except esp clobbered at this point
    13618     # restore ed
    13619     89/<- %edx 4/r32/esp
    13620     (flush _test-output-buffered-file)
    13621     (flush _test-error-buffered-file)
    13622 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
    13628     # check output
    13629     (check-stream-equal _test-output-stream  ""  "F - test-length-with-array-atom-base-type: output should be empty")
    13630     (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")
    13631     # check that stop(1) was called
    13632     (check-ints-equal *(edx+4) 2 "F - test-length-with-array-atom-base-type: exit status")
    13633     # don't restore from ebp
    13634     81 0/subop/add %esp 8/imm32
    13635     # . epilogue
    13636     5d/pop-to-ebp
    13637     c3/return
    13638
    13639 test-length-with-addr-base-on-stack:
    13640     # . prologue
    13641     55/push-ebp
    13642     89/<- %ebp 4/r32/esp
    13643     # setup
    13644     (clear-stream _test-input-stream)
    13645     (clear-stream $_test-input-buffered-file->buffer)
    13646     (clear-stream _test-output-stream)
    13647     (clear-stream $_test-output-buffered-file->buffer)
    13648     (clear-stream _test-error-stream)
    13649     (clear-stream $_test-error-buffered-file->buffer)
    13650     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    13651     68/push 0/imm32
    13652     68/push 0/imm32
    13653     89/<- %edx 4/r32/esp
    13654     (tailor-exit-descriptor %edx 0x10)
    13655     #
    13656     (write _test-input-stream "fn foo {\n")
    13657     (write _test-input-stream "  var a: (addr array int)\n")
    13658     (write _test-input-stream "  var c/ecx: (addr int) <- length a\n")
    13659     (write _test-input-stream "}\n")
    13660     # convert
    13661     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    13662     # registers except esp clobbered at this point
    13663     # restore ed
    13664     89/<- %edx 4/r32/esp
    13665     (flush _test-output-buffered-file)
    13666     (flush _test-error-buffered-file)
    13667 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
    13673     # check output
    13674     (check-stream-equal _test-output-stream  ""  "F - test-length-with-addr-base-on-stack: output should be empty")
    13675     (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")
    13676     # check that stop(1) was called
    13677     (check-ints-equal *(edx+4) 2 "F - test-length-with-addr-base-on-stack: exit status")
    13678     # don't restore from ebp
    13679     81 0/subop/add %esp 8/imm32
    13680     # . epilogue
    13681     5d/pop-to-ebp
    13682     c3/return
    13683
    13684 test-length-with-wrong-output-type:
    13685     # . prologue
    13686     55/push-ebp
    13687     89/<- %ebp 4/r32/esp
    13688     # setup
    13689     (clear-stream _test-input-stream)
    13690     (clear-stream $_test-input-buffered-file->buffer)
    13691     (clear-stream _test-output-stream)
    13692     (clear-stream $_test-output-buffered-file->buffer)
    13693     (clear-stream _test-error-stream)
    13694     (clear-stream $_test-error-buffered-file->buffer)
    13695     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    13696     68/push 0/imm32
    13697     68/push 0/imm32
    13698     89/<- %edx 4/r32/esp
    13699     (tailor-exit-descriptor %edx 0x10)
    13700     #
    13701     (write _test-input-stream "fn foo {\n")
    13702     (write _test-input-stream "  var a/ebx: (addr array boolean) <- copy 0\n")
    13703     (write _test-input-stream "  var o/edi: (addr int) <- length a\n")
    13704     (write _test-input-stream "}\n")
    13705     # convert
    13706     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    13707     # registers except esp clobbered at this point
    13708     # restore ed
    13709     89/<- %edx 4/r32/esp
    13710     (flush _test-output-buffered-file)
    13711     (flush _test-error-buffered-file)
    13712 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
    13718     # check output
    13719     (check-stream-equal _test-output-stream  ""  "F - test-length-with-wrong-output-type: output should be empty")
    13720     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt length: output 'o' does not have the right type"  "F - test-length-with-wrong-output-type: error message")
    13721     # check that stop(1) was called
    13722     (check-ints-equal *(edx+4) 2 "F - test-length-with-wrong-output-type: exit status")
    13723     # don't restore from ebp
    13724     81 0/subop/add %esp 8/imm32
    13725     # . epilogue
    13726     5d/pop-to-ebp
    13727     c3/return
    13728
    13729 test-length-with-wrong-output-compound-type:
    13730     # . prologue
    13731     55/push-ebp
    13732     89/<- %ebp 4/r32/esp
    13733     # setup
    13734     (clear-stream _test-input-stream)
    13735     (clear-stream $_test-input-buffered-file->buffer)
    13736     (clear-stream _test-output-stream)
    13737     (clear-stream $_test-output-buffered-file->buffer)
    13738     (clear-stream _test-error-stream)
    13739     (clear-stream $_test-error-buffered-file->buffer)
    13740     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    13741     68/push 0/imm32
    13742     68/push 0/imm32
    13743     89/<- %edx 4/r32/esp
    13744     (tailor-exit-descriptor %edx 0x10)
    13745     #
    13746     (write _test-input-stream "fn foo {\n")
    13747     (write _test-input-stream "  var a/ebx: (addr array handle boolean) <- copy 0\n")
    13748     (write _test-input-stream "  var o/edi: (addr handle int) <- length a\n")
    13749     (write _test-input-stream "}\n")
    13750     # convert
    13751     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    13752     # registers except esp clobbered at this point
    13753     # restore ed
    13754     89/<- %edx 4/r32/esp
    13755     (flush _test-output-buffered-file)
    13756     (flush _test-error-buffered-file)
    13757 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
    13763     # check output
    13764     (check-stream-equal _test-output-stream  ""  "F - test-length-with-wrong-output-compound-type: output should be empty")
    13765     (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")
    13766     # check that stop(1) was called
    13767     (check-ints-equal *(edx+4) 2 "F - test-length-with-wrong-output-compound-type: exit status")
    13768     # don't restore from ebp
    13769     81 0/subop/add %esp 8/imm32
    13770     # . epilogue
    13771     5d/pop-to-ebp
    13772     c3/return
    13773
    13774 test-length-with-no-inouts:
    13775     # . prologue
    13776     55/push-ebp
    13777     89/<- %ebp 4/r32/esp
    13778     # setup
    13779     (clear-stream _test-input-stream)
    13780     (clear-stream $_test-input-buffered-file->buffer)
    13781     (clear-stream _test-output-stream)
    13782     (clear-stream $_test-output-buffered-file->buffer)
    13783     (clear-stream _test-error-stream)
    13784     (clear-stream $_test-error-buffered-file->buffer)
    13785     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    13786     68/push 0/imm32
    13787     68/push 0/imm32
    13788     89/<- %edx 4/r32/esp
    13789     (tailor-exit-descriptor %edx 0x10)
    13790     #
    13791     (write _test-input-stream "fn foo {\n")
    13792     (write _test-input-stream "  var c/ecx: int <- length\n")
    13793     (write _test-input-stream "}\n")
    13794     # convert
    13795     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    13796     # registers except esp clobbered at this point
    13797     # restore ed
    13798     89/<- %edx 4/r32/esp
    13799     (flush _test-output-buffered-file)
    13800     (flush _test-error-buffered-file)
    13801 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
    13807     # check output
    13808     (check-stream-equal _test-output-stream  ""  "F - test-length-with-no-inouts: output should be empty")
    13809     (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")
    13810     # check that stop(1) was called
    13811     (check-ints-equal *(edx+4) 2 "F - test-length-with-no-inouts: exit status")
    13812     # don't restore from ebp
    13813     81 0/subop/add %esp 8/imm32
    13814     # . epilogue
    13815     5d/pop-to-ebp
    13816     c3/return
    13817
    13818 test-length-with-too-many-inouts:
    13819     # . prologue
    13820     55/push-ebp
    13821     89/<- %ebp 4/r32/esp
    13822     # setup
    13823     (clear-stream _test-input-stream)
    13824     (clear-stream $_test-input-buffered-file->buffer)
    13825     (clear-stream _test-output-stream)
    13826     (clear-stream $_test-output-buffered-file->buffer)
    13827     (clear-stream _test-error-stream)
    13828     (clear-stream $_test-error-buffered-file->buffer)
    13829     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    13830     68/push 0/imm32
    13831     68/push 0/imm32
    13832     89/<- %edx 4/r32/esp
    13833     (tailor-exit-descriptor %edx 0x10)
    13834     #
    13835     (write _test-input-stream "fn foo {\n")
    13836     (write _test-input-stream "  var a: (array int 3)\n")
    13837     (write _test-input-stream "  var c/ecx: int <- length a, 0, 0\n")
    13838     (write _test-input-stream "}\n")
    13839     # convert
    13840     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    13841     # registers except esp clobbered at this point
    13842     # restore ed
    13843     89/<- %edx 4/r32/esp
    13844     (flush _test-output-buffered-file)
    13845     (flush _test-error-buffered-file)
    13846 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
    13852     # check output
    13853     (check-stream-equal _test-output-stream  ""  "F - test-length-with-too-many-inouts: output should be empty")
    13854     (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")
    13855     # check that stop(1) was called
    13856     (check-ints-equal *(edx+4) 2 "F - test-length-with-too-many-inouts: exit status")
    13857     # don't restore from ebp
    13858     81 0/subop/add %esp 8/imm32
    13859     # . epilogue
    13860     5d/pop-to-ebp
    13861     c3/return
    13862
    13863 test-length-with-no-output:
    13864     # . prologue
    13865     55/push-ebp
    13866     89/<- %ebp 4/r32/esp
    13867     # setup
    13868     (clear-stream _test-input-stream)
    13869     (clear-stream $_test-input-buffered-file->buffer)
    13870     (clear-stream _test-output-stream)
    13871     (clear-stream $_test-output-buffered-file->buffer)
    13872     (clear-stream _test-error-stream)
    13873     (clear-stream $_test-error-buffered-file->buffer)
    13874     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    13875     68/push 0/imm32
    13876     68/push 0/imm32
    13877     89/<- %edx 4/r32/esp
    13878     (tailor-exit-descriptor %edx 0x10)
    13879     #
    13880     (write _test-input-stream "fn foo {\n")
    13881     (write _test-input-stream "  var a: (array int 3)\n")
    13882     (write _test-input-stream "  length a\n")
    13883     (write _test-input-stream "}\n")
    13884     # convert
    13885     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    13886     # registers except esp clobbered at this point
    13887     # restore ed
    13888     89/<- %edx 4/r32/esp
    13889     (flush _test-output-buffered-file)
    13890     (flush _test-error-buffered-file)
    13891 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
    13897     # check output
    13898     (check-stream-equal _test-output-stream  ""  "F - test-length-with-no-output: output should be empty")
    13899     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt length: must have an output"  "F - test-length-with-no-output: error message")
    13900     # check that stop(1) was called
    13901     (check-ints-equal *(edx+4) 2 "F - test-length-with-no-output: exit status")
    13902     # don't restore from ebp
    13903     81 0/subop/add %esp 8/imm32
    13904     # . epilogue
    13905     5d/pop-to-ebp
    13906     c3/return
    13907
    13908 test-length-with-too-many-outputs:
    13909     # . prologue
    13910     55/push-ebp
    13911     89/<- %ebp 4/r32/esp
    13912     # setup
    13913     (clear-stream _test-input-stream)
    13914     (clear-stream $_test-input-buffered-file->buffer)
    13915     (clear-stream _test-output-stream)
    13916     (clear-stream $_test-output-buffered-file->buffer)
    13917     (clear-stream _test-error-stream)
    13918     (clear-stream $_test-error-buffered-file->buffer)
    13919     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    13920     68/push 0/imm32
    13921     68/push 0/imm32
    13922     89/<- %edx 4/r32/esp
    13923     (tailor-exit-descriptor %edx 0x10)
    13924     #
    13925     (write _test-input-stream "fn foo {\n")
    13926     (write _test-input-stream "  var a: (array int 3)\n")
    13927     (write _test-input-stream "  var b/eax: int <- copy 0\n")
    13928     (write _test-input-stream "  var c/ecx: int <- copy 0\n")
    13929     (write _test-input-stream "  b, c <- length a\n")
    13930     (write _test-input-stream "}\n")
    13931     # convert
    13932     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    13933     # registers except esp clobbered at this point
    13934     # restore ed
    13935     89/<- %edx 4/r32/esp
    13936     (flush _test-output-buffered-file)
    13937     (flush _test-error-buffered-file)
    13938 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
    13944     # check output
    13945     (check-stream-equal _test-output-stream  ""  "F - test-length-with-too-many-outputs: output should be empty")
    13946     (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")
    13947     # check that stop(1) was called
    13948     (check-ints-equal *(edx+4) 2 "F - test-length-with-too-many-outputs: exit status")
    13949     # don't restore from ebp
    13950     81 0/subop/add %esp 8/imm32
    13951     # . epilogue
    13952     5d/pop-to-ebp
    13953     c3/return
    13954
    13955 test-convert-function-with-return-register-and-local:
    13956     # . prologue
    13957     55/push-ebp
    13958     89/<- %ebp 4/r32/esp
    13959     # setup
    13960     (clear-stream _test-input-stream)
    13961     (clear-stream $_test-input-buffered-file->buffer)
    13962     (clear-stream _test-output-stream)
    13963     (clear-stream $_test-output-buffered-file->buffer)
    13964     #
    13965     (write _test-input-stream "fn foo -> _/eax: int {\n")
    13966     (write _test-input-stream "  var y/eax: int <- copy 3\n")
    13967     (write _test-input-stream "  var z/ecx: int <- copy 4\n")
    13968     (write _test-input-stream "  return y\n")
    13969     (write _test-input-stream "}\n")
    13970     # convert
    13971     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
    13972     (flush _test-output-buffered-file)
    13973 +--  6 lines: #?     # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------
    13979     # check output
    13980     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return-register-and-local/0")
    13981     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return-register-and-local/1")
    13982     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return-register-and-local/2")
    13983     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return-register-and-local/3")
    13984     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return-register-and-local/4")
    13985     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return-register-and-local/5")
    13986     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-with-return-register-and-local/6")
    13987     (check-next-stream-line-equal _test-output-stream "    b8/copy-to-eax 3/imm32"  "F - test-convert-function-with-return-register-and-local/7")
    13988     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-return-register-and-local/8")
    13989     (check-next-stream-line-equal _test-output-stream "    b9/copy-to-ecx 4/imm32"  "F - test-convert-function-with-return-register-and-local/9")
    13990     (check-next-stream-line-equal _test-output-stream "    8b/-> %eax 0x00000000/r32" "F - test-convert-function-with-return-register-and-local/10")
    13991     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"         "F - test-convert-function-with-return-register-and-local/11")
    13992     (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")
    13993     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-return-register-and-local/13")
    13994     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return-register-and-local/14")
    13995     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return-register-and-local/15")
    13996     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return-register-and-local/16")
    13997     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return-register-and-local/17")
    13998     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return-register-and-local/18")
    13999     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return-register-and-local/19")
    14000     # . epilogue
    14001     89/<- %esp 5/r32/ebp
    14002     5d/pop-to-ebp
    14003     c3/return
    14004
    14005 test-convert-function-with-return-register-and-local-2:
    14006     # . prologue
    14007     55/push-ebp
    14008     89/<- %ebp 4/r32/esp
    14009     # setup
    14010     (clear-stream _test-input-stream)
    14011     (clear-stream $_test-input-buffered-file->buffer)
    14012     (clear-stream _test-output-stream)
    14013     (clear-stream $_test-output-buffered-file->buffer)
    14014     #
    14015     (write _test-input-stream "fn foo -> _/eax: int {\n")
    14016     (write _test-input-stream "  var y/eax: int <- copy 3\n")
    14017     (write _test-input-stream "  var z/ecx: int <- copy 4\n")
    14018     (write _test-input-stream "  return z\n")
    14019     (write _test-input-stream "}\n")
    14020     # convert
    14021     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
    14022     (flush _test-output-buffered-file)
    14023 +--  6 lines: #?     # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------
    14029     # check output
    14030     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return-register-and-local-2/0")
    14031     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return-register-and-local-2/1")
    14032     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return-register-and-local-2/2")
    14033     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return-register-and-local-2/3")
    14034     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return-register-and-local-2/4")
    14035     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return-register-and-local-2/5")
    14036     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %eax"  "F - test-convert-function-with-return-register-and-local-2/6")
    14037     (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")
    14038     (check-next-stream-line-equal _test-output-stream "    ff 6/subop/push %ecx"  "F - test-convert-function-with-return-register-and-local-2/8")
    14039     (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")
    14040     (check-next-stream-line-equal _test-output-stream "    8b/-> %ecx 0x00000000/r32" "F - test-convert-function-with-return-register-and-local-2/10")
    14041     (check-next-stream-line-equal _test-output-stream "    8f 0/subop/pop %ecx"         "F - test-convert-function-with-return-register-and-local-2/11")
    14042     (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")
    14043     (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")
    14044     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return-register-and-local-2/14")
    14045     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return-register-and-local-2/15")
    14046     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return-register-and-local-2/16")
    14047     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return-register-and-local-2/17")
    14048     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return-register-and-local-2/18")
    14049     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return-register-and-local-2/19")
    14050     # . epilogue
    14051     89/<- %esp 5/r32/ebp
    14052     5d/pop-to-ebp
    14053     c3/return
    14054
    14055 test-convert-function-with-return-float-register-and-local:
    14056     # . prologue
    14057     55/push-ebp
    14058     89/<- %ebp 4/r32/esp
    14059     # setup
    14060     (clear-stream _test-input-stream)
    14061     (clear-stream $_test-input-buffered-file->buffer)
    14062     (clear-stream _test-output-stream)
    14063     (clear-stream $_test-output-buffered-file->buffer)
    14064     #
    14065     (write _test-input-stream "fn foo -> _/xmm1: float {\n")
    14066     (write _test-input-stream "  var y/eax: int <- copy 3\n")
    14067     (write _test-input-stream "  var g/xmm0: float <- convert y\n")
    14068     (write _test-input-stream "  var h/xmm1: float <- convert y\n")
    14069     (write _test-input-stream "  return g\n")
    14070     (write _test-input-stream "}\n")
    14071     # convert
    14072     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
    14073     (flush _test-output-buffered-file)
    14074 +--  6 lines: #?     # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------
    14080     # check output
    14081     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return-float-register-and-local/0")
    14082     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return-float-register-and-local/1")
    14083     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return-float-register-and-local/2")
    14084     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return-float-register-and-local/3")
    14085     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return-float-register-and-local/4")
    14086     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return-float-register-and-local/5")
    14087     (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
    14088     (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")
    14089     (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
    14090     (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")
    14091     (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")
    14092     (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
    14093     (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")
    14094     (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")
    14095     (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
    14096     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-floating-point-dereferenced/15")  # reclaim h
    14097     (check-next-stream-line-equal _test-output-stream "    f3 0f 10/-> *esp 0/x32"  "F - test-convert-floating-point-dereferenced/16")  # reclaim g
    14098     (check-next-stream-line-equal _test-output-stream "    81 0/subop/add %esp 4/imm32"  "F - test-convert-floating-point-dereferenced/17")
    14099     (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
    14100     (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")
    14101     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return-float-register-and-local/20")
    14102     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return-float-register-and-local/21")
    14103     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return-float-register-and-local/22")
    14104     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return-float-register-and-local/23")
    14105     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return-float-register-and-local/24")
    14106     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return-float-register-and-local/25")
    14107     # . epilogue
    14108     89/<- %esp 5/r32/ebp
    14109     5d/pop-to-ebp
    14110     c3/return
    14111
    14112 test-convert-function-with-return-and-local-vars:
    14113     # . prologue
    14114     55/push-ebp
    14115     89/<- %ebp 4/r32/esp
    14116     # setup
    14117     (clear-stream _test-input-stream)
    14118     (clear-stream $_test-input-buffered-file->buffer)
    14119     (clear-stream _test-output-stream)
    14120     (clear-stream $_test-output-buffered-file->buffer)
    14121     #
    14122     (write _test-input-stream "fn foo -> _/eax: int {\n")
    14123     (write _test-input-stream "  {\n")
    14124     (write _test-input-stream "    var x: int\n")
    14125     (write _test-input-stream "    {\n")
    14126     (write _test-input-stream "      var y: int\n")
    14127     (write _test-input-stream "      return y\n")
    14128     (write _test-input-stream "      increment x\n")
    14129     (write _test-input-stream "    }\n")
    14130     (write _test-input-stream "  }\n")
    14131     (write _test-input-stream "  return 0\n")
    14132     (write _test-input-stream "}\n")
    14133     # convert
    14134     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
    14135     (flush _test-output-buffered-file)
    14136 +--  6 lines: #?     # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------
    14142     # check output
    14143     (check-next-stream-line-equal _test-output-stream "foo:"                    "F - test-convert-function-with-return-and-local-vars/0")
    14144     (check-next-stream-line-equal _test-output-stream "  # . prologue"          "F - test-convert-function-with-return-and-local-vars/1")
    14145     (check-next-stream-line-equal _test-output-stream "  55/push-ebp"           "F - test-convert-function-with-return-and-local-vars/2")
    14146     (check-next-stream-line-equal _test-output-stream "  89/<- %ebp 4/r32/esp"  "F - test-convert-function-with-return-and-local-vars/3")
    14147     (check-next-stream-line-equal _test-output-stream "  {"                     "F - test-convert-function-with-return-and-local-vars/4")
    14148     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:loop:"   "F - test-convert-function-with-return-and-local-vars/5")
    14149     (check-next-stream-line-equal _test-output-stream "    {"                   "F - test-convert-function-with-return-and-local-vars/6")
    14150     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:loop:"   "F - test-convert-function-with-return-and-local-vars/7")
    14151     (check-next-stream-line-equal _test-output-stream "      68/push 0/imm32"   "F - test-convert-function-with-return-and-local-vars/8")  # var x
    14152     (check-next-stream-line-equal _test-output-stream "      {"                 "F - test-convert-function-with-return-and-local-vars/9")
    14153     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:loop:"   "F - test-convert-function-with-return-and-local-vars/10")
    14154     (check-next-stream-line-equal _test-output-stream "        68/push 0/imm32" "F - test-convert-function-with-return-and-local-vars/11")  # var y
    14155     (check-next-stream-line-equal _test-output-stream "        8b/-> *(ebp+0xfffffff8) 0x00000000/r32" "F - test-convert-function-with-return-and-local-vars/12")
    14156     (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")
    14157     (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")
    14158     (check-next-stream-line-equal _test-output-stream "        e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-return-and-local-vars/15")
    14159     (check-next-stream-line-equal _test-output-stream "      }"                 "F - test-convert-function-with-return-and-local-vars/16")
    14160     (check-next-stream-line-equal _test-output-stream "$foo:0x00000003:break:"  "F - test-convert-function-with-return-and-local-vars/17")
    14161     (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")
    14162     (check-next-stream-line-equal _test-output-stream "    }"                   "F - test-convert-function-with-return-and-local-vars/19")
    14163     (check-next-stream-line-equal _test-output-stream "$foo:0x00000002:break:"  "F - test-convert-function-with-return-and-local-vars/20")
    14164     (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")
    14165     (check-next-stream-line-equal _test-output-stream "    e9/jump $foo:0x00000001:break/disp32"  "F - test-convert-function-with-return-and-local-vars/21")
    14166     (check-next-stream-line-equal _test-output-stream "  }"                     "F - test-convert-function-with-return-and-local-vars/21")
    14167     (check-next-stream-line-equal _test-output-stream "$foo:0x00000001:break:"  "F - test-convert-function-with-return-and-local-vars/22")
    14168     (check-next-stream-line-equal _test-output-stream "  # . epilogue"          "F - test-convert-function-with-return-and-local-vars/23")
    14169     (check-next-stream-line-equal _test-output-stream "  89/<- %esp 5/r32/ebp"  "F - test-convert-function-with-return-and-local-vars/24")
    14170     (check-next-stream-line-equal _test-output-stream "  5d/pop-to-ebp"         "F - test-convert-function-with-return-and-local-vars/25")
    14171     (check-next-stream-line-equal _test-output-stream "  c3/return"             "F - test-convert-function-with-return-and-local-vars/26")
    14172     # . epilogue
    14173     89/<- %esp 5/r32/ebp
    14174     5d/pop-to-ebp
    14175     c3/return
    14176
    14177 test-copy-object-with-no-inout:
    14178     # . prologue
    14179     55/push-ebp
    14180     89/<- %ebp 4/r32/esp
    14181     # setup
    14182     (clear-stream _test-input-stream)
    14183     (clear-stream $_test-input-buffered-file->buffer)
    14184     (clear-stream _test-output-stream)
    14185     (clear-stream $_test-output-buffered-file->buffer)
    14186     (clear-stream _test-error-stream)
    14187     (clear-stream $_test-error-buffered-file->buffer)
    14188     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    14189     68/push 0/imm32
    14190     68/push 0/imm32
    14191     89/<- %edx 4/r32/esp
    14192     (tailor-exit-descriptor %edx 0x10)
    14193     #
    14194     (write _test-input-stream "fn foo {\n")
    14195     (write _test-input-stream "  copy-object\n")
    14196     (write _test-input-stream "}\n")
    14197     # convert
    14198     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    14199     # registers except esp clobbered at this point
    14200     # restore ed
    14201     89/<- %edx 4/r32/esp
    14202     (flush _test-output-buffered-file)
    14203     (flush _test-error-buffered-file)
    14204 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
    14210     # check output
    14211     (check-stream-equal _test-output-stream  ""  "F - test-copy-object-with-no-inout: output should be empty")
    14212     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy-object' must have two inouts"  "F - test-copy-object-with-no-inout: error message")
    14213     # check that stop(1) was called
    14214     (check-ints-equal *(edx+4) 2 "F - test-copy-object-with-no-inout: exit status")
    14215     # don't restore from ebp
    14216     81 0/subop/add %esp 8/imm32
    14217     # . epilogue
    14218     5d/pop-to-ebp
    14219     c3/return
    14220
    14221 test-copy-object-with-no-source:
    14222     # . prologue
    14223     55/push-ebp
    14224     89/<- %ebp 4/r32/esp
    14225     # setup
    14226     (clear-stream _test-input-stream)
    14227     (clear-stream $_test-input-buffered-file->buffer)
    14228     (clear-stream _test-output-stream)
    14229     (clear-stream $_test-output-buffered-file->buffer)
    14230     (clear-stream _test-error-stream)
    14231     (clear-stream $_test-error-buffered-file->buffer)
    14232     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    14233     68/push 0/imm32
    14234     68/push 0/imm32
    14235     89/<- %edx 4/r32/esp
    14236     (tailor-exit-descriptor %edx 0x10)
    14237     #
    14238     (write _test-input-stream "fn foo {\n")
    14239     (write _test-input-stream "  var x: (addr int)\n")
    14240     (write _test-input-stream "  copy-object x\n")
    14241     (write _test-input-stream "}\n")
    14242     # convert
    14243     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    14244     # registers except esp clobbered at this point
    14245     # restore ed
    14246     89/<- %edx 4/r32/esp
    14247     (flush _test-output-buffered-file)
    14248     (flush _test-error-buffered-file)
    14249 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
    14255     # check output
    14256     (check-stream-equal _test-output-stream  ""  "F - test-copy-object-with-no-source: output should be empty")
    14257     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'copy-object' must have two inouts"  "F - test-copy-object-with-no-source: error message")
    14258     # check that stop(1) was called
    14259     (check-ints-equal *(edx+4) 2 "F - test-copy-object-with-no-source: exit status")
    14260     # don't restore from ebp
    14261     81 0/subop/add %esp 8/imm32
    14262     # . epilogue
    14263     5d/pop-to-ebp
    14264     c3/return
    14265
    14266 test-copy-object-with-too-many-inouts:
    14267     # . prologue
    14268     55/push-ebp
    14269     89/<- %ebp 4/r32/esp
    14270     # setup
    14271     (clear-stream _test-input-stream)
    14272     (clear-stream $_test-input-buffered-file->buffer)
    14273     (clear-stream _test-output-stream)
    14274     (clear-stream $_test-output-buffered-file->buffer)
    14275     (clear-stream _test-error-stream)
    14276     (clear-stream $_test-error-buffered-file->buffer)
    14277     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    14278     68/push 0/imm32
    14279     68/push 0/imm32
    14280     89/<- %edx 4/r32/esp
    14281     (tailor-exit-descriptor %edx 0x10)
    14282     #
    14283     (write _test-input-stream "fn foo {\n")
    14284     (write _test-input-stream "  var x: (addr boolean)\n")
    14285     (write _test-input-stream "  copy-object x, x, x\n")
    14286     (write _test-input-stream "}\n")
    14287     # convert
    14288     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    14289     # registers except esp clobbered at this point
    14290     # restore ed
    14291     89/<- %edx 4/r32/esp
    14292     (flush _test-output-buffered-file)
    14293     (flush _test-error-buffered-file)
    14294 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
    14300     # check output
    14301     (check-stream-equal _test-output-stream  ""  "F - test-copy-object-with-too-many-inouts: output should be empty")
    14302     (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")
    14303     # check that stop(1) was called
    14304     (check-ints-equal *(edx+4) 2 "F - test-copy-object-with-too-many-inouts: exit status")
    14305     # don't restore from ebp
    14306     81 0/subop/add %esp 8/imm32
    14307     # . epilogue
    14308     5d/pop-to-ebp
    14309     c3/return
    14310
    14311 test-copy-object-with-output:
    14312     # . prologue
    14313     55/push-ebp
    14314     89/<- %ebp 4/r32/esp
    14315     # setup
    14316     (clear-stream _test-input-stream)
    14317     (clear-stream $_test-input-buffered-file->buffer)
    14318     (clear-stream _test-output-stream)
    14319     (clear-stream $_test-output-buffered-file->buffer)
    14320     (clear-stream _test-error-stream)
    14321     (clear-stream $_test-error-buffered-file->buffer)
    14322     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    14323     68/push 0/imm32
    14324     68/push 0/imm32
    14325     89/<- %edx 4/r32/esp
    14326     (tailor-exit-descriptor %edx 0x10)
    14327     #
    14328     (write _test-input-stream "fn foo {\n")
    14329     (write _test-input-stream "  var x/eax: (addr boolean) <- copy 0\n")
    14330     (write _test-input-stream "  var y/ecx: (addr boolean) <- copy 0\n")
    14331     (write _test-input-stream "  x <- copy-object x, y\n")
    14332     (write _test-input-stream "}\n")
    14333     # convert
    14334     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    14335     # registers except esp clobbered at this point
    14336     # restore ed
    14337     89/<- %edx 4/r32/esp
    14338     (flush _test-output-buffered-file)
    14339     (flush _test-error-buffered-file)
    14340 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
    14346     # check output
    14347     (check-stream-equal _test-output-stream  ""  "F - test-copy-object-with-output: output should be empty")
    14348     (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")
    14349     # check that stop(1) was called
    14350     (check-ints-equal *(edx+4) 2 "F - test-copy-object-with-output: exit status")
    14351     # don't restore from ebp
    14352     81 0/subop/add %esp 8/imm32
    14353     # . epilogue
    14354     5d/pop-to-ebp
    14355     c3/return
    14356
    14357 test-copy-object-deref-address:
    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     #
    14367     (write _test-input-stream "fn foo {\n")
    14368     (write _test-input-stream "  var x/eax: (addr int) <- copy 0\n")
    14369     (write _test-input-stream "  var y/ecx: (addr addr int) <- copy 0\n")
    14370     (write _test-input-stream "  copy-object *y, x\n")
    14371     (write _test-input-stream "}\n")
    14372     # convert
    14373     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
    14374     (flush _test-output-buffered-file)
    14375     # no errors
    14376     # . epilogue
    14377     5d/pop-to-ebp
    14378     c3/return
    14379
    14380 test-copy-object-non-addr:
    14381     # . prologue
    14382     55/push-ebp
    14383     89/<- %ebp 4/r32/esp
    14384     # setup
    14385     (clear-stream _test-input-stream)
    14386     (clear-stream $_test-input-buffered-file->buffer)
    14387     (clear-stream _test-output-stream)
    14388     (clear-stream $_test-output-buffered-file->buffer)
    14389     (clear-stream _test-error-stream)
    14390     (clear-stream $_test-error-buffered-file->buffer)
    14391     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    14392     68/push 0/imm32
    14393     68/push 0/imm32
    14394     89/<- %edx 4/r32/esp
    14395     (tailor-exit-descriptor %edx 0x10)
    14396     #
    14397     (write _test-input-stream "fn foo {\n")
    14398     (write _test-input-stream "  var x: int\n")
    14399     (write _test-input-stream "  var y: int\n")
    14400     (write _test-input-stream "  copy-object y, x\n")
    14401     (write _test-input-stream "}\n")
    14402     # convert
    14403     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    14404     # registers except esp clobbered at this point
    14405     # restore ed
    14406     89/<- %edx 4/r32/esp
    14407     (flush _test-output-buffered-file)
    14408     (flush _test-error-buffered-file)
    14409 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
    14415     # check output
    14416     (check-stream-equal _test-output-stream  ""  "F - test-copy-object-non-addr: output should be empty")
    14417     (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")
    14418     # check that stop(1) was called
    14419     (check-ints-equal *(edx+4) 2 "F - test-copy-object-non-addr: exit status")
    14420     # don't restore from ebp
    14421     81 0/subop/add %esp 8/imm32
    14422     # . epilogue
    14423     5d/pop-to-ebp
    14424     c3/return
    14425
    14426 test-copy-object-non-equal:
    14427     # . prologue
    14428     55/push-ebp
    14429     89/<- %ebp 4/r32/esp
    14430     # setup
    14431     (clear-stream _test-input-stream)
    14432     (clear-stream $_test-input-buffered-file->buffer)
    14433     (clear-stream _test-output-stream)
    14434     (clear-stream $_test-output-buffered-file->buffer)
    14435     (clear-stream _test-error-stream)
    14436     (clear-stream $_test-error-buffered-file->buffer)
    14437     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    14438     68/push 0/imm32
    14439     68/push 0/imm32
    14440     89/<- %edx 4/r32/esp
    14441     (tailor-exit-descriptor %edx 0x10)
    14442     #
    14443     (write _test-input-stream "fn foo {\n")
    14444     (write _test-input-stream "  var x: (addr int)\n")
    14445     (write _test-input-stream "  var y: (addr boolean)\n")
    14446     (write _test-input-stream "  copy-object y, x\n")
    14447     (write _test-input-stream "}\n")
    14448     # convert
    14449     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    14450     # registers except esp clobbered at this point
    14451     # restore ed
    14452     89/<- %edx 4/r32/esp
    14453     (flush _test-output-buffered-file)
    14454     (flush _test-error-buffered-file)
    14455 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
    14461     # check output
    14462     (check-stream-equal _test-output-stream  ""  "F - test-copy-object-non-equal: output should be empty")
    14463     (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")
    14464     # check that stop(1) was called
    14465     (check-ints-equal *(edx+4) 2 "F - test-copy-object-non-equal: exit status")
    14466     # don't restore from ebp
    14467     81 0/subop/add %esp 8/imm32
    14468     # . epilogue
    14469     5d/pop-to-ebp
    14470     c3/return
    14471
    14472 test-allocate-with-no-inout:
    14473     # . prologue
    14474     55/push-ebp
    14475     89/<- %ebp 4/r32/esp
    14476     # setup
    14477     (clear-stream _test-input-stream)
    14478     (clear-stream $_test-input-buffered-file->buffer)
    14479     (clear-stream _test-output-stream)
    14480     (clear-stream $_test-output-buffered-file->buffer)
    14481     (clear-stream _test-error-stream)
    14482     (clear-stream $_test-error-buffered-file->buffer)
    14483     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    14484     68/push 0/imm32
    14485     68/push 0/imm32
    14486     89/<- %edx 4/r32/esp
    14487     (tailor-exit-descriptor %edx 0x10)
    14488     #
    14489     (write _test-input-stream "fn foo {\n")
    14490     (write _test-input-stream "  allocate\n")
    14491     (write _test-input-stream "}\n")
    14492     # convert
    14493     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    14494     # registers except esp clobbered at this point
    14495     # restore ed
    14496     89/<- %edx 4/r32/esp
    14497     (flush _test-output-buffered-file)
    14498     (flush _test-error-buffered-file)
    14499 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
    14505     # check output
    14506     (check-stream-equal _test-output-stream  ""  "F - test-allocate-with-no-inout: output should be empty")
    14507     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'allocate' must have a single inout"  "F - test-allocate-with-no-inout: error message")
    14508     # check that stop(1) was called
    14509     (check-ints-equal *(edx+4) 2 "F - test-allocate-with-no-inout: exit status")
    14510     # don't restore from ebp
    14511     81 0/subop/add %esp 8/imm32
    14512     # . epilogue
    14513     5d/pop-to-ebp
    14514     c3/return
    14515
    14516 test-allocate-with-too-many-inouts:
    14517     # . prologue
    14518     55/push-ebp
    14519     89/<- %ebp 4/r32/esp
    14520     # setup
    14521     (clear-stream _test-input-stream)
    14522     (clear-stream $_test-input-buffered-file->buffer)
    14523     (clear-stream _test-output-stream)
    14524     (clear-stream $_test-output-buffered-file->buffer)
    14525     (clear-stream _test-error-stream)
    14526     (clear-stream $_test-error-buffered-file->buffer)
    14527     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    14528     68/push 0/imm32
    14529     68/push 0/imm32
    14530     89/<- %edx 4/r32/esp
    14531     (tailor-exit-descriptor %edx 0x10)
    14532     #
    14533     (write _test-input-stream "fn foo {\n")
    14534     (write _test-input-stream "  var x: (addr handle int)\n")
    14535     (write _test-input-stream "  allocate x, 0\n")
    14536     (write _test-input-stream "}\n")
    14537     # convert
    14538     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    14539     # registers except esp clobbered at this point
    14540     # restore ed
    14541     89/<- %edx 4/r32/esp
    14542     (flush _test-output-buffered-file)
    14543     (flush _test-error-buffered-file)
    14544 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
    14550     # check output
    14551     (check-stream-equal _test-output-stream  ""  "F - test-allocate-with-too-many-inouts: output should be empty")
    14552     (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")
    14553     # check that stop(1) was called
    14554     (check-ints-equal *(edx+4) 2 "F - test-allocate-with-too-many-inouts: exit status")
    14555     # don't restore from ebp
    14556     81 0/subop/add %esp 8/imm32
    14557     # . epilogue
    14558     5d/pop-to-ebp
    14559     c3/return
    14560
    14561 test-allocate-with-output:
    14562     # . prologue
    14563     55/push-ebp
    14564     89/<- %ebp 4/r32/esp
    14565     # setup
    14566     (clear-stream _test-input-stream)
    14567     (clear-stream $_test-input-buffered-file->buffer)
    14568     (clear-stream _test-output-stream)
    14569     (clear-stream $_test-output-buffered-file->buffer)
    14570     (clear-stream _test-error-stream)
    14571     (clear-stream $_test-error-buffered-file->buffer)
    14572     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    14573     68/push 0/imm32
    14574     68/push 0/imm32
    14575     89/<- %edx 4/r32/esp
    14576     (tailor-exit-descriptor %edx 0x10)
    14577     #
    14578     (write _test-input-stream "fn foo {\n")
    14579     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
    14580     (write _test-input-stream "  var y/ecx: (addr handle int) <- copy 0\n")
    14581     (write _test-input-stream "  x <- allocate y\n")
    14582     (write _test-input-stream "}\n")
    14583     # convert
    14584     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    14585     # registers except esp clobbered at this point
    14586     # restore ed
    14587     89/<- %edx 4/r32/esp
    14588     (flush _test-output-buffered-file)
    14589     (flush _test-error-buffered-file)
    14590 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
    14596     # check output
    14597     (check-stream-equal _test-output-stream  ""  "F - test-allocate-with-output: output should be empty")
    14598     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'allocate' must not have any outputs"  "F - test-allocate-with-output: error message")
    14599     # check that stop(1) was called
    14600     (check-ints-equal *(edx+4) 2 "F - test-allocate-with-output: exit status")
    14601     # don't restore from ebp
    14602     81 0/subop/add %esp 8/imm32
    14603     # . epilogue
    14604     5d/pop-to-ebp
    14605     c3/return
    14606
    14607 test-allocate-non-addr:
    14608     # . prologue
    14609     55/push-ebp
    14610     89/<- %ebp 4/r32/esp
    14611     # setup
    14612     (clear-stream _test-input-stream)
    14613     (clear-stream $_test-input-buffered-file->buffer)
    14614     (clear-stream _test-output-stream)
    14615     (clear-stream $_test-output-buffered-file->buffer)
    14616     (clear-stream _test-error-stream)
    14617     (clear-stream $_test-error-buffered-file->buffer)
    14618     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    14619     68/push 0/imm32
    14620     68/push 0/imm32
    14621     89/<- %edx 4/r32/esp
    14622     (tailor-exit-descriptor %edx 0x10)
    14623     #
    14624     (write _test-input-stream "fn foo {\n")
    14625     (write _test-input-stream "  var y: (handle int)\n")
    14626     (write _test-input-stream "  allocate y\n")
    14627     (write _test-input-stream "}\n")
    14628     # convert
    14629     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    14630     # registers except esp clobbered at this point
    14631     # restore ed
    14632     89/<- %edx 4/r32/esp
    14633     (flush _test-output-buffered-file)
    14634     (flush _test-error-buffered-file)
    14635 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
    14641     # check output
    14642     (check-stream-equal _test-output-stream  ""  "F - test-allocate-non-addr: output must be empty")
    14643     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt allocate: inout 'y' must have type (addr handle ...)"  "F - test-allocate-non-addr: error message")
    14644     # check that stop(1) was called
    14645     (check-ints-equal *(edx+4) 2 "F - test-allocate-non-addr: exit status")
    14646     # don't restore from ebp
    14647     81 0/subop/add %esp 8/imm32
    14648     # . epilogue
    14649     5d/pop-to-ebp
    14650     c3/return
    14651
    14652 test-allocate-non-addr-handle:
    14653     # . prologue
    14654     55/push-ebp
    14655     89/<- %ebp 4/r32/esp
    14656     # setup
    14657     (clear-stream _test-input-stream)
    14658     (clear-stream $_test-input-buffered-file->buffer)
    14659     (clear-stream _test-output-stream)
    14660     (clear-stream $_test-output-buffered-file->buffer)
    14661     (clear-stream _test-error-stream)
    14662     (clear-stream $_test-error-buffered-file->buffer)
    14663     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    14664     68/push 0/imm32
    14665     68/push 0/imm32
    14666     89/<- %edx 4/r32/esp
    14667     (tailor-exit-descriptor %edx 0x10)
    14668     #
    14669     (write _test-input-stream "fn foo {\n")
    14670     (write _test-input-stream "  var y/ecx: (addr int) <- copy 0\n")
    14671     (write _test-input-stream "  allocate y\n")
    14672     (write _test-input-stream "}\n")
    14673     # convert
    14674     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    14675     # registers except esp clobbered at this point
    14676     # restore ed
    14677     89/<- %edx 4/r32/esp
    14678     (flush _test-output-buffered-file)
    14679     (flush _test-error-buffered-file)
    14680 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
    14686     # check output
    14687     (check-stream-equal _test-output-stream  ""  "F - test-allocate-non-addr-handle: output should be empty")
    14688     (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")
    14689     # check that stop(1) was called
    14690     (check-ints-equal *(edx+4) 2 "F - test-allocate-non-addr-handle: exit status")
    14691     # don't restore from ebp
    14692     81 0/subop/add %esp 8/imm32
    14693     # . epilogue
    14694     5d/pop-to-ebp
    14695     c3/return
    14696
    14697 test-allocate-deref-address:
    14698     # . prologue
    14699     55/push-ebp
    14700     89/<- %ebp 4/r32/esp
    14701     # setup
    14702     (clear-stream _test-input-stream)
    14703     (clear-stream $_test-input-buffered-file->buffer)
    14704     (clear-stream _test-output-stream)
    14705     (clear-stream $_test-output-buffered-file->buffer)
    14706     #
    14707     (write _test-input-stream "fn foo {\n")
    14708     (write _test-input-stream "  var y/ecx: (addr addr handle int) <- copy 0\n")
    14709     (write _test-input-stream "  allocate *y\n")
    14710     (write _test-input-stream "}\n")
    14711     # convert
    14712     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
    14713     (flush _test-output-buffered-file)
    14714     # no errors
    14715     # . epilogue
    14716     5d/pop-to-ebp
    14717     c3/return
    14718
    14719 test-populate-with-no-inout:
    14720     # . prologue
    14721     55/push-ebp
    14722     89/<- %ebp 4/r32/esp
    14723     # setup
    14724     (clear-stream _test-input-stream)
    14725     (clear-stream $_test-input-buffered-file->buffer)
    14726     (clear-stream _test-output-stream)
    14727     (clear-stream $_test-output-buffered-file->buffer)
    14728     (clear-stream _test-error-stream)
    14729     (clear-stream $_test-error-buffered-file->buffer)
    14730     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    14731     68/push 0/imm32
    14732     68/push 0/imm32
    14733     89/<- %edx 4/r32/esp
    14734     (tailor-exit-descriptor %edx 0x10)
    14735     #
    14736     (write _test-input-stream "fn foo {\n")
    14737     (write _test-input-stream "  populate\n")
    14738     (write _test-input-stream "}\n")
    14739     # convert
    14740     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    14741     # registers except esp clobbered at this point
    14742     # restore ed
    14743     89/<- %edx 4/r32/esp
    14744     (flush _test-output-buffered-file)
    14745     (flush _test-error-buffered-file)
    14746 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
    14752     # check output
    14753     (check-stream-equal _test-output-stream  ""  "F - test-populate-with-no-inout: output should be empty")
    14754     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'populate' must have two inouts"  "F - test-populate-with-no-inout: error message")
    14755     # check that stop(1) was called
    14756     (check-ints-equal *(edx+4) 2 "F - test-populate-with-no-inout: exit status")
    14757     # don't restore from ebp
    14758     81 0/subop/add %esp 8/imm32
    14759     # . epilogue
    14760     5d/pop-to-ebp
    14761     c3/return
    14762
    14763 test-populate-with-too-many-inouts:
    14764     # . prologue
    14765     55/push-ebp
    14766     89/<- %ebp 4/r32/esp
    14767     # setup
    14768     (clear-stream _test-input-stream)
    14769     (clear-stream $_test-input-buffered-file->buffer)
    14770     (clear-stream _test-output-stream)
    14771     (clear-stream $_test-output-buffered-file->buffer)
    14772     (clear-stream _test-error-stream)
    14773     (clear-stream $_test-error-buffered-file->buffer)
    14774     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    14775     68/push 0/imm32
    14776     68/push 0/imm32
    14777     89/<- %edx 4/r32/esp
    14778     (tailor-exit-descriptor %edx 0x10)
    14779     #
    14780     (write _test-input-stream "fn foo {\n")
    14781     (write _test-input-stream "  var x: (addr handle int)\n")
    14782     (write _test-input-stream "  populate x, 3, 0\n")
    14783     (write _test-input-stream "}\n")
    14784     # convert
    14785     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    14786     # registers except esp clobbered at this point
    14787     # restore ed
    14788     89/<- %edx 4/r32/esp
    14789     (flush _test-output-buffered-file)
    14790     (flush _test-error-buffered-file)
    14791 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
    14797     # check output
    14798     (check-stream-equal _test-output-stream  ""  "F - test-populate-with-too-many-inouts: output should be empty")
    14799     (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")
    14800     # check that stop(1) was called
    14801     (check-ints-equal *(edx+4) 2 "F - test-populate-with-too-many-inouts: exit status")
    14802     # don't restore from ebp
    14803     81 0/subop/add %esp 8/imm32
    14804     # . epilogue
    14805     5d/pop-to-ebp
    14806     c3/return
    14807
    14808 test-populate-with-output:
    14809     # . prologue
    14810     55/push-ebp
    14811     89/<- %ebp 4/r32/esp
    14812     # setup
    14813     (clear-stream _test-input-stream)
    14814     (clear-stream $_test-input-buffered-file->buffer)
    14815     (clear-stream _test-output-stream)
    14816     (clear-stream $_test-output-buffered-file->buffer)
    14817     (clear-stream _test-error-stream)
    14818     (clear-stream $_test-error-buffered-file->buffer)
    14819     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    14820     68/push 0/imm32
    14821     68/push 0/imm32
    14822     89/<- %edx 4/r32/esp
    14823     (tailor-exit-descriptor %edx 0x10)
    14824     #
    14825     (write _test-input-stream "fn foo {\n")
    14826     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
    14827     (write _test-input-stream "  var y/ecx: (addr handle int) <- copy 0\n")
    14828     (write _test-input-stream "  x <- populate y\n")
    14829     (write _test-input-stream "}\n")
    14830     # convert
    14831     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    14832     # registers except esp clobbered at this point
    14833     # restore ed
    14834     89/<- %edx 4/r32/esp
    14835     (flush _test-output-buffered-file)
    14836     (flush _test-error-buffered-file)
    14837 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
    14843     # check output
    14844     (check-stream-equal _test-output-stream  ""  "F - test-populate-with-output: output should be empty")
    14845     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'populate' must not have any outputs"  "F - test-populate-with-output: error message")
    14846     # check that stop(1) was called
    14847     (check-ints-equal *(edx+4) 2 "F - test-populate-with-output: exit status")
    14848     # don't restore from ebp
    14849     81 0/subop/add %esp 8/imm32
    14850     # . epilogue
    14851     5d/pop-to-ebp
    14852     c3/return
    14853
    14854 test-populate-non-addr:
    14855     # . prologue
    14856     55/push-ebp
    14857     89/<- %ebp 4/r32/esp
    14858     # setup
    14859     (clear-stream _test-input-stream)
    14860     (clear-stream $_test-input-buffered-file->buffer)
    14861     (clear-stream _test-output-stream)
    14862     (clear-stream $_test-output-buffered-file->buffer)
    14863     (clear-stream _test-error-stream)
    14864     (clear-stream $_test-error-buffered-file->buffer)
    14865     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    14866     68/push 0/imm32
    14867     68/push 0/imm32
    14868     89/<- %edx 4/r32/esp
    14869     (tailor-exit-descriptor %edx 0x10)
    14870     #
    14871     (write _test-input-stream "fn foo {\n")
    14872     (write _test-input-stream "  var y: (handle int)\n")
    14873     (write _test-input-stream "  populate y, 3\n")
    14874     (write _test-input-stream "}\n")
    14875     # convert
    14876     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    14877     # registers except esp clobbered at this point
    14878     # restore ed
    14879     89/<- %edx 4/r32/esp
    14880     (flush _test-output-buffered-file)
    14881     (flush _test-error-buffered-file)
    14882 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
    14888     # check output
    14889     (check-stream-equal _test-output-stream  ""  "F - test-populate-non-addr: output must be empty")
    14890     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt populate: first inout 'y' must have type (addr handle array ...)"  "F - test-populate-non-addr: error message")
    14891     # check that stop(1) was called
    14892     (check-ints-equal *(edx+4) 2 "F - test-populate-non-addr: exit status")
    14893     # don't restore from ebp
    14894     81 0/subop/add %esp 8/imm32
    14895     # . epilogue
    14896     5d/pop-to-ebp
    14897     c3/return
    14898
    14899 test-populate-non-addr-handle:
    14900     # . prologue
    14901     55/push-ebp
    14902     89/<- %ebp 4/r32/esp
    14903     # setup
    14904     (clear-stream _test-input-stream)
    14905     (clear-stream $_test-input-buffered-file->buffer)
    14906     (clear-stream _test-output-stream)
    14907     (clear-stream $_test-output-buffered-file->buffer)
    14908     (clear-stream _test-error-stream)
    14909     (clear-stream $_test-error-buffered-file->buffer)
    14910     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    14911     68/push 0/imm32
    14912     68/push 0/imm32
    14913     89/<- %edx 4/r32/esp
    14914     (tailor-exit-descriptor %edx 0x10)
    14915     #
    14916     (write _test-input-stream "fn foo {\n")
    14917     (write _test-input-stream "  var y/ecx: (addr int) <- copy 0\n")
    14918     (write _test-input-stream "  populate y, 3\n")
    14919     (write _test-input-stream "}\n")
    14920     # convert
    14921     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    14922     # registers except esp clobbered at this point
    14923     # restore ed
    14924     89/<- %edx 4/r32/esp
    14925     (flush _test-output-buffered-file)
    14926     (flush _test-error-buffered-file)
    14927 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
    14933     # check output
    14934     (check-stream-equal _test-output-stream  ""  "F - test-populate-non-addr-handle: output should be empty")
    14935     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt populate: first inout 'y' must have type (addr handle array ...)"  "F - test-populate-non-addr-handle: error message")
    14936     # check that stop(1) was called
    14937     (check-ints-equal *(edx+4) 2 "F - test-populate-non-addr-handle: exit status")
    14938     # don't restore from ebp
    14939     81 0/subop/add %esp 8/imm32
    14940     # . epilogue
    14941     5d/pop-to-ebp
    14942     c3/return
    14943
    14944 test-populate-non-addr-handle-array:
    14945     # . prologue
    14946     55/push-ebp
    14947     89/<- %ebp 4/r32/esp
    14948     # setup
    14949     (clear-stream _test-input-stream)
    14950     (clear-stream $_test-input-buffered-file->buffer)
    14951     (clear-stream _test-output-stream)
    14952     (clear-stream $_test-output-buffered-file->buffer)
    14953     (clear-stream _test-error-stream)
    14954     (clear-stream $_test-error-buffered-file->buffer)
    14955     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    14956     68/push 0/imm32
    14957     68/push 0/imm32
    14958     89/<- %edx 4/r32/esp
    14959     (tailor-exit-descriptor %edx 0x10)
    14960     #
    14961     (write _test-input-stream "fn foo {\n")
    14962     (write _test-input-stream "  var y/ecx: (addr handle int) <- copy 0\n")
    14963     (write _test-input-stream "  populate y, 3\n")
    14964     (write _test-input-stream "}\n")
    14965     # convert
    14966     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    14967     # registers except esp clobbered at this point
    14968     # restore ed
    14969     89/<- %edx 4/r32/esp
    14970     (flush _test-output-buffered-file)
    14971     (flush _test-error-buffered-file)
    14972 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
    14978     # check output
    14979     (check-stream-equal _test-output-stream  ""  "F - test-populate-non-addr-handle-array: output should be empty")
    14980     (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")
    14981     # check that stop(1) was called
    14982     (check-ints-equal *(edx+4) 2 "F - test-populate-non-addr-handle-array: exit status")
    14983     # don't restore from ebp
    14984     81 0/subop/add %esp 8/imm32
    14985     # . epilogue
    14986     5d/pop-to-ebp
    14987     c3/return
    14988
    14989 test-populate-deref-address:
    14990     # . prologue
    14991     55/push-ebp
    14992     89/<- %ebp 4/r32/esp
    14993     # setup
    14994     (clear-stream _test-input-stream)
    14995     (clear-stream $_test-input-buffered-file->buffer)
    14996     (clear-stream _test-output-stream)
    14997     (clear-stream $_test-output-buffered-file->buffer)
    14998     #
    14999     (write _test-input-stream "fn foo {\n")
    15000     (write _test-input-stream "  var y/ecx: (addr addr handle array int) <- copy 0\n")
    15001     (write _test-input-stream "  populate *y, 3\n")
    15002     (write _test-input-stream "}\n")
    15003     # convert
    15004     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
    15005     (flush _test-output-buffered-file)
    15006     # no errors
    15007     # . epilogue
    15008     5d/pop-to-ebp
    15009     c3/return
    15010
    15011 test-populate-stream-with-no-inout:
    15012     # . prologue
    15013     55/push-ebp
    15014     89/<- %ebp 4/r32/esp
    15015     # setup
    15016     (clear-stream _test-input-stream)
    15017     (clear-stream $_test-input-buffered-file->buffer)
    15018     (clear-stream _test-output-stream)
    15019     (clear-stream $_test-output-buffered-file->buffer)
    15020     (clear-stream _test-error-stream)
    15021     (clear-stream $_test-error-buffered-file->buffer)
    15022     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    15023     68/push 0/imm32
    15024     68/push 0/imm32
    15025     89/<- %edx 4/r32/esp
    15026     (tailor-exit-descriptor %edx 0x10)
    15027     #
    15028     (write _test-input-stream "fn foo {\n")
    15029     (write _test-input-stream "  populate-stream\n")
    15030     (write _test-input-stream "}\n")
    15031     # convert
    15032     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    15033     # registers except esp clobbered at this point
    15034     # restore ed
    15035     89/<- %edx 4/r32/esp
    15036     (flush _test-output-buffered-file)
    15037     (flush _test-error-buffered-file)
    15038 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
    15044     # check output
    15045     (check-stream-equal _test-output-stream  ""  "F - test-populate-stream-with-no-inout: output should be empty")
    15046     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'populate-stream' must have two inouts"  "F - test-populate-stream-with-no-inout: error message")
    15047     # check that stop(1) was called
    15048     (check-ints-equal *(edx+4) 2 "F - test-populate-stream-with-no-inout: exit status")
    15049     # don't restore from ebp
    15050     81 0/subop/add %esp 8/imm32
    15051     # . epilogue
    15052     5d/pop-to-ebp
    15053     c3/return
    15054
    15055 test-populate-stream-with-too-many-inouts:
    15056     # . prologue
    15057     55/push-ebp
    15058     89/<- %ebp 4/r32/esp
    15059     # setup
    15060     (clear-stream _test-input-stream)
    15061     (clear-stream $_test-input-buffered-file->buffer)
    15062     (clear-stream _test-output-stream)
    15063     (clear-stream $_test-output-buffered-file->buffer)
    15064     (clear-stream _test-error-stream)
    15065     (clear-stream $_test-error-buffered-file->buffer)
    15066     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    15067     68/push 0/imm32
    15068     68/push 0/imm32
    15069     89/<- %edx 4/r32/esp
    15070     (tailor-exit-descriptor %edx 0x10)
    15071     #
    15072     (write _test-input-stream "fn foo {\n")
    15073     (write _test-input-stream "  var x: (addr handle int)\n")
    15074     (write _test-input-stream "  populate-stream x, 3, 0\n")
    15075     (write _test-input-stream "}\n")
    15076     # convert
    15077     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    15078     # registers except esp clobbered at this point
    15079     # restore ed
    15080     89/<- %edx 4/r32/esp
    15081     (flush _test-output-buffered-file)
    15082     (flush _test-error-buffered-file)
    15083 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
    15089     # check output
    15090     (check-stream-equal _test-output-stream  ""  "F - test-populate-stream-with-too-many-inouts: output should be empty")
    15091     (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")
    15092     # check that stop(1) was called
    15093     (check-ints-equal *(edx+4) 2 "F - test-populate-stream-with-too-many-inouts: exit status")
    15094     # don't restore from ebp
    15095     81 0/subop/add %esp 8/imm32
    15096     # . epilogue
    15097     5d/pop-to-ebp
    15098     c3/return
    15099
    15100 test-populate-stream-with-output:
    15101     # . prologue
    15102     55/push-ebp
    15103     89/<- %ebp 4/r32/esp
    15104     # setup
    15105     (clear-stream _test-input-stream)
    15106     (clear-stream $_test-input-buffered-file->buffer)
    15107     (clear-stream _test-output-stream)
    15108     (clear-stream $_test-output-buffered-file->buffer)
    15109     (clear-stream _test-error-stream)
    15110     (clear-stream $_test-error-buffered-file->buffer)
    15111     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    15112     68/push 0/imm32
    15113     68/push 0/imm32
    15114     89/<- %edx 4/r32/esp
    15115     (tailor-exit-descriptor %edx 0x10)
    15116     #
    15117     (write _test-input-stream "fn foo {\n")
    15118     (write _test-input-stream "  var x/eax: boolean <- copy 0\n")
    15119     (write _test-input-stream "  var y/ecx: (addr handle int) <- copy 0\n")
    15120     (write _test-input-stream "  x <- populate-stream y\n")
    15121     (write _test-input-stream "}\n")
    15122     # convert
    15123     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    15124     # registers except esp clobbered at this point
    15125     # restore ed
    15126     89/<- %edx 4/r32/esp
    15127     (flush _test-output-buffered-file)
    15128     (flush _test-error-buffered-file)
    15129 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
    15135     # check output
    15136     (check-stream-equal _test-output-stream  ""  "F - test-populate-stream-with-output: output should be empty")
    15137     (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")
    15138     # check that stop(1) was called
    15139     (check-ints-equal *(edx+4) 2 "F - test-populate-stream-with-output: exit status")
    15140     # don't restore from ebp
    15141     81 0/subop/add %esp 8/imm32
    15142     # . epilogue
    15143     5d/pop-to-ebp
    15144     c3/return
    15145
    15146 test-populate-stream-non-addr:
    15147     # . prologue
    15148     55/push-ebp
    15149     89/<- %ebp 4/r32/esp
    15150     # setup
    15151     (clear-stream _test-input-stream)
    15152     (clear-stream $_test-input-buffered-file->buffer)
    15153     (clear-stream _test-output-stream)
    15154     (clear-stream $_test-output-buffered-file->buffer)
    15155     (clear-stream _test-error-stream)
    15156     (clear-stream $_test-error-buffered-file->buffer)
    15157     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    15158     68/push 0/imm32
    15159     68/push 0/imm32
    15160     89/<- %edx 4/r32/esp
    15161     (tailor-exit-descriptor %edx 0x10)
    15162     #
    15163     (write _test-input-stream "fn foo {\n")
    15164     (write _test-input-stream "  var y: (handle int)\n")
    15165     (write _test-input-stream "  populate-stream y, 3\n")
    15166     (write _test-input-stream "}\n")
    15167     # convert
    15168     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    15169     # registers except esp clobbered at this point
    15170     # restore ed
    15171     89/<- %edx 4/r32/esp
    15172     (flush _test-output-buffered-file)
    15173     (flush _test-error-buffered-file)
    15174 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
    15180     # check output
    15181     (check-stream-equal _test-output-stream  ""  "F - test-populate-stream-non-addr: output must be empty")
    15182     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt populate-stream: first inout 'y' must have type (addr handle stream ...)"  "F - test-populate-stream-non-addr: error message")
    15183     # check that stop(1) was called
    15184     (check-ints-equal *(edx+4) 2 "F - test-populate-stream-non-addr: exit status")
    15185     # don't restore from ebp
    15186     81 0/subop/add %esp 8/imm32
    15187     # . epilogue
    15188     5d/pop-to-ebp
    15189     c3/return
    15190
    15191 test-populate-stream-non-addr-handle:
    15192     # . prologue
    15193     55/push-ebp
    15194     89/<- %ebp 4/r32/esp
    15195     # setup
    15196     (clear-stream _test-input-stream)
    15197     (clear-stream $_test-input-buffered-file->buffer)
    15198     (clear-stream _test-output-stream)
    15199     (clear-stream $_test-output-buffered-file->buffer)
    15200     (clear-stream _test-error-stream)
    15201     (clear-stream $_test-error-buffered-file->buffer)
    15202     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    15203     68/push 0/imm32
    15204     68/push 0/imm32
    15205     89/<- %edx 4/r32/esp
    15206     (tailor-exit-descriptor %edx 0x10)
    15207     #
    15208     (write _test-input-stream "fn foo {\n")
    15209     (write _test-input-stream "  var y/ecx: (addr int) <- copy 0\n")
    15210     (write _test-input-stream "  populate-stream y, 3\n")
    15211     (write _test-input-stream "}\n")
    15212     # convert
    15213     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    15214     # registers except esp clobbered at this point
    15215     # restore ed
    15216     89/<- %edx 4/r32/esp
    15217     (flush _test-output-buffered-file)
    15218     (flush _test-error-buffered-file)
    15219 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
    15225     # check output
    15226     (check-stream-equal _test-output-stream  ""  "F - test-populate-stream-non-addr-handle: output should be empty")
    15227     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt populate-stream: first inout 'y' must have type (addr handle stream ...)"  "F - test-populate-stream-non-addr-handle: error message")
    15228     # check that stop(1) was called
    15229     (check-ints-equal *(edx+4) 2 "F - test-populate-stream-non-addr-handle: exit status")
    15230     # don't restore from ebp
    15231     81 0/subop/add %esp 8/imm32
    15232     # . epilogue
    15233     5d/pop-to-ebp
    15234     c3/return
    15235
    15236 test-populate-stream-non-addr-handle-stream:
    15237     # . prologue
    15238     55/push-ebp
    15239     89/<- %ebp 4/r32/esp
    15240     # setup
    15241     (clear-stream _test-input-stream)
    15242     (clear-stream $_test-input-buffered-file->buffer)
    15243     (clear-stream _test-output-stream)
    15244     (clear-stream $_test-output-buffered-file->buffer)
    15245     (clear-stream _test-error-stream)
    15246     (clear-stream $_test-error-buffered-file->buffer)
    15247     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    15248     68/push 0/imm32
    15249     68/push 0/imm32
    15250     89/<- %edx 4/r32/esp
    15251     (tailor-exit-descriptor %edx 0x10)
    15252     #
    15253     (write _test-input-stream "fn foo {\n")
    15254     (write _test-input-stream "  var y/ecx: (addr handle int) <- copy 0\n")
    15255     (write _test-input-stream "  populate-stream y, 3\n")
    15256     (write _test-input-stream "}\n")
    15257     # convert
    15258     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    15259     # registers except esp clobbered at this point
    15260     # restore ed
    15261     89/<- %edx 4/r32/esp
    15262     (flush _test-output-buffered-file)
    15263     (flush _test-error-buffered-file)
    15264 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
    15270     # check output
    15271     (check-stream-equal _test-output-stream  ""  "F - test-populate-stream-non-addr-handle-stream: output should be empty")
    15272     (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")
    15273     # check that stop(1) was called
    15274     (check-ints-equal *(edx+4) 2 "F - test-populate-stream-non-addr-handle-stream: exit status")
    15275     # don't restore from ebp
    15276     81 0/subop/add %esp 8/imm32
    15277     # . epilogue
    15278     5d/pop-to-ebp
    15279     c3/return
    15280
    15281 test-populate-stream-deref-address:
    15282     # . prologue
    15283     55/push-ebp
    15284     89/<- %ebp 4/r32/esp
    15285     # setup
    15286     (clear-stream _test-input-stream)
    15287     (clear-stream $_test-input-buffered-file->buffer)
    15288     (clear-stream _test-output-stream)
    15289     (clear-stream $_test-output-buffered-file->buffer)
    15290     #
    15291     (write _test-input-stream "fn foo {\n")
    15292     (write _test-input-stream "  var y/ecx: (addr addr handle stream int) <- copy 0\n")
    15293     (write _test-input-stream "  populate-stream *y, 3\n")
    15294     (write _test-input-stream "}\n")
    15295     # convert
    15296     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
    15297     (flush _test-output-buffered-file)
    15298     # no errors
    15299     # . epilogue
    15300     5d/pop-to-ebp
    15301     c3/return
    15302
    15303 test-convert-with-no-inout:
    15304     # . prologue
    15305     55/push-ebp
    15306     89/<- %ebp 4/r32/esp
    15307     # setup
    15308     (clear-stream _test-input-stream)
    15309     (clear-stream $_test-input-buffered-file->buffer)
    15310     (clear-stream _test-output-stream)
    15311     (clear-stream $_test-output-buffered-file->buffer)
    15312     (clear-stream _test-error-stream)
    15313     (clear-stream $_test-error-buffered-file->buffer)
    15314     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    15315     68/push 0/imm32
    15316     68/push 0/imm32
    15317     89/<- %edx 4/r32/esp
    15318     (tailor-exit-descriptor %edx 0x10)
    15319     #
    15320     (write _test-input-stream "fn foo {\n")
    15321     (write _test-input-stream "  var x/eax: int <- convert\n")
    15322     (write _test-input-stream "}\n")
    15323     # convert
    15324     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    15325     # registers except esp clobbered at this point
    15326     # restore ed
    15327     89/<- %edx 4/r32/esp
    15328     (flush _test-output-buffered-file)
    15329     (flush _test-error-buffered-file)
    15330 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
    15336     # check output
    15337     (check-stream-equal _test-output-stream  ""  "F - test-convert-with-no-inout: output should be empty")
    15338     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'convert' expects an inout"  "F - test-convert-with-no-inout: error message")
    15339     # check that stop(1) was called
    15340     (check-ints-equal *(edx+4) 2 "F - test-convert-with-no-inout: exit status")
    15341     # don't restore from ebp
    15342     81 0/subop/add %esp 8/imm32
    15343     # . epilogue
    15344     5d/pop-to-ebp
    15345     c3/return
    15346
    15347 test-convert-with-multiple-inouts:
    15348     # . prologue
    15349     55/push-ebp
    15350     89/<- %ebp 4/r32/esp
    15351     # setup
    15352     (clear-stream _test-input-stream)
    15353     (clear-stream $_test-input-buffered-file->buffer)
    15354     (clear-stream _test-output-stream)
    15355     (clear-stream $_test-output-buffered-file->buffer)
    15356     (clear-stream _test-error-stream)
    15357     (clear-stream $_test-error-buffered-file->buffer)
    15358     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    15359     68/push 0/imm32
    15360     68/push 0/imm32
    15361     89/<- %edx 4/r32/esp
    15362     (tailor-exit-descriptor %edx 0x10)
    15363     #
    15364     (write _test-input-stream "fn foo {\n")
    15365     (write _test-input-stream "  var x/eax: int <- convert 0, 0\n")
    15366     (write _test-input-stream "}\n")
    15367     # convert
    15368     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    15369     # registers except esp clobbered at this point
    15370     # restore ed
    15371     89/<- %edx 4/r32/esp
    15372     (flush _test-output-buffered-file)
    15373     (flush _test-error-buffered-file)
    15374 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
    15380     # check output
    15381     (check-stream-equal _test-output-stream  ""  "F - test-convert-with-multiple-inouts: output should be empty")
    15382     (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")
    15383     # check that stop(1) was called
    15384     (check-ints-equal *(edx+4) 2 "F - test-convert-with-multiple-inouts: exit status")
    15385     # don't restore from ebp
    15386     81 0/subop/add %esp 8/imm32
    15387     # . epilogue
    15388     5d/pop-to-ebp
    15389     c3/return
    15390
    15391 test-convert-with-no-output:
    15392     # . prologue
    15393     55/push-ebp
    15394     89/<- %ebp 4/r32/esp
    15395     # setup
    15396     (clear-stream _test-input-stream)
    15397     (clear-stream $_test-input-buffered-file->buffer)
    15398     (clear-stream _test-output-stream)
    15399     (clear-stream $_test-output-buffered-file->buffer)
    15400     (clear-stream _test-error-stream)
    15401     (clear-stream $_test-error-buffered-file->buffer)
    15402     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    15403     68/push 0/imm32
    15404     68/push 0/imm32
    15405     89/<- %edx 4/r32/esp
    15406     (tailor-exit-descriptor %edx 0x10)
    15407     #
    15408     (write _test-input-stream "fn foo {\n")
    15409     (write _test-input-stream "  convert 0\n")
    15410     (write _test-input-stream "}\n")
    15411     # convert
    15412     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    15413     # registers except esp clobbered at this point
    15414     # restore ed
    15415     89/<- %edx 4/r32/esp
    15416     (flush _test-output-buffered-file)
    15417     (flush _test-error-buffered-file)
    15418 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
    15424     # check output
    15425     (check-stream-equal _test-output-stream  ""  "F - test-convert-with-no-output: output should be empty")
    15426     (check-next-stream-line-equal _test-error-stream  "fn foo: stmt 'convert' expects an output"  "F - test-convert-with-no-output: error message")
    15427     # check that stop(1) was called
    15428     (check-ints-equal *(edx+4) 2 "F - test-convert-with-no-output: exit status")
    15429     # don't restore from ebp
    15430     81 0/subop/add %esp 8/imm32
    15431     # . epilogue
    15432     5d/pop-to-ebp
    15433     c3/return
    15434
    15435 test-convert-with-multiple-outputs:
    15436     # . prologue
    15437     55/push-ebp
    15438     89/<- %ebp 4/r32/esp
    15439     # setup
    15440     (clear-stream _test-input-stream)
    15441     (clear-stream $_test-input-buffered-file->buffer)
    15442     (clear-stream _test-output-stream)
    15443     (clear-stream $_test-output-buffered-file->buffer)
    15444     (clear-stream _test-error-stream)
    15445     (clear-stream $_test-error-buffered-file->buffer)
    15446     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    15447     68/push 0/imm32
    15448     68/push 0/imm32
    15449     89/<- %edx 4/r32/esp
    15450     (tailor-exit-descriptor %edx 0x10)
    15451     #
    15452     (write _test-input-stream "fn foo {\n")
    15453     (write _test-input-stream "  var x/eax: int <- copy 0\n")
    15454     (write _test-input-stream "  var y/ecx: int <- copy 0\n")
    15455     (write _test-input-stream "  x, y <- convert 0\n")
    15456     (write _test-input-stream "}\n")
    15457     # convert
    15458     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    15459     # registers except esp clobbered at this point
    15460     # restore ed
    15461     89/<- %edx 4/r32/esp
    15462     (flush _test-output-buffered-file)
    15463     (flush _test-error-buffered-file)
    15464 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
    15470     # check output
    15471     (check-stream-equal _test-output-stream  ""  "F - test-convert-with-multiple-outputs: output should be empty")
    15472     (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")
    15473     # check that stop(1) was called
    15474     (check-ints-equal *(edx+4) 2 "F - test-convert-with-multiple-outputs: exit status")
    15475     # don't restore from ebp
    15476     81 0/subop/add %esp 8/imm32
    15477     # . epilogue
    15478     5d/pop-to-ebp
    15479     c3/return
    15480
    15481 test-convert-deref-address:
    15482     # . prologue
    15483     55/push-ebp
    15484     89/<- %ebp 4/r32/esp
    15485     # setup
    15486     (clear-stream _test-input-stream)
    15487     (clear-stream $_test-input-buffered-file->buffer)
    15488     (clear-stream _test-output-stream)
    15489     (clear-stream $_test-output-buffered-file->buffer)
    15490     #
    15491     (write _test-input-stream "fn foo {\n")
    15492     (write _test-input-stream "  var x/eax: (addr int) <- copy 0\n")
    15493     (write _test-input-stream "  var y/xmm4: float <- convert *x\n")
    15494     (write _test-input-stream "}\n")
    15495     # convert
    15496     (convert-mu _test-input-buffered-file _test-output-buffered-file Stderr 0)
    15497     (flush _test-output-buffered-file)
    15498     # no errors
    15499     # . epilogue
    15500     5d/pop-to-ebp
    15501     c3/return
    15502
    15503 test-convert-to-non-register:
    15504     # . prologue
    15505     55/push-ebp
    15506     89/<- %ebp 4/r32/esp
    15507     # setup
    15508     (clear-stream _test-input-stream)
    15509     (clear-stream $_test-input-buffered-file->buffer)
    15510     (clear-stream _test-output-stream)
    15511     (clear-stream $_test-output-buffered-file->buffer)
    15512     (clear-stream _test-error-stream)
    15513     (clear-stream $_test-error-buffered-file->buffer)
    15514     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    15515     68/push 0/imm32
    15516     68/push 0/imm32
    15517     89/<- %edx 4/r32/esp
    15518     (tailor-exit-descriptor %edx 0x10)
    15519     #
    15520     (write _test-input-stream "fn foo {\n")
    15521     (write _test-input-stream "  var x: float\n")
    15522     (write _test-input-stream "  var y: int\n")
    15523     (write _test-input-stream "  x <- convert y\n")
    15524     (write _test-input-stream "}\n")
    15525     # convert
    15526     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    15527     # registers except esp clobbered at this point
    15528     # restore ed
    15529     89/<- %edx 4/r32/esp
    15530     (flush _test-output-buffered-file)
    15531     (flush _test-error-buffered-file)
    15532 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
    15538     # check output
    15539     (check-stream-equal _test-output-stream  ""  "F - test-convert-to-non-register: output should be empty")
    15540     (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")
    15541     # check that stop(1) was called
    15542     (check-ints-equal *(edx+4) 2 "F - test-convert-to-non-register: exit status")
    15543     # don't restore from ebp
    15544     81 0/subop/add %esp 8/imm32
    15545     # . epilogue
    15546     5d/pop-to-ebp
    15547     c3/return
    15548
    15549 test-convert-invalid-inout-type:
    15550     # . prologue
    15551     55/push-ebp
    15552     89/<- %ebp 4/r32/esp
    15553     # setup
    15554     (clear-stream _test-input-stream)
    15555     (clear-stream $_test-input-buffered-file->buffer)
    15556     (clear-stream _test-output-stream)
    15557     (clear-stream $_test-output-buffered-file->buffer)
    15558     (clear-stream _test-error-stream)
    15559     (clear-stream $_test-error-buffered-file->buffer)
    15560     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    15561     68/push 0/imm32
    15562     68/push 0/imm32
    15563     89/<- %edx 4/r32/esp
    15564     (tailor-exit-descriptor %edx 0x10)
    15565     #
    15566     (write _test-input-stream "fn foo {\n")
    15567     (write _test-input-stream "  var x: boolean\n")
    15568     (write _test-input-stream "  var y/xmm1: float <- convert x\n")
    15569     (write _test-input-stream "}\n")
    15570     # convert
    15571     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    15572     # registers except esp clobbered at this point
    15573     # restore ed
    15574     89/<- %edx 4/r32/esp
    15575     (flush _test-output-buffered-file)
    15576     (flush _test-error-buffered-file)
    15577 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
    15583     # check output
    15584     (check-stream-equal _test-output-stream  ""  "F - test-convert-invalid-inout-type: output should be empty")
    15585     (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")
    15586     # check that stop(1) was called
    15587     (check-ints-equal *(edx+4) 2 "F - test-convert-invalid-inout-type: exit status")
    15588     # don't restore from ebp
    15589     81 0/subop/add %esp 8/imm32
    15590     # . epilogue
    15591     5d/pop-to-ebp
    15592     c3/return
    15593
    15594 test-convert-invalid-output-type:
    15595     # . prologue
    15596     55/push-ebp
    15597     89/<- %ebp 4/r32/esp
    15598     # setup
    15599     (clear-stream _test-input-stream)
    15600     (clear-stream $_test-input-buffered-file->buffer)
    15601     (clear-stream _test-output-stream)
    15602     (clear-stream $_test-output-buffered-file->buffer)
    15603     (clear-stream _test-error-stream)
    15604     (clear-stream $_test-error-buffered-file->buffer)
    15605     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    15606     68/push 0/imm32
    15607     68/push 0/imm32
    15608     89/<- %edx 4/r32/esp
    15609     (tailor-exit-descriptor %edx 0x10)
    15610     #
    15611     (write _test-input-stream "fn foo {\n")
    15612     (write _test-input-stream "  var x: float\n")
    15613     (write _test-input-stream "  var y/eax: boolean <- convert x\n")
    15614     (write _test-input-stream "}\n")
    15615     # convert
    15616     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    15617     # registers except esp clobbered at this point
    15618     # restore ed
    15619     89/<- %edx 4/r32/esp
    15620     (flush _test-output-buffered-file)
    15621     (flush _test-error-buffered-file)
    15622 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
    15628     # check output
    15629     (check-stream-equal _test-output-stream  ""  "F - test-convert-invalid-output-type: output should be empty")
    15630     (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")
    15631     # check that stop(1) was called
    15632     (check-ints-equal *(edx+4) 2 "F - test-convert-invalid-output-type: exit status")
    15633     # don't restore from ebp
    15634     81 0/subop/add %esp 8/imm32
    15635     # . epilogue
    15636     5d/pop-to-ebp
    15637     c3/return
    15638
    15639 test-convert-int-to-int:
    15640     # . prologue
    15641     55/push-ebp
    15642     89/<- %ebp 4/r32/esp
    15643     # setup
    15644     (clear-stream _test-input-stream)
    15645     (clear-stream $_test-input-buffered-file->buffer)
    15646     (clear-stream _test-output-stream)
    15647     (clear-stream $_test-output-buffered-file->buffer)
    15648     (clear-stream _test-error-stream)
    15649     (clear-stream $_test-error-buffered-file->buffer)
    15650     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    15651     68/push 0/imm32
    15652     68/push 0/imm32
    15653     89/<- %edx 4/r32/esp
    15654     (tailor-exit-descriptor %edx 0x10)
    15655     #
    15656     (write _test-input-stream "fn foo {\n")
    15657     (write _test-input-stream "  var x: int\n")
    15658     (write _test-input-stream "  var y/eax: int <- convert x\n")
    15659     (write _test-input-stream "}\n")
    15660     # convert
    15661     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    15662     # registers except esp clobbered at this point
    15663     # restore ed
    15664     89/<- %edx 4/r32/esp
    15665     (flush _test-output-buffered-file)
    15666     (flush _test-error-buffered-file)
    15667 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
    15673     # check output
    15674     (check-stream-equal _test-output-stream  ""  "F - test-convert-int-to-int: output should be empty")
    15675     (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")
    15676     # check that stop(1) was called
    15677     (check-ints-equal *(edx+4) 2 "F - test-convert-int-to-int: exit status")
    15678     # don't restore from ebp
    15679     81 0/subop/add %esp 8/imm32
    15680     # . epilogue
    15681     5d/pop-to-ebp
    15682     c3/return
    15683
    15684 test-convert-float-to-float:
    15685     # . prologue
    15686     55/push-ebp
    15687     89/<- %ebp 4/r32/esp
    15688     # setup
    15689     (clear-stream _test-input-stream)
    15690     (clear-stream $_test-input-buffered-file->buffer)
    15691     (clear-stream _test-output-stream)
    15692     (clear-stream $_test-output-buffered-file->buffer)
    15693     (clear-stream _test-error-stream)
    15694     (clear-stream $_test-error-buffered-file->buffer)
    15695     # var ed/edx: exit-descriptor = tailor-exit-descriptor(16)
    15696     68/push 0/imm32
    15697     68/push 0/imm32
    15698     89/<- %edx 4/r32/esp
    15699     (tailor-exit-descriptor %edx 0x10)
    15700     #
    15701     (write _test-input-stream "fn foo {\n")
    15702     (write _test-input-stream "  var x: float\n")
    15703     (write _test-input-stream "  var y/xmm6: float <- convert x\n")
    15704     (write _test-input-stream "}\n")
    15705     # convert
    15706     (convert-mu _test-input-buffered-file _test-output-buffered-file _test-error-buffered-file %edx)
    15707     # registers except esp clobbered at this point
    15708     # restore ed
    15709     89/<- %edx 4/r32/esp
    15710     (flush _test-output-buffered-file)
    15711     (flush _test-error-buffered-file)
    15712 +--  6 lines: #?     # dump _test-error-stream -----------------------------------------------------------------------------------------------------------------------------
    15718     # check output
    15719     (check-stream-equal _test-output-stream  ""  "F - test-convert-float-to-float: output should be empty")
    15720     (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")
    15721     # check that stop(1) was called
    15722     (check-ints-equal *(edx+4) 2 "F - test-convert-float-to-float: exit status")
    15723     # don't restore from ebp
    15724     81 0/subop/add %esp 8/imm32
    15725     # . epilogue
    15726     5d/pop-to-ebp
    15727     c3/return
    15728
    15729 #######################################################
    15730 # Parsing
    15731 #######################################################
    15732
    15733 == data
    15734
    15735 # Global state added to each var record when parsing a function
    15736 Next-block-index:  # (addr int)
    15737     1/imm32
    15738
    15739 Curr-block-depth:  # (addr int)
    15740     1/imm32
    15741
    15742 == code
    15743
    15744 parse-mu:  # in: (addr buffered-file), err: (addr buffered-file), ed: (addr exit-descriptor)
    15745     # pseudocode
    15746     #   var curr-function: (addr handle function) = Program->functions
    15747     #   var curr-signature: (addr handle function) = Program->signatures
    15748     #   var curr-type: (addr handle typeinfo) = Program->types
    15749     #   var line: (stream byte 512)
    15750     #   var word-slice: slice
    15751     #   while true                                  # line loop
    15752     #     clear-stream(line)
    15753     #     read-line-buffered(in, line)
    15754     #     if (line->write == 0) break               # end of file
    15755     #     word-slice = next-mu-token(line)
    15756     #     if slice-empty?(word-slice)               # end of line
    15757     #       continue
    15758     #     else if slice-starts-with?(word-slice, "#")  # comment
    15759     #       continue                                # end of line
    15760     #     else if slice-equal?(word-slice, "fn")
    15761     #       var new-function: (handle function) = allocate(function)
    15762     #       var vars: (stack live-var 256)
    15763     #       populate-mu-function-header(line, new-function, vars)
    15764     #       populate-mu-function-body(in, new-function, vars)
    15765     #       assert(vars->top == 0)
    15766     #       *curr-function = new-function
    15767     #       curr-function = &new-function->next
    15768     #     else if slice-equal?(word-slice, "sig")
    15769     #       var new-function: (handle function) = allocate(function)
    15770     #       populate-mu-function-signature(line, new-function)
    15771     #       *curr-signature = new-function
    15772     #       curr-signature = &new-function->next
    15773     #     else if slice-equal?(word-slice, "type")
    15774     #       word-slice = next-mu-token(line)
    15775     #       type-id = pos-or-insert-slice(Type-id, word-slice)
    15776     #       var new-type: (handle typeinfo) = find-or-create-typeinfo(type-id)
    15777     #       assert(next-word(line) == "{")
    15778     #       populate-mu-type(in, new-type)
    15779     #     else
    15780     #       abort()
    15781     #
    15782     # . prologue
    15783     55/push-ebp
    15784     89/<- %ebp 4/r32/esp
    15785     # var curr-signature: (addr handle function) at *(ebp-4)
    15786     68/push _Program-signatures/imm32
    15787     # . save registers
    15788     50/push-eax
    15789     51/push-ecx
    15790     52/push-edx
    15791     53/push-ebx
    15792     56/push-esi
    15793     57/push-edi
    15794     # var line/ecx: (stream byte 512)
    15795     81 5/subop/subtract %esp 0x200/imm32
    15796     68/push 0x200/imm32/size
    15797     68/push 0/imm32/read
    15798     68/push 0/imm32/write
    15799     89/<- %ecx 4/r32/esp
    15800     # var word-slice/edx: slice
    15801     68/push 0/imm32/end
    15802     68/push 0/imm32/start
    15803     89/<- %edx 4/r32/esp
    15804     # var curr-function/edi: (addr handle function)
    15805     bf/copy-to-edi _Program-functions/imm32
    15806     # var vars/ebx: (stack live-var 256)
    15807     81 5/subop/subtract %esp 0xc00/imm32
    15808     68/push 0xc00/imm32/size
    15809     68/push 0/imm32/top
    15810     89/<- %ebx 4/r32/esp
    15811     {
    15812 $parse-mu:line-loop:
    15813       (clear-stream %ecx)
    15814       (read-line-buffered *(ebp+8) %ecx)
    15815       # if (line->write == 0) break
    15816       81 7/subop/compare *ecx 0/imm32
    15817       0f 84/jump-if-= break/disp32
    15818 +--  6 lines: #?       # dump line -----------------------------------------------------------------------------------------------------------------------------------------
    15824       (next-mu-token %ecx %edx)
    15825       # if slice-empty?(word-slice) continue
    15826       (slice-empty? %edx)  # => eax
    15827       3d/compare-eax-and 0/imm32/false
    15828       0f 85/jump-if-!= loop/disp32
    15829       # if (*word-slice->start == "#") continue
    15830       # . eax = *word-slice->start
    15831       8b/-> *edx 0/r32/eax
    15832       8a/copy-byte *eax 0/r32/AL
    15833       25/and-eax-with 0xff/imm32
    15834       # . if (eax == '#') continue
    15835       3d/compare-eax-and 0x23/imm32/hash
    15836       0f 84/jump-if-= loop/disp32
    15837       # if (slice-equal?(word-slice, "fn")) parse a function
    15838       {
    15839 $parse-mu:fn:
    15840         (slice-equal? %edx "fn")  # => eax
    15841         3d/compare-eax-and 0/imm32/false
    15842         0f 84/jump-if-= break/disp32
    15843         # var new-function/esi: (handle function)
    15844         68/push 0/imm32
    15845         68/push 0/imm32
    15846         89/<- %esi 4/r32/esp
    15847         # populate-mu-function(line, in, vars, new-function)
    15848         (allocate Heap *Function-size %esi)
    15849         # var new-function-addr/eax: (addr function)
    15850         (lookup *esi *(esi+4))  # => eax
    15851         # initialize vars
    15852         (clear-stack %ebx)
    15853         #
    15854         (populate-mu-function-header %ecx %eax %ebx *(ebp+0xc) *(ebp+0x10))
    15855         (populate-mu-function-body *(ebp+8) %eax %ebx *(ebp+0xc) *(ebp+0x10))
    15856         # *curr-function = new-function
    15857         8b/-> *esi 0/r32/eax
    15858         89/<- *edi 0/r32/eax
    15859         8b/-> *(esi+4) 0/r32/eax
    15860         89/<- *(edi+4) 0/r32/eax
    15861         # curr-function = &new-function->next
    15862         # . var tmp/eax: (addr function) = lookup(new-function)
    15863         (lookup *esi *(esi+4))  # => eax
    15864         # . curr-function = &tmp->next
    15865         8d/copy-address *(eax+0x20) 7/r32/edi  # Function-next
    15866         # reclaim new-function
    15867         81 0/subop/add %esp 8/imm32
    15868         #
    15869         e9/jump $parse-mu:line-loop/disp32
    15870       }
    15871       # if (slice-equal?(word-slice, "sig")) parse a function signature
    15872       # Function signatures are for providing types to SubX functions.
    15873       {
    15874 $parse-mu:sig:
    15875         (slice-equal? %edx "sig")  # => eax
    15876         3d/compare-eax-and 0/imm32/false
    15877         0f 84/jump-if-= break/disp32
    15878         # edi = curr-function
    15879         57/push-edi
    15880         8b/-> *(ebp-4) 7/r32/edi
    15881         # var new-function/esi: (handle function)
    15882         68/push 0/imm32
    15883         68/push 0/imm32
    15884         89/<- %esi 4/r32/esp
    15885         # populate-mu-function(line, in, vars, new-function)
    15886         (allocate Heap *Function-size %esi)
    15887         # var new-function-addr/eax: (addr function)
    15888         (lookup *esi *(esi+4))  # => eax
    15889         #
    15890         (populate-mu-function-signature %ecx %eax *(ebp+0xc) *(ebp+0x10))
    15891         # *curr-signature = new-function
    15892         8b/-> *esi 0/r32/eax
    15893         89/<- *edi 0/r32/eax
    15894         8b/-> *(esi+4) 0/r32/eax
    15895         89/<- *(edi+4) 0/r32/eax
    15896         # curr-signature = &new-function->next
    15897         # . var tmp/eax: (addr function) = lookup(new-function)
    15898         (lookup *esi *(esi+4))  # => eax
    15899         # . curr-function = &tmp->next
    15900         8d/copy-address *(eax+0x20) 7/r32/edi  # Function-next
    15901         # reclaim new-function
    15902         81 0/subop/add %esp 8/imm32
    15903         # save curr-function
    15904         89/<- *(ebp-4) 7/r32/edi
    15905         # restore edi
    15906         5f/pop-to-edi
    15907         #
    15908         e9/jump $parse-mu:line-loop/disp32
    15909       }
    15910       # if (slice-equal?(word-slice, "type")) parse a type (struct/record) definition
    15911       {
    15912 $parse-mu:type:
    15913         (slice-equal? %edx "type")  # => eax
    15914         3d/compare-eax-and 0/imm32
    15915         0f 84/jump-if-= break/disp32
    15916         (next-mu-token %ecx %edx)
    15917         # var type-id/eax: int
    15918         (pos-or-insert-slice Type-id %edx)  # => eax
    15919         # spill
    15920         51/push-ecx
    15921         # var new-type/ecx: (handle typeinfo)
    15922         68/push 0/imm32
    15923         68/push 0/imm32
    15924         89/<- %ecx 4/r32/esp
    15925         (find-or-create-typeinfo %eax %ecx)
    15926         #
    15927         (lookup *ecx *(ecx+4))  # => eax
    15928         # TODO: ensure that 'line' has nothing else but '{'
    15929 #? (dump-typeinfos "=== aaa\n")
    15930         (populate-mu-type *(ebp+8) %eax *(ebp+0xc) *(ebp+0x10))  # => eax
    15931 #? (dump-typeinfos "=== zzz\n")
    15932         # reclaim new-type
    15933         81 0/subop/add %esp 8/imm32
    15934         # restore
    15935         59/pop-to-ecx
    15936         e9/jump $parse-mu:line-loop/disp32
    15937       }
    15938       # otherwise abort
    15939       e9/jump $parse-mu:error1/disp32
    15940     } # end line loop
    15941 $parse-mu:end:
    15942     # . reclaim locals
    15943     81 0/subop/add %esp 0x20c/imm32  # line
    15944     81 0/subop/add %esp 0xc08/imm32  # vars
    15945     81 0/subop/add %esp 8/imm32
    15946     # . restore registers
    15947     5f/pop-to-edi
    15948     5e/pop-to-esi
    15949     5b/pop-to-ebx
    15950     5a/pop-to-edx
    15951     59/pop-to-ecx
    15952     58/pop-to-eax
    15953     # . reclaim local
    15954     81 0/subop/add %esp 4/imm32
    15955     # . epilogue
    15956     89/<- %esp 5/r32/ebp
    15957     5d/pop-to-ebp
    15958     c3/return
    15959
    15960 $parse-mu:error1:
    15961     # error("unexpected top-level command: " word-slice "\n")
    15962     (write-buffered *(ebp+0xc) "unexpected top-level command: ")
    15963     (write-slice-buffered *(ebp+0xc) %edx)
    15964     (write-buffered *(ebp+0xc) "\n")
    15965     (flush *(ebp+0xc))
    15966     (stop *(ebp+0x10) 1)
    15967     # never gets here
    15968
    15969 $parse-mu:error2:
    15970     # error(vars->top " vars not reclaimed after fn '" new-function->name "'\n")
    15971     (write-int32-hex-buffered *(ebp+0xc) *ebx)
    15972     (write-buffered *(ebp+0xc) " vars not reclaimed after fn '")
    15973     (write-slice-buffered *(ebp+0xc) *eax)  # Function-name
    15974     (write-buffered *(ebp+0xc) "'\n")
    15975     (flush *(ebp+0xc))
    15976     (stop *(ebp+0x10) 1)
    15977     # never gets here
    15978
    15979 # scenarios considered:
    15980 # ✗ fn foo  # no block
    15981 # ✓ fn foo {
    15982 # ✗ fn foo { {
    15983 # ✗ fn foo { }
    15984 # ✗ fn foo { } {
    15985 # ✗ fn foo x {
    15986 # ✗ fn foo x: {
    15987 # ✓ fn foo x: int {
    15988 # ✓ fn foo x: int {
    15989 # ✓ fn foo x: int -> _/eax: int {
    15990 # TODO:
    15991 #   disallow outputs of type `(... addr ...)`
    15992 #   disallow inputs of type `(... addr ... addr ...)`
    15993 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)
    15994     # pseudocode:
    15995     #   var word-slice: slice
    15996     #   next-mu-token(first-line, word-slice)
    15997     #   if slice-empty?(word-slice) abort
    15998     #   assert(word-slice not in '{' '}' '->')
    15999     #   out->name = slice-to-string(word-slice)
    16000     #   ## inouts
    16001     #   while true
    16002     #     word-slice = next-mu-token(first-line)
    16003     #     if slice-empty?(word-slice) abort
    16004     #     if (word-slice == '{') goto done
    16005     #     if (word-slice == '->') break
    16006     #     assert(word-slice != '}')
    16007     #     var v: (handle var) = parse-var-with-type(word-slice, first-line)
    16008     #     assert(v->register == null)
    16009     #     # v->block-depth is implicitly 0
    16010     #     out->inouts = append(v, out->inouts)
    16011     #     push(vars, {v, false})
    16012     #   ## outputs
    16013     #   while true
    16014     #     word-slice = next-mu-token(first-line)
    16015     #     if slice-empty?(word-slice) abort
    16016     #     if (word-slice == '{') break
    16017     #     assert(word-slice not in '}' '->')
    16018     #     var v: (handle var) = parse-var-with-type(word-slice, first-line)
    16019     #     assert(v->register != null)
    16020     #     assert(v->name == "_")
    16021     #     out->outputs = append(v, out->outputs)
    16022     #   done:
    16023     #
    16024     # . prologue
    16025     55/push-ebp
    16026     89/<- %ebp 4/r32/esp
    16027     # . save registers
    16028     50/push-eax
    16029     51/push-ecx
    16030     52/push-edx
    16031     53/push-ebx
    16032     57/push-edi
    16033     # edi = out
    16034     8b/-> *(ebp+0xc) 7/r32/edi
    16035     # var word-slice/ecx: slice
    16036     68/push 0/imm32/end
    16037     68/push 0/imm32/start
    16038     89/<- %ecx 4/r32/esp
    16039     # var v/ebx: (handle var)
    16040     68/push 0/imm32
    16041     68/push 0/imm32
    16042     89/<- %ebx 4/r32/esp
    16043     # read function name
    16044     (next-mu-token *(ebp+8) %ecx)
    16045     # error checking
    16046     # if slice-empty?(word-slice) abort
    16047     (slice-empty? %ecx)  # => eax
    16048     3d/compare-eax-and 0/imm32/false
    16049     0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
    16050     # if (word-slice == '{') abort
    16051     (slice-equal? %ecx "{")   # => eax
    16052     3d/compare-eax-and 0/imm32/false
    16053     0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
    16054     # if (word-slice == '->') abort
    16055     (slice-equal? %ecx "->")   # => eax
    16056     3d/compare-eax-and 0/imm32/false
    16057     0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
    16058     # if (word-slice == '}') abort
    16059     (slice-equal? %ecx "}")   # => eax
    16060     3d/compare-eax-and 0/imm32/false
    16061     0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
    16062     # if word-slice already defined, abort
    16063     (function-exists? %ecx)  # => eax
    16064     3d/compare-eax-and 0/imm32/false
    16065     0f 85/jump-if-!= $populate-mu-function-header:error-duplicate/disp32
    16066     #
    16067     (slice-starts-with? %ecx "break")  # => eax
    16068     3d/compare-eax-and 0/imm32/false
    16069     0f 85/jump-if-!= $populate-mu-function-header:error-break/disp32
    16070     (slice-starts-with? %ecx "loop")  # => eax
    16071     3d/compare-eax-and 0/imm32/false
    16072     0f 85/jump-if-!= $populate-mu-function-header:error-loop/disp32
    16073     (slice-equal? %ecx "lookup")  # => eax
    16074     3d/compare-eax-and 0/imm32/false
    16075     0f 85/jump-if-!= $populate-mu-function-header:error-lookup/disp32
    16076     # save function name
    16077     (slice-to-string Heap %ecx %edi)  # Function-name
    16078     # save function inouts
    16079     {
    16080 $populate-mu-function-header:check-for-inout:
    16081       (next-mu-token *(ebp+8) %ecx)
    16082       # if slice-empty?(word-slice) abort
    16083       (slice-empty? %ecx)  # => eax
    16084       3d/compare-eax-and 0/imm32/false
    16085       0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
    16086       # if (word-slice == '{') goto done
    16087       (slice-equal? %ecx "{")   # => eax
    16088       3d/compare-eax-and 0/imm32/false
    16089       0f 85/jump-if-!= $populate-mu-function-header:done/disp32
    16090       # if (word-slice == '->') break
    16091       (slice-equal? %ecx "->")   # => eax
    16092       3d/compare-eax-and 0/imm32/false
    16093       0f 85/jump-if-!= break/disp32
    16094       # if (word-slice == '}') abort
    16095       (slice-equal? %ecx "}")   # => eax
    16096       3d/compare-eax-and 0/imm32/false
    16097       0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
    16098       # v = parse-var-with-type(word-slice, first-line)
    16099       (lookup *edi *(edi+4))  # Function-name Function-name => eax
    16100       (parse-var-with-type %ecx *(ebp+8) %ebx %eax *(ebp+0x14) *(ebp+0x18))
    16101       # if (v->register != null) abort
    16102       # . eax: (addr var) = lookup(v)
    16103       (lookup *ebx *(ebx+4))  # => eax
    16104       81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
    16105       0f 85/jump-if-!= $populate-mu-function-header:error2/disp32
    16106       # if function name is not "main"
    16107       #    and v->type contains an 'addr' anywhere except the start, abort
    16108       {
    16109         (lookup *edi *(edi+4))  # Function-name Function-name => eax
    16110         (string-equal? %eax "main")  # => eax
    16111         3d/compare-eax-and 0/imm32/false
    16112         75/jump-if-!= break/disp8
    16113         (lookup *ebx *(ebx+4))  # => eax
    16114         (addr-payload-contains-addr? %eax)  # => eax
    16115         3d/compare-eax-and 0/imm32/false
    16116         0f 85/jump-if-!= $populate-mu-function-header:error-nested-addr-inout/disp32
    16117       }
    16118       # v->block-depth is implicitly 0
    16119       #
    16120       # out->inouts = append(v, out->inouts)
    16121       8d/copy-address *(edi+8) 0/r32/eax  # Function-inouts
    16122       (append-list Heap  *ebx *(ebx+4)  *(edi+8) *(edi+0xc)  %eax)  # Function-inouts, Function-inouts
    16123       # push(vars, {v, false})
    16124       (push *(ebp+0x10) *ebx)
    16125       (push *(ebp+0x10) *(ebx+4))
    16126       (push *(ebp+0x10) 0)  # false
    16127       #
    16128       e9/jump loop/disp32
    16129     }
    16130     # save function outputs
    16131     {
    16132 $populate-mu-function-header:check-for-out:
    16133       (next-mu-token *(ebp+8) %ecx)
    16134       # if slice-empty?(word-slice) abort
    16135       (slice-empty? %ecx)  # => eax
    16136       3d/compare-eax-and 0/imm32/false
    16137       0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
    16138       # if (word-slice == '{') break
    16139       (slice-equal? %ecx "{")   # => eax
    16140       3d/compare-eax-and 0/imm32/false
    16141       0f 85/jump-if-!= break/disp32
    16142       # if (word-slice == '->') abort
    16143       (slice-equal? %ecx "->")   # => eax
    16144       3d/compare-eax-and 0/imm32/false
    16145       0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
    16146       # if (word-slice == '}') abort
    16147       (slice-equal? %ecx "}")   # => eax
    16148       3d/compare-eax-and 0/imm32/false
    16149       0f 85/jump-if-!= $populate-mu-function-header:error1/disp32
    16150       # v = parse-var-with-type(word-slice, first-line)
    16151       (lookup *edi *(edi+4))  # Function-name Function-name => eax
    16152       (parse-var-with-type %ecx *(ebp+8) %ebx %eax *(ebp+0x14) *(ebp+0x18))
    16153       # assert(var->register != null)
    16154       # . eax: (addr var) = lookup(v)
    16155       (lookup *ebx *(ebx+4))  # => eax
    16156       81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
    16157       0f 84/jump-if-= $populate-mu-function-header:error3/disp32
    16158       # if (var->name != "_") abort
    16159       (lookup *eax *(eax+4))  # Var-name Var-name => eax
    16160       (string-equal? %eax "_")  # => eax
    16161       3d/compare-eax-and 0/imm32/false
    16162       0f 84/jump-if-= $populate-mu-function-header:error4/disp32
    16163       # if v->type is an addr, abort
    16164       (lookup *ebx *(ebx+4))  # => eax
    16165       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    16166       (mu-addr-type? %eax)  # => eax
    16167       3d/compare-eax-and 0/imm32/false
    16168       0f 85/jump-if-!= $populate-mu-function-header:error-addr-output/disp32
    16169       # out->outputs = append(v, out->outputs)
    16170       8d/copy-address *(edi+0x10) 0/r32/eax  # Function-outputs
    16171       (append-list Heap  *ebx *(ebx+4)  *(edi+0x10) *(edi+0x14)  %eax)  # Function-outputs, Function-outputs
    16172       #
    16173       e9/jump loop/disp32
    16174     }
    16175 $populate-mu-function-header:done:
    16176     (check-no-tokens-left *(ebp+8))
    16177 $populate-mu-function-header:end:
    16178     # . reclaim locals
    16179     81 0/subop/add %esp 0x10/imm32
    16180     # . restore registers
    16181     5f/pop-to-edi
    16182     5b/pop-to-ebx
    16183     5a/pop-to-edx
    16184     59/pop-to-ecx
    16185     58/pop-to-eax
    16186     # . epilogue
    16187     89/<- %esp 5/r32/ebp
    16188     5d/pop-to-ebp
    16189     c3/return
    16190
    16191 $populate-mu-function-header:error1:
    16192     # error("function header not in form 'fn <name> {'")
    16193     (write-buffered *(ebp+0x14) "function header not in form 'fn <name> [inouts] [-> outputs] {' -- '")
    16194     (flush *(ebp+0x14))
    16195     (rewind-stream *(ebp+8))
    16196     (write-stream-data *(ebp+0x14) *(ebp+8))
    16197     (write-buffered *(ebp+0x14) "'\n")
    16198     (flush *(ebp+0x14))
    16199     (stop *(ebp+0x18) 1)
    16200     # never gets here
    16201
    16202 $populate-mu-function-header:error2:
    16203     # error("fn " fn ": function inout '" var "' cannot be in a register")
    16204     (write-buffered *(ebp+0x14) "fn ")
    16205     50/push-eax
    16206     (lookup *edi *(edi+4))  # Function-name Function-name => eax
    16207     (write-buffered *(ebp+0x14) %eax)
    16208     58/pop-to-eax
    16209     (write-buffered *(ebp+0x14) ": function inout '")
    16210     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    16211     (write-buffered *(ebp+0x14) %eax)
    16212     (write-buffered *(ebp+0x14) "' cannot be in a register")
    16213     (flush *(ebp+0x14))
    16214     (stop *(ebp+0x18) 1)
    16215     # never gets here
    16216
    16217 $populate-mu-function-header:error3:
    16218     # error("fn " fn ": function output '" var "' must be in a register")
    16219     (write-buffered *(ebp+0x14) "fn ")
    16220     50/push-eax
    16221     (lookup *edi *(edi+4))  # Function-name Function-name => eax
    16222     (write-buffered *(ebp+0x14) %eax)
    16223     58/pop-to-eax
    16224     (write-buffered *(ebp+0x14) ": function output '")
    16225     (lookup *ebx *(ebx+4))  # => eax
    16226     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    16227     (write-buffered *(ebp+0x14) %eax)
    16228     (write-buffered *(ebp+0x14) "' must be in a register, in instruction '")
    16229     (rewind-stream *(ebp+8))
    16230     (write-stream-data *(ebp+0x14) *(ebp+8))
    16231     (write-buffered *(ebp+0x14) "'\n")
    16232     (flush *(ebp+0x14))
    16233     (stop *(ebp+0x18) 1)
    16234     # never gets here
    16235
    16236 $populate-mu-function-header:error4:
    16237     # error("fn " fn ": function outputs cannot be named; rename '" var "' in the header to '_'")
    16238     (write-buffered *(ebp+0x14) "fn ")
    16239     50/push-eax
    16240     (lookup *edi *(edi+4))  # Function-name Function-name => eax
    16241     (write-buffered *(ebp+0x14) %eax)
    16242     58/pop-to-eax
    16243     (write-buffered *(ebp+0x14) ": function outputs cannot be named; rename '")
    16244     (lookup *ebx *(ebx+4))  # => eax
    16245     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    16246     (write-buffered *(ebp+0x14) %eax)
    16247     (write-buffered *(ebp+0x14) "' in the header to '_'\n")
    16248     (flush *(ebp+0x14))
    16249     (stop *(ebp+0x18) 1)
    16250     # never gets here
    16251
    16252 $populate-mu-function-header:error-duplicate:
    16253     (write-buffered *(ebp+0x14) "fn ")
    16254     (write-slice-buffered *(ebp+0x14) %ecx)
    16255     (write-buffered *(ebp+0x14) " defined more than once\n")
    16256     (flush *(ebp+0x14))
    16257     (stop *(ebp+0x18) 1)
    16258     # never gets here
    16259
    16260 $populate-mu-function-header:error-break:
    16261     (write-buffered *(ebp+0x14) "Sorry, I've reserved all function names starting with 'break' for now. Please contact mu@akkartik.com.\n")
    16262     (flush *(ebp+0x14))
    16263     (stop *(ebp+0x18) 1)
    16264     # never gets here
    16265
    16266 $populate-mu-function-header:error-loop:
    16267     (write-buffered *(ebp+0x14) "Sorry, I've reserved all function names starting with 'loop' for now. Please contact mu@akkartik.com.\n")
    16268     (flush *(ebp+0x14))
    16269     (stop *(ebp+0x18) 1)
    16270     # never gets here
    16271
    16272 $populate-mu-function-header:error-lookup:
    16273     (write-buffered *(ebp+0x14) "cannot define a function called 'lookup'\n")
    16274     (flush *(ebp+0x14))
    16275     (stop *(ebp+0x18) 1)
    16276     # never gets here
    16277
    16278 $populate-mu-function-header:error-addr-output:
    16279     # error("fn " fn ": output cannot have an addr type; that could allow unsafe addresses to escape the function")
    16280     (write-buffered *(ebp+0x14) "fn ")
    16281     50/push-eax
    16282     (lookup *edi *(edi+4))  # Function-name Function-name => eax
    16283     (write-buffered *(ebp+0x14) %eax)
    16284     58/pop-to-eax
    16285     (write-buffered *(ebp+0x14) ": output cannot have an addr type; that could allow unsafe addresses to escape the function\n")
    16286     (flush *(ebp+0x14))
    16287     (stop *(ebp+0x18) 1)
    16288     # never gets here
    16289
    16290 $populate-mu-function-header:error-nested-addr-inout:
    16291     # 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")
    16292     (write-buffered *(ebp+0x14) "fn ")
    16293     (lookup *edi *(edi+4))  # Function-name Function-name => eax
    16294     (write-buffered *(ebp+0x14) %eax)
    16295     (write-buffered *(ebp+0x14) ": inout '")
    16296     (lookup *ebx *(ebx+4))  # => eax
    16297     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    16298     (write-buffered *(ebp+0x14) %eax)
    16299     (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")
    16300     (flush *(ebp+0x14))
    16301     (stop *(ebp+0x18) 1)
    16302     # never gets here
    16303
    16304 # scenarios considered:
    16305 # ✓ fn foo
    16306 # ✗ fn foo {
    16307 # ✓ fn foo x
    16308 # ✓ fn foo x: int
    16309 # ✓ fn foo x: int -> _/eax: int
    16310 # TODO:
    16311 #   disallow outputs of type `(... addr ...)`
    16312 #   disallow inputs of type `(... addr ... addr ...)`
    16313 populate-mu-function-signature:  # first-line: (addr stream byte), out: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    16314     # pseudocode:
    16315     #   var word-slice: slice
    16316     #   next-mu-token(first-line, word-slice)
    16317     #   assert(word-slice not in '{' '}' '->')
    16318     #   out->name = slice-to-string(word-slice)
    16319     #   ## inouts
    16320     #   while true
    16321     #     word-slice = next-mu-token(first-line)
    16322     #     if slice-empty?(word-slice) break
    16323     #     if (word-slice == '->') break
    16324     #     assert(word-slice not in '{' '}')
    16325     #     var v: (handle var) = parse-var-with-type(word-slice, first-line)
    16326     #     assert(v->register == null)
    16327     #     # v->block-depth is implicitly 0
    16328     #     out->inouts = append(v, out->inouts)
    16329     #   ## outputs
    16330     #   while true
    16331     #     word-slice = next-mu-token(first-line)
    16332     #     if slice-empty?(word-slice) break
    16333     #     assert(word-slice not in '{' '}' '->')
    16334     #     var v: (handle var) = parse-var-with-type(word-slice, first-line)
    16335     #     assert(v->register != null)
    16336     #     out->outputs = append(v, out->outputs)
    16337     #
    16338     # . prologue
    16339     55/push-ebp
    16340     89/<- %ebp 4/r32/esp
    16341     # . save registers
    16342     50/push-eax
    16343     51/push-ecx
    16344     52/push-edx
    16345     53/push-ebx
    16346     57/push-edi
    16347     # edi = out
    16348     8b/-> *(ebp+0xc) 7/r32/edi
    16349     # var word-slice/ecx: slice
    16350     68/push 0/imm32/end
    16351     68/push 0/imm32/start
    16352     89/<- %ecx 4/r32/esp
    16353     # var v/ebx: (handle var)
    16354     68/push 0/imm32
    16355     68/push 0/imm32
    16356     89/<- %ebx 4/r32/esp
    16357     # read function name
    16358     (next-mu-token *(ebp+8) %ecx)
    16359     # error checking
    16360     # if (word-slice == '{') abort
    16361     (slice-equal? %ecx "{")   # => eax
    16362     3d/compare-eax-and 0/imm32/false
    16363     0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
    16364     # if (word-slice == '->') abort
    16365     (slice-equal? %ecx "->")   # => eax
    16366     3d/compare-eax-and 0/imm32/false
    16367     0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
    16368     # if (word-slice == '}') abort
    16369     (slice-equal? %ecx "}")   # => eax
    16370     3d/compare-eax-and 0/imm32/false
    16371     0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
    16372     # if word-slice already defined, abort
    16373     (function-exists? %ecx)  # => eax
    16374     3d/compare-eax-and 0/imm32/false
    16375     0f 85/jump-if-!= $populate-mu-function-signature:error-duplicate/disp32
    16376     #
    16377     (slice-starts-with? %ecx "break")  # => eax
    16378     3d/compare-eax-and 0/imm32/false
    16379     0f 85/jump-if-!= $populate-mu-function-signature:error-break/disp32
    16380     (slice-starts-with? %ecx "loop")  # => eax
    16381     3d/compare-eax-and 0/imm32/false
    16382     0f 85/jump-if-!= $populate-mu-function-signature:error-loop/disp32
    16383     # save function name
    16384     (slice-to-string Heap %ecx %edi)  # Function-name
    16385     # save function inouts
    16386     {
    16387 $populate-mu-function-signature:check-for-inout:
    16388       (next-mu-token *(ebp+8) %ecx)
    16389       (slice-empty? %ecx)  # => eax
    16390       3d/compare-eax-and 0/imm32/false
    16391       0f 85/jump-if-!= break/disp32
    16392       # if (word-slice == '->') break
    16393       (slice-equal? %ecx "->")   # => eax
    16394       3d/compare-eax-and 0/imm32/false
    16395       0f 85/jump-if-!= break/disp32
    16396       # if (word-slice == '{') abort
    16397       (slice-equal? %ecx "{")   # => eax
    16398       3d/compare-eax-and 0/imm32/false
    16399       0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
    16400       # if (word-slice == '}') abort
    16401       (slice-equal? %ecx "}")   # => eax
    16402       3d/compare-eax-and 0/imm32/false
    16403       0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
    16404       # v = parse-var-with-type(word-slice, first-line)
    16405       (lookup *edi *(edi+4))  # Function-name Function-name => eax
    16406       (parse-var-with-type %ecx *(ebp+8) %ebx %eax *(ebp+0x10) *(ebp+0x14))
    16407       # if (v->register != null) abort
    16408       # . eax: (addr var) = lookup(v)
    16409       (lookup *ebx *(ebx+4))  # => eax
    16410       81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
    16411       0f 85/jump-if-!= $populate-mu-function-signature:error2/disp32
    16412       # if function name is not "main"
    16413       #    and v->type contains an 'addr' anywhere except the start, abort
    16414       {
    16415         (lookup *edi *(edi+4))  # Function-name Function-name => eax
    16416         (string-equal? %eax "main")  # => eax
    16417         3d/compare-eax-and 0/imm32/false
    16418         75/jump-if-!= break/disp8
    16419         (lookup *ebx *(ebx+4))  # => eax
    16420         (addr-payload-contains-addr? %eax)  # => eax
    16421         3d/compare-eax-and 0/imm32/false
    16422         0f 85/jump-if-!= $populate-mu-function-signature:error-nested-addr-inout/disp32
    16423       }
    16424       # assert(v->register == null)
    16425       # . eax: (addr var) = lookup(v)
    16426       (lookup *ebx *(ebx+4))  # => eax
    16427       81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
    16428       0f 85/jump-if-!= $populate-mu-function-signature:error2/disp32
    16429       # v->block-depth is implicitly 0
    16430       #
    16431       # out->inouts = append(v, out->inouts)
    16432       8d/copy-address *(edi+8) 0/r32/eax  # Function-inouts
    16433       (append-list Heap  *ebx *(ebx+4)  *(edi+8) *(edi+0xc)  %eax)  # Function-inouts, Function-inouts
    16434       #
    16435       e9/jump loop/disp32
    16436     }
    16437     # save function outputs
    16438     {
    16439 $populate-mu-function-signature:check-for-out:
    16440       (next-mu-token *(ebp+8) %ecx)
    16441       (slice-empty? %ecx)  # => eax
    16442       3d/compare-eax-and 0/imm32/false
    16443       0f 85/jump-if-!= break/disp32
    16444       # if (word-slice == '{') abort
    16445       (slice-equal? %ecx "{")   # => eax
    16446       3d/compare-eax-and 0/imm32/false
    16447       0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
    16448       # if (word-slice == '->') abort
    16449       (slice-equal? %ecx "->")   # => eax
    16450       3d/compare-eax-and 0/imm32/false
    16451       0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
    16452       # if (word-slice == '}') abort
    16453       (slice-equal? %ecx "}")   # => eax
    16454       3d/compare-eax-and 0/imm32/false
    16455       0f 85/jump-if-!= $populate-mu-function-signature:error1/disp32
    16456       # v = parse-var-with-type(word-slice, first-line)
    16457       (lookup *edi *(edi+4))  # Function-name Function-name => eax
    16458       (parse-var-with-type %ecx *(ebp+8) %ebx %eax *(ebp+0x10) *(ebp+0x14))
    16459       # assert(var->register != null)
    16460       # . eax: (addr var) = lookup(v)
    16461       (lookup *ebx *(ebx+4))  # => eax
    16462       81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
    16463       0f 84/jump-if-= $populate-mu-function-signature:error3/disp32
    16464       # if (var->name != "_") abort
    16465       (lookup *eax *(eax+4))  # Var-name Var-name => eax
    16466       (string-equal? %eax "_")  # => eax
    16467       3d/compare-eax-and 0/imm32/false
    16468       0f 84/jump-if-= $populate-mu-function-signature:error4/disp32
    16469       # if function name is not "lookup"
    16470       #    and v->type is an addr, abort
    16471       {
    16472         (lookup *edi *(edi+4))  # Function-name Function-name => eax
    16473         (string-equal? %eax "lookup")  # => eax
    16474         3d/compare-eax-and 0/imm32/false
    16475         75/jump-if-!= break/disp8
    16476         (lookup *ebx *(ebx+4))  # => eax
    16477         (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    16478         (mu-addr-type? %eax)  # => eax
    16479         3d/compare-eax-and 0/imm32/false
    16480         0f 85/jump-if-!= $populate-mu-function-signature:error-addr-output/disp32
    16481       }
    16482       # out->outputs = append(v, out->outputs)
    16483       8d/copy-address *(edi+0x10) 0/r32/eax  # Function-outputs
    16484       (append-list Heap  *ebx *(ebx+4)  *(edi+0x10) *(edi+0x14)  %eax)  # Function-outputs, Function-outputs
    16485       #
    16486       e9/jump loop/disp32
    16487     }
    16488 $populate-mu-function-signature:done:
    16489     (check-no-tokens-left *(ebp+8))
    16490 $populate-mu-function-signature:end:
    16491     # . reclaim locals
    16492     81 0/subop/add %esp 0x10/imm32
    16493     # . restore registers
    16494     5f/pop-to-edi
    16495     5b/pop-to-ebx
    16496     5a/pop-to-edx
    16497     59/pop-to-ecx
    16498     58/pop-to-eax
    16499     # . epilogue
    16500     89/<- %esp 5/r32/ebp
    16501     5d/pop-to-ebp
    16502     c3/return
    16503
    16504 $populate-mu-function-signature:error1:
    16505     # error("function signature not in form 'fn <name> {'")
    16506     (write-buffered *(ebp+0x10) "function signature not in form 'fn <name> [inouts] [-> outputs] {' -- '")
    16507     (flush *(ebp+0x10))
    16508     (rewind-stream *(ebp+8))
    16509     (write-stream-data *(ebp+0x10) *(ebp+8))
    16510     (write-buffered *(ebp+0x10) "'\n")
    16511     (flush *(ebp+0x10))
    16512     (stop *(ebp+0x14) 1)
    16513     # never gets here
    16514
    16515 $populate-mu-function-signature:error2:
    16516     # error("fn " fn ": function inout '" var "' cannot be in a register")
    16517     (write-buffered *(ebp+0x10) "fn ")
    16518     50/push-eax
    16519     (lookup *edi *(edi+4))  # Function-name Function-name => eax
    16520     (write-buffered *(ebp+0x10) %eax)
    16521     58/pop-to-eax
    16522     (write-buffered *(ebp+0x10) ": function inout '")
    16523     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    16524     (write-buffered *(ebp+0x10) %eax)
    16525     (write-buffered *(ebp+0x10) "' cannot be in a register")
    16526     (flush *(ebp+0x10))
    16527     (stop *(ebp+0x14) 1)
    16528     # never gets here
    16529
    16530 $populate-mu-function-signature:error3:
    16531     # error("fn " fn ": function output '" var "' must be in a register")
    16532     (write-buffered *(ebp+0x10) "fn ")
    16533     50/push-eax
    16534     (lookup *edi *(edi+4))  # Function-name Function-name => eax
    16535     (write-buffered *(ebp+0x10) %eax)
    16536     58/pop-to-eax
    16537     (write-buffered *(ebp+0x10) ": function output '")
    16538     (lookup *ebx *(ebx+4))  # => eax
    16539     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    16540     (write-buffered *(ebp+0x10) %eax)
    16541     (write-buffered *(ebp+0x10) "' must be in a register, in instruction '")
    16542     (rewind-stream *(ebp+8))
    16543     (write-stream-data *(ebp+0x10) *(ebp+8))
    16544     (write-buffered *(ebp+0x10) "'\n")
    16545     (flush *(ebp+0x10))
    16546     (stop *(ebp+0x14) 1)
    16547     # never gets here
    16548
    16549 $populate-mu-function-signature:error4:
    16550     # error("fn " fn ": function outputs cannot be named; rename '" var "' in the header to '_'")
    16551     (write-buffered *(ebp+0x10) "fn ")
    16552     50/push-eax
    16553     (lookup *edi *(edi+4))  # Function-name Function-name => eax
    16554     (write-buffered *(ebp+0x10) %eax)
    16555     58/pop-to-eax
    16556     (write-buffered *(ebp+0x10) ": function outputs cannot be named; rename '")
    16557     (lookup *ebx *(ebx+4))  # => eax
    16558     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    16559     (write-buffered *(ebp+0x10) %eax)
    16560     (write-buffered *(ebp+0x10) "' in the header to '_'\n")
    16561     (flush *(ebp+0x10))
    16562     (stop *(ebp+0x14) 1)
    16563     # never gets here
    16564
    16565 $populate-mu-function-signature:error-duplicate:
    16566     (write-buffered *(ebp+0x10) "fn ")
    16567     (write-slice-buffered *(ebp+0x10) %ecx)
    16568     (write-buffered *(ebp+0x10) " defined more than once\n")
    16569     (flush *(ebp+0x10))
    16570     (stop *(ebp+0x14) 1)
    16571     # never gets here
    16572
    16573 $populate-mu-function-signature:error-break:
    16574     (write-buffered *(ebp+0x10) "Sorry, I've reserved all function names starting with 'break' for now. Please contact mu@akkartik.com.\n")
    16575     (flush *(ebp+0x10))
    16576     (stop *(ebp+0x14) 1)
    16577     # never gets here
    16578
    16579 $populate-mu-function-signature:error-loop:
    16580     (write-buffered *(ebp+0x10) "Sorry, I've reserved all function names starting with 'loop' for now. Please contact mu@akkartik.com.\n")
    16581     (flush *(ebp+0x10))
    16582     (stop *(ebp+0x14) 1)
    16583     # never gets here
    16584
    16585 $populate-mu-function-signature:error-addr-output:
    16586     # error("fn " fn ": output cannot have an addr type; that could allow unsafe addresses to escape the function")
    16587     (write-buffered *(ebp+0x10) "fn ")
    16588     50/push-eax
    16589     (lookup *edi *(edi+4))  # Function-name Function-name => eax
    16590     (write-buffered *(ebp+0x10) %eax)
    16591     58/pop-to-eax
    16592     (write-buffered *(ebp+0x10) ": output cannot have an addr type; that could allow unsafe addresses to escape the function\n")
    16593     (flush *(ebp+0x10))
    16594     (stop *(ebp+0x14) 1)
    16595     # never gets here
    16596
    16597 $populate-mu-function-signature:error-nested-addr-inout:
    16598     # 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")
    16599     (write-buffered *(ebp+0x10) "fn ")
    16600     (lookup *edi *(edi+4))  # Function-name Function-name => eax
    16601     (write-buffered *(ebp+0x10) %eax)
    16602     (write-buffered *(ebp+0x10) ": inout '")
    16603     (lookup *ebx *(ebx+4))  # => eax
    16604     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    16605     (write-buffered *(ebp+0x10) %eax)
    16606     (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")
    16607     (flush *(ebp+0x10))
    16608     (stop *(ebp+0x14) 1)
    16609     # never gets here
    16610
    16611 addr-payload-contains-addr?:  # v: (addr var) -> result/eax: boolean
    16612     # . prologue
    16613     55/push-ebp
    16614     89/<- %ebp 4/r32/esp
    16615     # var t/eax: (addr type-tree) = v->type
    16616     8b/-> *(ebp+8) 0/r32/eax
    16617     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    16618     # if t->right contains addr, return true
    16619     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
    16620     (type-tree-contains? %eax 2)  # addr => eax
    16621     # we don't have to look at t->left as long as it's guaranteed to be an atom
    16622 $addr-payload-contains-addr?:end:
    16623     # . epilogue
    16624     89/<- %esp 5/r32/ebp
    16625     5d/pop-to-ebp
    16626     c3/return
    16627
    16628 type-tree-contains?:  # t: (addr type-tree), n: type-id -> result/eax: boolean
    16629     # . prologue
    16630     55/push-ebp
    16631     89/<- %ebp 4/r32/esp
    16632     # . save registers
    16633     51/push-ecx
    16634     # if t is null, return false
    16635     8b/-> *(ebp+8) 0/r32/eax
    16636     3d/compare-eax-and 0/imm32
    16637     0f 84/jump-if-= $type-tree-contains?:end/disp32  # eax changes type
    16638     # if t is an atom, return (t->value == n)
    16639     81 7/subop/compare *eax 0/imm32/false
    16640     {
    16641       74/jump-if-= break/disp8
    16642       8b/-> *(ebp+0xc) 1/r32/ecx
    16643       39/compare *(eax+4) 1/r32/ecx  # Type-tree-value
    16644       0f 94/set-if-= %al
    16645       25/and-eax-with 0xff/imm32
    16646       eb/jump $type-tree-contains?:end/disp8
    16647     }
    16648     # if t->left contains n, return true
    16649     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    16650     (type-tree-contains? %eax *(ebp+0xc))  # => eax
    16651     3d/compare-eax-and 0/imm32/false
    16652     75/jump-if-!= $type-tree-contains?:end/disp8
    16653     # otherwise return whether t->right contains n
    16654     8b/-> *(ebp+8) 0/r32/eax
    16655     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
    16656     (type-tree-contains? %eax *(ebp+0xc))  # => eax
    16657 $type-tree-contains?:end:
    16658     # . restore registers
    16659     59/pop-to-ecx
    16660     # . epilogue
    16661     89/<- %esp 5/r32/ebp
    16662     5d/pop-to-ebp
    16663     c3/return
    16664
    16665 function-exists?:  # s: (addr slice) -> result/eax: boolean
    16666     # . prologue
    16667     55/push-ebp
    16668     89/<- %ebp 4/r32/esp
    16669     # . save registers
    16670     51/push-ecx
    16671     # var curr/ecx: (addr function) = functions
    16672     (lookup *_Program-functions *_Program-functions->payload)  # => eax
    16673     89/<- %ecx 0/r32/eax
    16674     {
    16675       # if (curr == null) break
    16676       81 7/subop/compare %ecx 0/imm32
    16677       74/jump-if-= break/disp8
    16678       # if (curr->name == s) return true
    16679       {
    16680         (lookup *ecx *(ecx+4))  # Function-name Function-name => eax
    16681         (slice-equal? *(ebp+8) %eax)  # => eax
    16682         3d/compare-eax-and 0/imm32/false
    16683         74/jump-if-= break/disp8
    16684         b8/copy-to-eax 1/imm32/true
    16685         e9/jump $function-exists?:end/disp32
    16686       }
    16687       # curr = curr->next
    16688       (lookup *(ecx+0x20) *(ecx+0x24))  # Function-next Function-next => eax
    16689       89/<- %ecx 0/r32/eax
    16690       #
    16691       eb/jump loop/disp8
    16692     }
    16693     # var curr/ecx: (addr function) = signatures
    16694     (lookup *_Program-signatures *_Program-signatures->payload)  # => eax
    16695     89/<- %ecx 0/r32/eax
    16696     {
    16697       # if (curr == null) break
    16698       81 7/subop/compare %ecx 0/imm32
    16699       74/jump-if-= break/disp8
    16700       # if (curr->name == s) return true
    16701       {
    16702         (lookup *ecx *(ecx+4))  # Function-name Function-name => eax
    16703         (slice-equal? *(ebp+8) %eax)  # => eax
    16704         3d/compare-eax-and 0/imm32/false
    16705         74/jump-if-= break/disp8
    16706         b8/copy-to-eax 1/imm32/true
    16707         eb/jump $function-exists?:end/disp8
    16708       }
    16709       # curr = curr->next
    16710       (lookup *(ecx+0x20) *(ecx+0x24))  # Function-next Function-next => eax
    16711       89/<- %ecx 0/r32/eax
    16712       #
    16713       eb/jump loop/disp8
    16714     }
    16715     # return false
    16716     b8/copy-to-eax 0/imm32/false
    16717 $function-exists?:end:
    16718     # . restore registers
    16719     59/pop-to-ecx
    16720     # . epilogue
    16721     89/<- %esp 5/r32/ebp
    16722     5d/pop-to-ebp
    16723     c3/return
    16724
    16725 test-function-header-with-arg:
    16726     # . prologue
    16727     55/push-ebp
    16728     89/<- %ebp 4/r32/esp
    16729     # setup
    16730     8b/-> *Primitive-type-ids 0/r32/eax
    16731     89/<- *Type-id 0/r32/eax  # stream-write
    16732     c7 0/subop/copy *_Program-functions 0/imm32
    16733     c7 0/subop/copy *_Program-functions->payload 0/imm32
    16734     c7 0/subop/copy *_Program-types 0/imm32
    16735     c7 0/subop/copy *_Program-types->payload 0/imm32
    16736     c7 0/subop/copy *_Program-signatures 0/imm32
    16737     c7 0/subop/copy *_Program-signatures->payload 0/imm32
    16738     (clear-stream _test-input-stream)
    16739     (write _test-input-stream "foo n: int {\n")
    16740     # var result/ecx: function
    16741     2b/subtract *Function-size 4/r32/esp
    16742     89/<- %ecx 4/r32/esp
    16743     (zero-out %ecx *Function-size)
    16744     # var vars/ebx: (stack live-var 16)
    16745     81 5/subop/subtract %esp 0xc0/imm32
    16746     68/push 0xc0/imm32/size
    16747     68/push 0/imm32/top
    16748     89/<- %ebx 4/r32/esp
    16749     # convert
    16750     (populate-mu-function-header _test-input-stream %ecx %ebx Stderr 0)
    16751     # check result->name
    16752     (lookup *ecx *(ecx+4))  # Function-name Function-name => eax
    16753     (check-strings-equal %eax "foo" "F - test-function-header-with-arg/name")
    16754     # var v/edx: (addr var) = result->inouts->value
    16755     (lookup *(ecx+8) *(ecx+0xc))  # Function-inouts Function-inouts => eax
    16756     (lookup *eax *(eax+4))  # List-value List-value => eax
    16757     89/<- %edx 0/r32/eax
    16758     # check v->name
    16759     (lookup *edx *(edx+4))  # Var-name Var-name => eax
    16760     (check-strings-equal %eax "n" "F - test-function-header-with-arg/inout:0")
    16761     # check v->type
    16762     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
    16763     (check-ints-equal *eax 1 "F - test-function-header-with-arg/inout:0/type:0")  # Type-tree-is-atom
    16764     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-arg/inout:0/type:1")  # Type-tree-value
    16765     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-arg/inout:0/type:2")  # Type-tree-right
    16766     # . epilogue
    16767     89/<- %esp 5/r32/ebp
    16768     5d/pop-to-ebp
    16769     c3/return
    16770
    16771 test-function-header-with-multiple-args:
    16772     # . prologue
    16773     55/push-ebp
    16774     89/<- %ebp 4/r32/esp
    16775     # setup
    16776     8b/-> *Primitive-type-ids 0/r32/eax
    16777     89/<- *Type-id 0/r32/eax  # stream-write
    16778     c7 0/subop/copy *_Program-functions 0/imm32
    16779     c7 0/subop/copy *_Program-functions->payload 0/imm32
    16780     c7 0/subop/copy *_Program-types 0/imm32
    16781     c7 0/subop/copy *_Program-types->payload 0/imm32
    16782     c7 0/subop/copy *_Program-signatures 0/imm32
    16783     c7 0/subop/copy *_Program-signatures->payload 0/imm32
    16784     (clear-stream _test-input-stream)
    16785     (write _test-input-stream "foo a: int, b: int c: int {\n")
    16786     # result/ecx: function
    16787     2b/subtract *Function-size 4/r32/esp
    16788     89/<- %ecx 4/r32/esp
    16789     (zero-out %ecx *Function-size)
    16790     # var vars/ebx: (stack live-var 16)
    16791     81 5/subop/subtract %esp 0xc0/imm32
    16792     68/push 0xc0/imm32/size
    16793     68/push 0/imm32/top
    16794     89/<- %ebx 4/r32/esp
    16795     # convert
    16796     (populate-mu-function-header _test-input-stream %ecx %ebx Stderr 0)
    16797     # check result->name
    16798     (lookup *ecx *(ecx+4))  # Function-name Function-name => eax
    16799     (check-strings-equal %eax "foo" "F - test-function-header-with-multiple-args/name")
    16800     # var inouts/edx: (addr list var) = lookup(result->inouts)
    16801     (lookup *(ecx+8) *(ecx+0xc))  # Function-inouts Function-inouts => eax
    16802     89/<- %edx 0/r32/eax
    16803 $test-function-header-with-multiple-args:inout0:
    16804     # var v/ebx: (addr var) = lookup(inouts->value)
    16805     (lookup *edx *(edx+4))  # List-value List-value => eax
    16806     89/<- %ebx 0/r32/eax
    16807     # check v->name
    16808     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
    16809     (check-strings-equal %eax "a" "F - test-function-header-with-multiple-args/inout:0")  # Var-name
    16810     # check v->type
    16811     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
    16812     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args/inout:0/type:0")  # Type-tree-is-atom
    16813     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args/inout:0/type:1")  # Type-tree-value
    16814     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args/inout:0/type:2")  # Type-tree-right
    16815 $test-function-header-with-multiple-args:inout1:
    16816     # inouts = lookup(inouts->next)
    16817     (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
    16818     89/<- %edx 0/r32/eax
    16819     # v = lookup(inouts->value)
    16820     (lookup *edx *(edx+4))  # List-value List-value => eax
    16821     89/<- %ebx 0/r32/eax
    16822     # check v->name
    16823     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
    16824     (check-strings-equal %eax "b" "F - test-function-header-with-multiple-args/inout:1")  # Var-name
    16825     # check v->type
    16826     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
    16827     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args/inout:1/type:0")  # Type-tree-is-atom
    16828     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args/inout:1/type:1")  # Type-tree-value
    16829     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args/inout:1/type:2")  # Type-tree-right
    16830 $test-function-header-with-multiple-args:inout2:
    16831     # inouts = lookup(inouts->next)
    16832     (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
    16833     89/<- %edx 0/r32/eax
    16834     # v = lookup(inouts->value)
    16835     (lookup *edx *(edx+4))  # List-value List-value => eax
    16836     89/<- %ebx 0/r32/eax
    16837     # check v->name
    16838     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
    16839     (check-strings-equal %eax "c" "F - test-function-header-with-multiple-args/inout:2")  # Var-name
    16840     # check v->type
    16841     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
    16842     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args/inout:2/type:0")  # Type-tree-is-atom
    16843     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args/inout:2/type:1")  # Type-tree-value
    16844     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args/inout:2/type:2")  # Type-tree-right
    16845     # . epilogue
    16846     89/<- %esp 5/r32/ebp
    16847     5d/pop-to-ebp
    16848     c3/return
    16849
    16850 test-function-header-with-multiple-args-and-outputs:
    16851     # . prologue
    16852     55/push-ebp
    16853     89/<- %ebp 4/r32/esp
    16854     # setup
    16855     8b/-> *Primitive-type-ids 0/r32/eax
    16856     89/<- *Type-id 0/r32/eax  # stream-write
    16857     c7 0/subop/copy *_Program-functions 0/imm32
    16858     c7 0/subop/copy *_Program-functions->payload 0/imm32
    16859     c7 0/subop/copy *_Program-types 0/imm32
    16860     c7 0/subop/copy *_Program-types->payload 0/imm32
    16861     c7 0/subop/copy *_Program-signatures 0/imm32
    16862     c7 0/subop/copy *_Program-signatures->payload 0/imm32
    16863     (clear-stream _test-input-stream)
    16864     (write _test-input-stream "foo a: int, b: int, c: int -> _/ecx: int _/edx: int {\n")
    16865     # result/ecx: function
    16866     2b/subtract *Function-size 4/r32/esp
    16867     89/<- %ecx 4/r32/esp
    16868     (zero-out %ecx *Function-size)
    16869     # var vars/ebx: (stack live-var 16)
    16870     81 5/subop/subtract %esp 0xc0/imm32
    16871     68/push 0xc0/imm32/size
    16872     68/push 0/imm32/top
    16873     89/<- %ebx 4/r32/esp
    16874     # convert
    16875     (populate-mu-function-header _test-input-stream %ecx %ebx Stderr 0)
    16876     # check result->name
    16877     (lookup *ecx *(ecx+4))  # Function-name Function-name => eax
    16878     (check-strings-equal %eax "foo" "F - test-function-header-with-multiple-args-and-outputs/name")
    16879     # var inouts/edx: (addr list var) = lookup(result->inouts)
    16880     (lookup *(ecx+8) *(ecx+0xc))  # Function-inouts Function-inouts => eax
    16881     89/<- %edx 0/r32/eax
    16882 $test-function-header-with-multiple-args-and-outputs:inout0:
    16883     # var v/ebx: (addr var) = lookup(inouts->value)
    16884     (lookup *edx *(edx+4))  # List-value List-value => eax
    16885     89/<- %ebx 0/r32/eax
    16886     # check v->name
    16887     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
    16888     (check-strings-equal %eax "a" "F - test-function-header-with-multiple-args-and-outputs/inout:0")
    16889     # check v->type
    16890     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
    16891     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args-and-outputs/inout:0/type:0")  # Type-tree-is-atom
    16892     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args-and-outputs/inout:0/type:1")  # Type-tree-value
    16893     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args-and-outputs/inout:0/type:2")  # Type-tree-right
    16894 $test-function-header-with-multiple-args-and-outputs:inout1:
    16895     # inouts = lookup(inouts->next)
    16896     (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
    16897     89/<- %edx 0/r32/eax
    16898     # v = lookup(inouts->value)
    16899     (lookup *edx *(edx+4))  # List-value List-value => eax
    16900     89/<- %ebx 0/r32/eax
    16901     # check v->name
    16902     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
    16903     (check-strings-equal %eax "b" "F - test-function-header-with-multiple-args-and-outputs/inout:1")
    16904     # check v->type
    16905     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
    16906     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args-and-outputs/inout:1/type:0")  # Type-tree-is-atom
    16907     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args-and-outputs/inout:1/type:1")  # Type-tree-value
    16908     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args-and-outputs/inout:1/type:2")  # Type-tree-right
    16909 $test-function-header-with-multiple-args-and-outputs:inout2:
    16910     # inouts = lookup(inouts->next)
    16911     (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
    16912     89/<- %edx 0/r32/eax
    16913     # v = lookup(inouts->value)
    16914     (lookup *edx *(edx+4))  # List-value List-value => eax
    16915     89/<- %ebx 0/r32/eax
    16916     # check v->name
    16917     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
    16918     (check-strings-equal %eax "c" "F - test-function-header-with-multiple-args-and-outputs/inout:2")
    16919     # check v->type
    16920     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
    16921     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args-and-outputs/inout:2/type:0")  # Type-tree-is-atom
    16922     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args-and-outputs/inout:2/type:1")  # Type-tree-value
    16923     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args-and-outputs/inout:2/type:2")  # Type-tree-right
    16924 $test-function-header-with-multiple-args-and-outputs:out0:
    16925     # var outputs/edx: (addr list var) = lookup(result->outputs)
    16926     (lookup *(ecx+0x10) *(ecx+0x14))  # Function-outputs Function-outputs => eax
    16927     89/<- %edx 0/r32/eax
    16928     # v = lookup(outputs->value)
    16929     (lookup *edx *(edx+4))  # List-value List-value => eax
    16930     89/<- %ebx 0/r32/eax
    16931     # check v->name
    16932     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
    16933     (check-strings-equal %eax "_" "F - test-function-header-with-multiple-args-and-outputs/output:0")
    16934     # check v->register
    16935     (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
    16936     (check-strings-equal %eax "ecx" "F - test-function-header-with-multiple-args-and-outputs/output:0/register")
    16937     # check v->type
    16938     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
    16939     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args-and-outputs/output:0/type:0")  # Type-tree-is-atom
    16940     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args-and-outputs/output:0/type:1")  # Type-tree-value
    16941     (check-ints-equal *(eax+0xc) 0 "F - test-function-header-with-multiple-args-and-outputs/output:0/type:2")  # Type-tree-right
    16942 $test-function-header-with-multiple-args-and-outputs:out1:
    16943     # outputs = lookup(outputs->next)
    16944     (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
    16945     89/<- %edx 0/r32/eax
    16946     # v = lookup(inouts->value)
    16947     (lookup *edx *(edx+4))  # List-value List-value => eax
    16948     89/<- %ebx 0/r32/eax
    16949     # check v->name
    16950     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
    16951     (check-strings-equal %eax "_" "F - test-function-header-with-multiple-args-and-outputs/output:1")
    16952     # check v->register
    16953     (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
    16954     (check-strings-equal %eax "edx" "F - test-function-header-with-multiple-args-and-outputs/output:1/register")
    16955     # check v->type
    16956     (lookup *(ebx+8) *(ebx+0xc))  # Var-type Var-type => eax
    16957     (check-ints-equal *eax 1 "F - test-function-header-with-multiple-args-and-outputs/output:1/type:0")  # Type-tree-is-atom
    16958     (check-ints-equal *(eax+4) 1 "F - test-function-header-with-multiple-args-and-outputs/output:1/type:1")  # Type-tree-value
    16959     (check-ints-equal *(eax+0c) 0 "F - test-function-header-with-multiple-args-and-outputs/output:1/type:2")  # Type-tree-right
    16960     # . epilogue
    16961     89/<- %esp 5/r32/ebp
    16962     5d/pop-to-ebp
    16963     c3/return
    16964
    16965 # format for variables with types
    16966 #   x: int
    16967 #   x: int,
    16968 #   x/eax: int
    16969 #   x/eax: int,
    16970 # ignores at most one trailing comma
    16971 # does not support other, non-register metadata
    16972 # WARNING: modifies name
    16973 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)
    16974     # pseudocode:
    16975     #   var s: slice
    16976     #   if (!slice-ends-with(name, ":"))
    16977     #     abort
    16978     #   --name->end to skip ':'
    16979     #   next-token-from-slice(name->start, name->end, '/', s)
    16980     #   new-var-from-slice(s, out)
    16981     #   ## register
    16982     #   next-token-from-slice(s->end, name->end, '/', s)
    16983     #   if (!slice-empty?(s))
    16984     #     out->register = slice-to-string(s)
    16985     #   ## type
    16986     #   var type: (handle type-tree) = parse-type(first-line)
    16987     #   out->type = type
    16988     #
    16989     # . prologue
    16990     55/push-ebp
    16991     89/<- %ebp 4/r32/esp
    16992     # . save registers
    16993     50/push-eax
    16994     51/push-ecx
    16995     52/push-edx
    16996     53/push-ebx
    16997     56/push-esi
    16998     57/push-edi
    16999     # esi = name
    17000     8b/-> *(ebp+8) 6/r32/esi
    17001     # if (!slice-ends-with?(name, ":")) abort
    17002     8b/-> *(esi+4) 1/r32/ecx  # Slice-end
    17003     49/decrement-ecx
    17004     8a/copy-byte *ecx 1/r32/CL
    17005     81 4/subop/and %ecx 0xff/imm32
    17006     81 7/subop/compare %ecx 0x3a/imm32/colon
    17007     0f 85/jump-if-!= $parse-var-with-type:abort/disp32
    17008     # --name->end to skip ':'
    17009     ff 1/subop/decrement *(esi+4)
    17010     # var s/ecx: slice
    17011     68/push 0/imm32/end
    17012     68/push 0/imm32/start
    17013     89/<- %ecx 4/r32/esp
    17014 $parse-var-with-type:parse-name:
    17015     (next-token-from-slice *esi *(esi+4) 0x2f %ecx)  # Slice-start, Slice-end, '/'
    17016 $parse-var-with-type:create-var:
    17017     # new-var-from-slice(s, out)
    17018     (new-var-from-slice Heap %ecx *(ebp+0x10))
    17019     # save out->register
    17020 $parse-var-with-type:save-register:
    17021     # . var out-addr/edi: (addr var) = lookup(*out)
    17022     8b/-> *(ebp+0x10) 7/r32/edi
    17023     (lookup *edi *(edi+4))  # => eax
    17024     89/<- %edi 0/r32/eax
    17025     # . s = next-token(...)
    17026     (next-token-from-slice *(ecx+4) *(esi+4) 0x2f %ecx)  # s->end, name->end, '/'
    17027     # . if (!slice-empty?(s)) out->register = slice-to-string(s)
    17028     {
    17029 $parse-var-with-type:write-register:
    17030       (slice-empty? %ecx)  # => eax
    17031       3d/compare-eax-and 0/imm32/false
    17032       75/jump-if-!= break/disp8
    17033       # out->register = slice-to-string(s)
    17034       8d/copy-address *(edi+0x18) 0/r32/eax  # Var-register
    17035       (slice-to-string Heap %ecx %eax)
    17036     }
    17037 $parse-var-with-type:save-type:
    17038     8d/copy-address *(edi+8) 0/r32/eax  # Var-type
    17039     (parse-type Heap *(ebp+0xc) %eax *(ebp+0x18) *(ebp+0x1c))
    17040 $parse-var-with-type:check-register:
    17041     (lookup *(edi+0x18) *(edi+0x1c))  # Var-register Var-register => eax
    17042     3d/compare-eax-and 0/imm32
    17043     74/jump-if-= $parse-var-with-type:end/disp8
    17044     (float-register? %eax)  # => eax
    17045     {
    17046       3d/compare-eax-and 0/imm32/false
    17047       74/jump-if-= break/disp8
    17048       # var is in a float register; ensure type is float
    17049       (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
    17050       (simple-mu-type? %eax 0xf)  # float => eax
    17051       3d/compare-eax-and 0/imm32/false
    17052       0f 84/jump-if-= $parse-var-with-type:error-non-float-in-floating-point-register/disp32
    17053       eb/jump $parse-var-with-type:end/disp8
    17054     }
    17055     # var is not in a float register; ensure type is not float
    17056     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
    17057     (simple-mu-type? %eax 0xf)  # float => eax
    17058     3d/compare-eax-and 0/imm32/false
    17059     0f 85/jump-if-!= $parse-var-with-type:error-float-in-integer-register/disp32
    17060 $parse-var-with-type:end:
    17061     # . reclaim locals
    17062     81 0/subop/add %esp 8/imm32
    17063     # . restore registers
    17064     5f/pop-to-edi
    17065     5e/pop-to-esi
    17066     5b/pop-to-ebx
    17067     5a/pop-to-edx
    17068     59/pop-to-ecx
    17069     58/pop-to-eax
    17070     # . epilogue
    17071     89/<- %esp 5/r32/ebp
    17072     5d/pop-to-ebp
    17073     c3/return
    17074
    17075 $parse-var-with-type:abort:
    17076     # error("fn " fn ": var should have form 'name: type' in '" line "'\n")
    17077     (write-buffered *(ebp+0x18) "fn ")
    17078     (write-buffered *(ebp+0x18) *(ebp+0x14))
    17079     (write-buffered *(ebp+0x18) ": var should have form 'name: type' in '")
    17080     (flush *(ebp+0x18))
    17081     (rewind-stream *(ebp+0xc))
    17082     (write-stream-data *(ebp+0x18) *(ebp+0xc))
    17083     (write-buffered *(ebp+0x18) "'\n")
    17084     (flush *(ebp+0x18))
    17085     (stop *(ebp+0x1c) 1)
    17086     # never gets here
    17087
    17088 $parse-var-with-type:error-float-in-integer-register:
    17089     # error("fn " fn ": float var '" var "' should be in a floating-point register\n")
    17090     (write-buffered *(ebp+0x18) "fn ")
    17091     (write-buffered *(ebp+0x18) *(ebp+0x14))
    17092     (write-buffered *(ebp+0x18) ": float var '")
    17093     (lookup *edi *(edi+4))  # Var-name Var-name => eax
    17094     (write-buffered *(ebp+0x18) %eax)
    17095     (write-buffered *(ebp+0x18) "' should be in a floating-point register\n")
    17096     (flush *(ebp+0x18))
    17097     (stop *(ebp+0x1c) 1)
    17098     # never gets here
    17099
    17100 $parse-var-with-type:error-non-float-in-floating-point-register:
    17101     # error("fn " fn ": non-float var '" var "' should be in an integer register\n")
    17102     (write-buffered *(ebp+0x18) "fn ")
    17103     (write-buffered *(ebp+0x18) *(ebp+0x14))
    17104     (write-buffered *(ebp+0x18) ": non-float var '")
    17105     (lookup *edi *(edi+4))  # Var-name Var-name => eax
    17106     (write-buffered *(ebp+0x18) %eax)
    17107     (write-buffered *(ebp+0x18) "' should be in an integer register\n")
    17108     (flush *(ebp+0x18))
    17109     (stop *(ebp+0x1c) 1)
    17110     # never gets here
    17111
    17112 float-register?:  # r: (addr array byte) -> result/eax: boolean
    17113     # . prologue
    17114     55/push-ebp
    17115     89/<- %ebp 4/r32/esp
    17116     #
    17117     (get Mu-registers-unique *(ebp+8) 0xc "Mu-registers-unique")  # => eax
    17118     81 7/subop/compare *eax 8/imm32/start-of-floating-point-registers
    17119     0f 9d/set-if->= %al
    17120     25/and-eax-with 0xff/imm32
    17121 $float-register?:end:
    17122     # . epilogue
    17123     89/<- %esp 5/r32/ebp
    17124     5d/pop-to-ebp
    17125     c3/return
    17126
    17127 parse-type:  # ad: (addr allocation-descriptor), in: (addr stream byte), out: (addr handle type-tree), err: (addr buffered-file), ed: (addr exit-descriptor)
    17128     # pseudocode:
    17129     #   var s: slice = next-mu-token(in)
    17130     #   assert s != ""
    17131     #   assert s != "->"
    17132     #   assert s != "{"
    17133     #   assert s != "}"
    17134     #   if s == ")"
    17135     #     return
    17136     #   out = allocate(Type-tree)
    17137     #   if s != "("
    17138     #     HACK: if s is an int, parse and return it
    17139     #     out->is-atom? = true
    17140     #     if (s[0] == "_")
    17141     #       out->value = type-parameter
    17142     #       out->parameter-name = slice-to-string(ad, s)
    17143     #     else
    17144     #       out->value = pos-or-insert-slice(Type-id, s)
    17145     #     return
    17146     #   out->left = parse-type(ad, in)
    17147     #   out->right = parse-type-tree(ad, in)
    17148     #
    17149     # . prologue
    17150     55/push-ebp
    17151     89/<- %ebp 4/r32/esp
    17152     # . save registers
    17153     50/push-eax
    17154     51/push-ecx
    17155     52/push-edx
    17156     # clear out
    17157     (zero-out *(ebp+0x10) *Handle-size)
    17158     # var s/ecx: slice
    17159     68/push 0/imm32
    17160     68/push 0/imm32
    17161     89/<- %ecx 4/r32/esp
    17162     # s = next-mu-token(in)
    17163     (next-mu-token *(ebp+0xc) %ecx)
    17164 #?     (write-buffered Stderr "tok: ")
    17165 #?     (write-slice-buffered Stderr %ecx)
    17166 #?     (write-buffered Stderr "$\n")
    17167 #?     (flush Stderr)
    17168     # assert s != ""
    17169     (slice-equal? %ecx "")  # => eax
    17170     3d/compare-eax-and 0/imm32/false
    17171     0f 85/jump-if-!= $parse-type:abort/disp32
    17172     # assert s != "{"
    17173     (slice-equal? %ecx "{")  # => eax
    17174     3d/compare-eax-and 0/imm32/false
    17175     0f 85/jump-if-!= $parse-type:abort/disp32
    17176     # assert s != "}"
    17177     (slice-equal? %ecx "}")  # => eax
    17178     3d/compare-eax-and 0/imm32/false
    17179     0f 85/jump-if-!= $parse-type:abort/disp32
    17180     # assert s != "->"
    17181     (slice-equal? %ecx "->")  # => eax
    17182     3d/compare-eax-and 0/imm32/false
    17183     0f 85/jump-if-!= $parse-type:abort/disp32
    17184     # if (s == ")") return
    17185     (slice-equal? %ecx ")")  # => eax
    17186     3d/compare-eax-and 0/imm32/false
    17187     0f 85/jump-if-!= $parse-type:end/disp32
    17188     # out = new tree
    17189     (allocate *(ebp+8) *Type-tree-size *(ebp+0x10))
    17190     # var out-addr/edx: (addr type-tree) = lookup(*out)
    17191     8b/-> *(ebp+0x10) 2/r32/edx
    17192     (lookup *edx *(edx+4))  # => eax
    17193     89/<- %edx 0/r32/eax
    17194     {
    17195       # if (s != "(") break
    17196       (slice-equal? %ecx "(")  # => eax
    17197       3d/compare-eax-and 0/imm32/false
    17198       0f 85/jump-if-!= break/disp32
    17199       # if s is a number, store it in the type's size field
    17200       {
    17201 $parse-type:check-for-int:
    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         # TODO: raise an error on `var x: (array int a)`
    17207         (decimal-digit? %eax)  # => eax
    17208         3d/compare-eax-and 0/imm32/false
    17209         74/jump-if-= break/disp8
    17210 $parse-type:int:
    17211         # strip out metadata
    17212         (next-token-from-slice *ecx *(ecx+4) 0x2f %ecx)
    17213         #
    17214         (check-mu-hex-int %ecx *(ebp+0x14) *(ebp+0x18))
    17215         (parse-hex-int-from-slice %ecx)  # => eax
    17216         c7 0/subop/copy *(edx+4) 9/imm32/type-id-array-capacity  # Type-tree-value
    17217         89/<- *(edx+8) 0/r32/eax  # Type-tree-value-size
    17218         e9/jump $parse-type:end/disp32
    17219       }
    17220 $parse-type:atom:
    17221       # out->is-atom? = true
    17222       c7 0/subop/copy *edx 1/imm32/true  # Type-tree-is-atom
    17223       {
    17224 $parse-type:check-for-type-parameter:
    17225         # var tmp/eax: byte = *s->slice
    17226         8b/-> *ecx 0/r32/eax
    17227         8a/copy-byte *eax 0/r32/AL
    17228         25/and-eax-with 0xff/imm32
    17229         # if (tmp != '_') break
    17230         3d/compare-eax-and 0x5f/imm32/_
    17231         75/jump-if-!= break/disp8
    17232 $parse-type:type-parameter:
    17233         # out->value = type-parameter
    17234         c7 0/subop/copy *(edx+4) 0xa/imm32/type-parameter  # Type-tree-value
    17235         # out->parameter-name = slice-to-string(ad, s)
    17236         8d/copy-address *(edx+8) 0/r32/eax  # Type-tree-parameter-name
    17237         (slice-to-string *(ebp+8) %ecx %eax)
    17238         e9/jump $parse-type:end/disp32
    17239       }
    17240 $parse-type:non-type-parameter:
    17241       # out->value = pos-or-insert-slice(Type-id, s)
    17242       (pos-or-insert-slice Type-id %ecx)  # => eax
    17243       89/<- *(edx+4) 0/r32/eax  # Type-tree-value
    17244       e9/jump $parse-type:end/disp32
    17245     }
    17246 $parse-type:non-atom:
    17247     # otherwise s == "("
    17248     # out->left = parse-type(ad, in)
    17249     8d/copy-address *(edx+4) 0/r32/eax  # Type-tree-left
    17250     (parse-type *(ebp+8) *(ebp+0xc) %eax *(ebp+0x14) *(ebp+0x18))
    17251     # out->right = parse-type-tree(ad, in)
    17252     8d/copy-address *(edx+0xc) 0/r32/eax  # Type-tree-right
    17253     (parse-type-tree *(ebp+8) *(ebp+0xc) %eax *(ebp+0x14) *(ebp+0x18))
    17254 $parse-type:end:
    17255     # . reclaim locals
    17256     81 0/subop/add %esp 8/imm32
    17257     # . restore registers
    17258     5a/pop-to-edx
    17259     59/pop-to-ecx
    17260     58/pop-to-eax
    17261     # . epilogue
    17262     89/<- %esp 5/r32/ebp
    17263     5d/pop-to-ebp
    17264     c3/return
    17265
    17266 $parse-type:abort:
    17267     # error("unexpected token when parsing type: '" s "'\n")
    17268     (write-buffered *(ebp+0x14) "unexpected token when parsing type: '")
    17269     (write-slice-buffered *(ebp+0x14) %ecx)
    17270     (write-buffered *(ebp+0x14) "'\n")
    17271     (flush *(ebp+0x14))
    17272     (stop *(ebp+0x18) 1)
    17273     # never gets here
    17274
    17275 parse-type-tree:  # ad: (addr allocation-descriptor), in: (addr stream byte), out: (addr handle type-tree), err: (addr buffered-file), ed: (addr exit-descriptor)
    17276     # pseudocode:
    17277     #   var tmp: (handle type-tree) = parse-type(ad, in)
    17278     #   if tmp == 0
    17279     #     return 0
    17280     #   out = allocate(Type-tree)
    17281     #   out->left = tmp
    17282     #   out->right = parse-type-tree(ad, in)
    17283     #
    17284     # . prologue
    17285     55/push-ebp
    17286     89/<- %ebp 4/r32/esp
    17287     # . save registers
    17288     50/push-eax
    17289     51/push-ecx
    17290     52/push-edx
    17291     #
    17292     (zero-out *(ebp+0x10) *Handle-size)
    17293     # var tmp/ecx: (handle type-tree)
    17294     68/push 0/imm32
    17295     68/push 0/imm32
    17296     89/<- %ecx 4/r32/esp
    17297     # tmp = parse-type(ad, in)
    17298     (parse-type *(ebp+8) *(ebp+0xc) %ecx *(ebp+0x14) *(ebp+0x18))
    17299     # if (tmp == 0) return
    17300     81 7/subop/compare *ecx 0/imm32
    17301     74/jump-if-= $parse-type-tree:end/disp8
    17302     # out = new tree
    17303     (allocate *(ebp+8) *Type-tree-size *(ebp+0x10))
    17304     # var out-addr/edx: (addr tree) = lookup(*out)
    17305     8b/-> *(ebp+0x10) 2/r32/edx
    17306     (lookup *edx *(edx+4))  # => eax
    17307     89/<- %edx 0/r32/eax
    17308     # out->left = tmp
    17309     8b/-> *ecx 0/r32/eax
    17310     89/<- *(edx+4) 0/r32/eax  # Type-tree-left
    17311     8b/-> *(ecx+4) 0/r32/eax
    17312     89/<- *(edx+8) 0/r32/eax  # Type-tree-left
    17313     # out->right = parse-type-tree(ad, in)
    17314     8d/copy-address *(edx+0xc) 0/r32/eax  # Type-tree-right
    17315     (parse-type-tree *(ebp+8) *(ebp+0xc) %eax *(ebp+0x14) *(ebp+0x18))
    17316 $parse-type-tree:end:
    17317     # . reclaim locals
    17318     81 0/subop/add %esp 8/imm32
    17319     # . restore registers
    17320     5a/pop-to-edx
    17321     59/pop-to-ecx
    17322     58/pop-to-eax
    17323     # . epilogue
    17324     89/<- %esp 5/r32/ebp
    17325     5d/pop-to-ebp
    17326     c3/return
    17327
    17328 next-mu-token:  # in: (addr stream byte), out: (addr slice)
    17329     # pseudocode:
    17330     # start:
    17331     #   skip-chars-matching-whitespace(in)
    17332     #   if in->read >= in->write              # end of in
    17333     #     out = {0, 0}
    17334     #     return
    17335     #   out->start = &in->data[in->read]
    17336     #   var curr-byte/eax: byte = in->data[in->read]
    17337     #   if curr->byte == ','                  # comment token
    17338     #     ++in->read
    17339     #     goto start
    17340     #   if curr-byte == '#'                   # comment
    17341     #     goto done                             # treat as eof
    17342     #   if curr-byte == '"'                   # string literal
    17343     #     skip-string(in)
    17344     #     goto done                           # no metadata
    17345     #   if curr-byte == '('
    17346     #     ++in->read
    17347     #     goto done
    17348     #   if curr-byte == ')'
    17349     #     ++in->read
    17350     #     goto done
    17351     #   # read a word
    17352     #   while true
    17353     #     if in->read >= in->write
    17354     #       break
    17355     #     curr-byte = in->data[in->read]
    17356     #     if curr-byte == ' '
    17357     #       break
    17358     #     if curr-byte == '\r'
    17359     #       break
    17360     #     if curr-byte == '\n'
    17361     #       break
    17362     #     if curr-byte == '('
    17363     #       break
    17364     #     if curr-byte == ')'
    17365     #       break
    17366     #     if curr-byte == ','
    17367     #       break
    17368     #     ++in->read
    17369     # done:
    17370     #   out->end = &in->data[in->read]
    17371     #
    17372     # . prologue
    17373     55/push-ebp
    17374     89/<- %ebp 4/r32/esp
    17375     # . save registers
    17376     50/push-eax
    17377     51/push-ecx
    17378     56/push-esi
    17379     57/push-edi
    17380     # esi = in
    17381     8b/-> *(ebp+8) 6/r32/esi
    17382     # edi = out
    17383     8b/-> *(ebp+0xc) 7/r32/edi
    17384 $next-mu-token:start:
    17385     (skip-chars-matching-whitespace %esi)
    17386 $next-mu-token:check0:
    17387     # if (in->read >= in->write) return out = {0, 0}
    17388     # . ecx = in->read
    17389     8b/-> *(esi+4) 1/r32/ecx
    17390     # . if (ecx >= in->write) return out = {0, 0}
    17391     3b/compare<- *esi 1/r32/ecx
    17392     c7 0/subop/copy *edi 0/imm32
    17393     c7 0/subop/copy *(edi+4) 0/imm32
    17394     0f 8d/jump-if->= $next-mu-token:end/disp32
    17395     # out->start = &in->data[in->read]
    17396     8d/copy-address *(esi+ecx+0xc) 0/r32/eax
    17397     89/<- *edi 0/r32/eax
    17398     # var curr-byte/eax: byte = in->data[in->read]
    17399     31/xor-with %eax 0/r32/eax
    17400     8a/copy-byte *(esi+ecx+0xc) 0/r32/AL
    17401     {
    17402 $next-mu-token:check-for-comma:
    17403       # if (curr-byte != ',') break
    17404       3d/compare-eax-and 0x2c/imm32/comma
    17405       75/jump-if-!= break/disp8
    17406       # ++in->read
    17407       ff 0/subop/increment *(esi+4)
    17408       # restart
    17409       e9/jump $next-mu-token:start/disp32
    17410     }
    17411     {
    17412 $next-mu-token:check-for-comment:
    17413       # if (curr-byte != '#') break
    17414       3d/compare-eax-and 0x23/imm32/pound
    17415       75/jump-if-!= break/disp8
    17416       # return eof
    17417       e9/jump $next-mu-token:done/disp32
    17418     }
    17419     {
    17420 $next-mu-token:check-for-string-literal:
    17421       # if (curr-byte != '"') break
    17422       3d/compare-eax-and 0x22/imm32/dquote
    17423       75/jump-if-!= break/disp8
    17424       (skip-string %esi)
    17425       # return
    17426       e9/jump $next-mu-token:done/disp32
    17427     }
    17428     {
    17429 $next-mu-token:check-for-open-paren:
    17430       # if (curr-byte != '(') break
    17431       3d/compare-eax-and 0x28/imm32/open-paren
    17432       75/jump-if-!= break/disp8
    17433       # ++in->read
    17434       ff 0/subop/increment *(esi+4)
    17435       # return
    17436       e9/jump $next-mu-token:done/disp32
    17437     }
    17438     {
    17439 $next-mu-token:check-for-close-paren:
    17440       # if (curr-byte != ')') break
    17441       3d/compare-eax-and 0x29/imm32/close-paren
    17442       75/jump-if-!= break/disp8
    17443       # ++in->read
    17444       ff 0/subop/increment *(esi+4)
    17445       # return
    17446       e9/jump $next-mu-token:done/disp32
    17447     }
    17448     {
    17449 $next-mu-token:regular-word-without-metadata:
    17450       # if (in->read >= in->write) break
    17451       # . ecx = in->read
    17452       8b/-> *(esi+4) 1/r32/ecx
    17453       # . if (ecx >= in->write) break
    17454       3b/compare<- *esi 1/r32/ecx
    17455       7d/jump-if->= break/disp8
    17456       # var c/eax: byte = in->data[in->read]
    17457       31/xor-with %eax 0/r32/eax
    17458       8a/copy-byte *(esi+ecx+0xc) 0/r32/AL
    17459       # if (c == ' ') break
    17460       3d/compare-eax-and 0x20/imm32/space
    17461       74/jump-if-= break/disp8
    17462       # if (c == '\r') break
    17463       3d/compare-eax-and 0xd/imm32/carriage-return
    17464       74/jump-if-= break/disp8
    17465       # if (c == '\n') break
    17466       3d/compare-eax-and 0xa/imm32/newline
    17467       74/jump-if-= break/disp8
    17468       # if (c == '(') break
    17469       3d/compare-eax-and 0x28/imm32/open-paren
    17470       0f 84/jump-if-= break/disp32
    17471       # if (c == ')') break
    17472       3d/compare-eax-and 0x29/imm32/close-paren
    17473       0f 84/jump-if-= break/disp32
    17474       # if (c == ',') break
    17475       3d/compare-eax-and 0x2c/imm32/comma
    17476       0f 84/jump-if-= break/disp32
    17477       # ++in->read
    17478       ff 0/subop/increment *(esi+4)
    17479       #
    17480       e9/jump loop/disp32
    17481     }
    17482 $next-mu-token:done:
    17483     # out->end = &in->data[in->read]
    17484     8b/-> *(esi+4) 1/r32/ecx
    17485     8d/copy-address *(esi+ecx+0xc) 0/r32/eax
    17486     89/<- *(edi+4) 0/r32/eax
    17487 $next-mu-token:end:
    17488     # . restore registers
    17489     5f/pop-to-edi
    17490     5e/pop-to-esi
    17491     59/pop-to-ecx
    17492     58/pop-to-eax
    17493     # . epilogue
    17494     89/<- %esp 5/r32/ebp
    17495     5d/pop-to-ebp
    17496     c3/return
    17497
    17498 pos-or-insert-slice:  # arr: (addr stream (addr array byte)), s: (addr slice) -> index/eax: int
    17499     # . prologue
    17500     55/push-ebp
    17501     89/<- %ebp 4/r32/esp
    17502     # if (pos-slice(arr, s) != -1) return it
    17503     (pos-slice *(ebp+8) *(ebp+0xc))  # => eax
    17504     3d/compare-eax-and -1/imm32
    17505     75/jump-if-!= $pos-or-insert-slice:end/disp8
    17506 $pos-or-insert-slice:insert:
    17507     # var s2/eax: (handle array byte)
    17508     68/push 0/imm32
    17509     68/push 0/imm32
    17510     89/<- %eax 4/r32/esp
    17511     (slice-to-string Heap *(ebp+0xc) %eax)
    17512     # throw away alloc-id
    17513     (lookup *eax *(eax+4))  # => eax
    17514     (write-int *(ebp+8) %eax)
    17515     (pos-slice *(ebp+8) *(ebp+0xc))  # => eax
    17516 $pos-or-insert-slice:end:
    17517     # . reclaim locals
    17518     81 0/subop/add %esp 8/imm32
    17519     # . epilogue
    17520     89/<- %esp 5/r32/ebp
    17521     5d/pop-to-ebp
    17522     c3/return
    17523
    17524 # return the index in an array of strings matching 's', -1 if not found
    17525 # index is denominated in elements, not bytes
    17526 pos-slice:  # arr: (addr stream (addr array byte)), s: (addr slice) -> index/eax: int
    17527     # . prologue
    17528     55/push-ebp
    17529     89/<- %ebp 4/r32/esp
    17530     # . save registers
    17531     51/push-ecx
    17532     52/push-edx
    17533     53/push-ebx
    17534     56/push-esi
    17535 #?     (write-buffered Stderr "pos-slice: ")
    17536 #?     (write-slice-buffered Stderr *(ebp+0xc))
    17537 #?     (write-buffered Stderr "\n")
    17538 #?     (flush Stderr)
    17539     # esi = arr
    17540     8b/-> *(ebp+8) 6/r32/esi
    17541     # var index/ecx: int = 0
    17542     b9/copy-to-ecx 0/imm32
    17543     # var curr/edx: (addr (addr array byte)) = arr->data
    17544     8d/copy-address *(esi+0xc) 2/r32/edx
    17545     # var max/ebx: (addr (addr array byte)) = &arr->data[arr->write]
    17546     8b/-> *esi 3/r32/ebx
    17547     8d/copy-address *(esi+ebx+0xc) 3/r32/ebx
    17548     {
    17549 #?       (write-buffered Stderr "  ")
    17550 #?       (write-int32-hex-buffered Stderr %ecx)
    17551 #?       (write-buffered Stderr "\n")
    17552 #?       (flush Stderr)
    17553       # if (curr >= max) return -1
    17554       39/compare %edx 3/r32/ebx
    17555       b8/copy-to-eax -1/imm32
    17556       73/jump-if-addr>= $pos-slice:end/disp8
    17557       # if (slice-equal?(s, *curr)) break
    17558       (slice-equal? *(ebp+0xc) *edx)  # => eax
    17559       3d/compare-eax-and 0/imm32/false
    17560       75/jump-if-!= break/disp8
    17561       # ++index
    17562       41/increment-ecx
    17563       # curr += 4
    17564       81 0/subop/add %edx 4/imm32
    17565       #
    17566       eb/jump loop/disp8
    17567     }
    17568     # return index
    17569     89/<- %eax 1/r32/ecx
    17570 $pos-slice:end:
    17571 #?     (write-buffered Stderr "=> ")
    17572 #?     (write-int32-hex-buffered Stderr %eax)
    17573 #?     (write-buffered Stderr "\n")
    17574     # . restore registers
    17575     5e/pop-to-esi
    17576     5b/pop-to-ebx
    17577     5a/pop-to-edx
    17578     59/pop-to-ecx
    17579     # . epilogue
    17580     89/<- %esp 5/r32/ebp
    17581     5d/pop-to-ebp
    17582     c3/return
    17583
    17584 test-parse-var-with-type:
    17585     # . prologue
    17586     55/push-ebp
    17587     89/<- %ebp 4/r32/esp
    17588     # setup
    17589     8b/-> *Primitive-type-ids 0/r32/eax
    17590     89/<- *Type-id 0/r32/eax  # stream-write
    17591     # (eax..ecx) = "x:"
    17592     b8/copy-to-eax "x:"/imm32
    17593     8b/-> *eax 1/r32/ecx
    17594     8d/copy-address *(eax+ecx+4) 1/r32/ecx
    17595     05/add-to-eax 4/imm32
    17596     # var slice/ecx: slice = {eax, ecx}
    17597     51/push-ecx
    17598     50/push-eax
    17599     89/<- %ecx 4/r32/esp
    17600     # _test-input-stream contains "int"
    17601     (clear-stream _test-input-stream)
    17602     (write _test-input-stream "int")
    17603     # var v/edx: (handle var)
    17604     68/push 0/imm32
    17605     68/push 0/imm32
    17606     89/<- %edx 4/r32/esp
    17607     #
    17608     (parse-var-with-type %ecx _test-input-stream %edx 0 Stderr 0)
    17609     # var v-addr/edx: (addr var) = lookup(v)
    17610     (lookup *edx *(edx+4))  # => eax
    17611     89/<- %edx 0/r32/eax
    17612     # check v-addr->name
    17613     (lookup *edx *(edx+4))  # Var-name Var-name => eax
    17614     (check-strings-equal %eax "x" "F - test-parse-var-with-type/name")
    17615     # check v-addr->type
    17616     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
    17617     (check-ints-equal *eax 1 "F - test-parse-var-with-type/type:0")  # Type-tree-is-atom
    17618     (check-ints-equal *(eax+4) 1 "F - test-parse-var-with-type/type:1")  # Type-tree-value
    17619     (check-ints-equal *(eax+0xc) 0 "F - test-parse-var-with-type/type:2")  # Type-tree-right
    17620     # . epilogue
    17621     89/<- %esp 5/r32/ebp
    17622     5d/pop-to-ebp
    17623     c3/return
    17624
    17625 test-parse-var-with-type-and-register:
    17626     # . prologue
    17627     55/push-ebp
    17628     89/<- %ebp 4/r32/esp
    17629     # setup
    17630     8b/-> *Primitive-type-ids 0/r32/eax
    17631     89/<- *Type-id 0/r32/eax  # stream-write
    17632     # (eax..ecx) = "x/eax:"
    17633     b8/copy-to-eax "x/eax:"/imm32
    17634     8b/-> *eax 1/r32/ecx
    17635     8d/copy-address *(eax+ecx+4) 1/r32/ecx
    17636     05/add-to-eax 4/imm32
    17637     # var slice/ecx: slice = {eax, ecx}
    17638     51/push-ecx
    17639     50/push-eax
    17640     89/<- %ecx 4/r32/esp
    17641     # _test-input-stream contains "int"
    17642     (clear-stream _test-input-stream)
    17643     (write _test-input-stream "int")
    17644     # var v/edx: (handle var)
    17645     68/push 0/imm32
    17646     68/push 0/imm32
    17647     89/<- %edx 4/r32/esp
    17648     #
    17649     (parse-var-with-type %ecx _test-input-stream %edx 0 Stderr 0)
    17650     # var v-addr/edx: (addr var) = lookup(v)
    17651     (lookup *edx *(edx+4))  # => eax
    17652     89/<- %edx 0/r32/eax
    17653     # check v-addr->name
    17654     (lookup *edx *(edx+4))  # Var-name Var-name => eax
    17655     (check-strings-equal %eax "x" "F - test-parse-var-with-type-and-register/name")
    17656     # check v-addr->register
    17657     (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
    17658     (check-strings-equal %eax "eax" "F - test-parse-var-with-type-and-register/register")
    17659     # check v-addr->type
    17660     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
    17661     (check-ints-equal *eax 1 "F - test-parse-var-with-type-and-register/type:0")  # Type-tree-is-atom
    17662     (check-ints-equal *(eax+4) 1 "F - test-parse-var-with-type-and-register/type:1")  # Type-tree-left
    17663     (check-ints-equal *(eax+0xc) 0 "F - test-parse-var-with-type-and-register/type:2")  # Type-tree-right
    17664     # . epilogue
    17665     89/<- %esp 5/r32/ebp
    17666     5d/pop-to-ebp
    17667     c3/return
    17668
    17669 test-parse-var-with-trailing-characters:
    17670     # . prologue
    17671     55/push-ebp
    17672     89/<- %ebp 4/r32/esp
    17673     # setup
    17674     8b/-> *Primitive-type-ids 0/r32/eax
    17675     89/<- *Type-id 0/r32/eax  # stream-write
    17676     # (eax..ecx) = "x:"
    17677     b8/copy-to-eax "x:"/imm32
    17678     8b/-> *eax 1/r32/ecx
    17679     8d/copy-address *(eax+ecx+4) 1/r32/ecx
    17680     05/add-to-eax 4/imm32
    17681     # var slice/ecx: slice = {eax, ecx}
    17682     51/push-ecx
    17683     50/push-eax
    17684     89/<- %ecx 4/r32/esp
    17685     # _test-input-stream contains "int,"
    17686     (clear-stream _test-input-stream)
    17687     (write _test-input-stream "int,")
    17688     # var v/edx: (handle var)
    17689     68/push 0/imm32
    17690     68/push 0/imm32
    17691     89/<- %edx 4/r32/esp
    17692     #
    17693     (parse-var-with-type %ecx _test-input-stream %edx 0 Stderr 0)
    17694     # var v-addr/edx: (addr var) = lookup(v)
    17695     (lookup *edx *(edx+4))  # => eax
    17696     89/<- %edx 0/r32/eax
    17697     # check v-addr->name
    17698     (lookup *edx *(edx+4))  # Var-name Var-name => eax
    17699     (check-strings-equal %eax "x" "F - test-parse-var-with-trailing-characters/name")
    17700     # check v-addr->register
    17701     (check-ints-equal *(edx+0x18) 0 "F - test-parse-var-with-trailing-characters/register")  # Var-register
    17702     # check v-addr->type
    17703     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
    17704     (check-ints-equal *eax 1 "F - test-parse-var-with-trailing-characters/type:0")  # Type-tree-is-atom
    17705     (check-ints-equal *(eax+4) 1 "F - test-parse-var-with-trailing-characters/type:1")  # Type-tree-left
    17706     (check-ints-equal *(eax+0xc) 0 "F - test-parse-var-with-trailing-characters/type:1")  # Type-tree-right
    17707     # . epilogue
    17708     89/<- %esp 5/r32/ebp
    17709     5d/pop-to-ebp
    17710     c3/return
    17711
    17712 test-parse-var-with-register-and-trailing-characters:
    17713     # . prologue
    17714     55/push-ebp
    17715     89/<- %ebp 4/r32/esp
    17716     # setup
    17717     8b/-> *Primitive-type-ids 0/r32/eax
    17718     89/<- *Type-id 0/r32/eax  # stream-write
    17719     # (eax..ecx) = "x/eax:"
    17720     b8/copy-to-eax "x/eax:"/imm32
    17721     8b/-> *eax 1/r32/ecx
    17722     8d/copy-address *(eax+ecx+4) 1/r32/ecx
    17723     05/add-to-eax 4/imm32
    17724     # var slice/ecx: slice = {eax, ecx}
    17725     51/push-ecx
    17726     50/push-eax
    17727     89/<- %ecx 4/r32/esp
    17728     # _test-input-stream contains "int,"
    17729     (clear-stream _test-input-stream)
    17730     (write _test-input-stream "int,")
    17731     # var v/edx: (handle var)
    17732     68/push 0/imm32
    17733     68/push 0/imm32
    17734     89/<- %edx 4/r32/esp
    17735     #
    17736     (parse-var-with-type %ecx _test-input-stream %edx 0 Stderr 0)
    17737     # var v-addr/edx: (addr var) = lookup(v)
    17738     (lookup *edx *(edx+4))  # => eax
    17739     89/<- %edx 0/r32/eax
    17740     # check v-addr->name
    17741     (lookup *edx *(edx+4))  # Var-name Var-name => eax
    17742     (check-strings-equal %eax "x" "F - test-parse-var-with-register-and-trailing-characters/name")
    17743     # check v-addr->register
    17744     (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
    17745     (check-strings-equal %eax "eax" "F - test-parse-var-with-register-and-trailing-characters/register")
    17746     # check v-addr->type
    17747     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
    17748     (check-ints-equal *eax 1 "F - test-parse-var-with-register-and-trailing-characters/type:0")  # Type-tree-is-atom
    17749     (check-ints-equal *(eax+4) 1 "F - test-parse-var-with-register-and-trailing-characters/type:1")  # Type-tree-left
    17750     (check-ints-equal *(eax+0xc) 0 "F - test-parse-var-with-register-and-trailing-characters/type:2")  # Type-tree-right
    17751     # . epilogue
    17752     89/<- %esp 5/r32/ebp
    17753     5d/pop-to-ebp
    17754     c3/return
    17755
    17756 test-parse-var-with-compound-type:
    17757     # . prologue
    17758     55/push-ebp
    17759     89/<- %ebp 4/r32/esp
    17760     # setup
    17761     8b/-> *Primitive-type-ids 0/r32/eax
    17762     89/<- *Type-id 0/r32/eax  # stream-write
    17763     # (eax..ecx) = "x:"
    17764     b8/copy-to-eax "x:"/imm32
    17765     8b/-> *eax 1/r32/ecx
    17766     8d/copy-address *(eax+ecx+4) 1/r32/ecx
    17767     05/add-to-eax 4/imm32
    17768     # var slice/ecx: slice = {eax, ecx}
    17769     51/push-ecx
    17770     50/push-eax
    17771     89/<- %ecx 4/r32/esp
    17772     # _test-input-stream contains "(addr int)"
    17773     (clear-stream _test-input-stream)
    17774     (write _test-input-stream "(addr int)")
    17775     # var v/edx: (handle var)
    17776     68/push 0/imm32
    17777     68/push 0/imm32
    17778     89/<- %edx 4/r32/esp
    17779     #
    17780     (parse-var-with-type %ecx _test-input-stream %edx 0 Stderr 0)
    17781     # var v-addr/edx: (addr var) = lookup(v)
    17782     (lookup *edx *(edx+4))  # => eax
    17783     89/<- %edx 0/r32/eax
    17784     # check v-addr->name
    17785     (lookup *edx *(edx+4))  # Var-name Var-name => eax
    17786     (check-strings-equal %eax "x" "F - test-parse-var-with-compound-type/name")
    17787     # check v-addr->register
    17788     (check-ints-equal *(edx+0x18) 0 "F - test-parse-var-with-compound-type/register")  # Var-register
    17789     # - check v-addr->type
    17790     # var type/edx: (addr type-tree) = var->type
    17791     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
    17792     89/<- %edx 0/r32/eax
    17793     # type is a non-atom
    17794     (check-ints-equal *edx 0 "F - test-parse-var-with-compound-type/type:0")  # Type-tree-is-atom
    17795     # type->left == atom(addr)
    17796     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
    17797     (check-ints-equal *eax 1 "F - test-parse-var-with-compound-type/type:1")  # Type-tree-is-atom
    17798     (check-ints-equal *(eax+4) 2 "F - test-parse-var-with-compound-type/type:2")  # Type-tree-value
    17799     # type->right->left == atom(int)
    17800     (lookup *(edx+0xc) *(edx+0x10))  # Type-tree-right Type-tree-right => eax
    17801     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    17802     (check-ints-equal *eax 1 "F - test-parse-var-with-compound-type/type:3")  # Type-tree-is-atom
    17803     (check-ints-equal *(eax+4) 1 "F - test-parse-var-with-compound-type/type:4")  # Type-tree-value
    17804     # type->right->right == null
    17805     (check-ints-equal *(eax+0xc) 0 "F - test-parse-var-with-compound-type/type:5")  # Type-tree-right
    17806     # . epilogue
    17807     89/<- %esp 5/r32/ebp
    17808     5d/pop-to-ebp
    17809     c3/return
    17810
    17811 # identifier starts with a letter or '$' or '_'
    17812 # no constraints at the moment on later letters
    17813 # all we really want to do so far is exclude '{', '}' and '->'
    17814 identifier?:  # in: (addr slice) -> result/eax: boolean
    17815     # . prologue
    17816     55/push-ebp
    17817     89/<- %ebp 4/r32/esp
    17818     # if (slice-empty?(in)) return false
    17819     (slice-empty? *(ebp+8))  # => eax
    17820     3d/compare-eax-and 0/imm32/false
    17821     75/jump-if-!= $identifier?:false/disp8
    17822     # var c/eax: byte = *in->start
    17823     8b/-> *(ebp+8) 0/r32/eax
    17824     8b/-> *eax 0/r32/eax
    17825     8a/copy-byte *eax 0/r32/AL
    17826     25/and-eax-with 0xff/imm32
    17827     # if (c == '$') return true
    17828     3d/compare-eax-and 0x24/imm32/$
    17829     74/jump-if-= $identifier?:true/disp8
    17830     # if (c == '_') return true
    17831     3d/compare-eax-and 0x5f/imm32/_
    17832     74/jump-if-= $identifier?:true/disp8
    17833     # drop case
    17834     25/and-eax-with 0x5f/imm32
    17835     # if (c < 'A') return false
    17836     3d/compare-eax-and 0x41/imm32/A
    17837     7c/jump-if-< $identifier?:false/disp8
    17838     # if (c > 'Z') return false
    17839     3d/compare-eax-and 0x5a/imm32/Z
    17840     7f/jump-if-> $identifier?:false/disp8
    17841     # otherwise return true
    17842 $identifier?:true:
    17843     b8/copy-to-eax 1/imm32/true
    17844     eb/jump $identifier?:end/disp8
    17845 $identifier?:false:
    17846     b8/copy-to-eax 0/imm32/false
    17847 $identifier?:end:
    17848     # . epilogue
    17849     89/<- %esp 5/r32/ebp
    17850     5d/pop-to-ebp
    17851     c3/return
    17852
    17853 test-is-identifier-dollar:
    17854     # . prologue
    17855     55/push-ebp
    17856     89/<- %ebp 4/r32/esp
    17857     # (eax..ecx) = "$a"
    17858     b8/copy-to-eax "$a"/imm32
    17859     8b/-> *eax 1/r32/ecx
    17860     8d/copy-address *(eax+ecx+4) 1/r32/ecx
    17861     05/add-to-eax 4/imm32
    17862     # var slice/ecx: slice = {eax, ecx}
    17863     51/push-ecx
    17864     50/push-eax
    17865     89/<- %ecx 4/r32/esp
    17866     #
    17867     (identifier? %ecx)
    17868     (check-ints-equal %eax 1 "F - test-is-identifier-dollar")
    17869     # . epilogue
    17870     89/<- %esp 5/r32/ebp
    17871     5d/pop-to-ebp
    17872     c3/return
    17873
    17874 test-is-identifier-underscore:
    17875     # . prologue
    17876     55/push-ebp
    17877     89/<- %ebp 4/r32/esp
    17878     # (eax..ecx) = "_a"
    17879     b8/copy-to-eax "_a"/imm32
    17880     8b/-> *eax 1/r32/ecx
    17881     8d/copy-address *(eax+ecx+4) 1/r32/ecx
    17882     05/add-to-eax 4/imm32
    17883     # var slice/ecx: slice = {eax, ecx}
    17884     51/push-ecx
    17885     50/push-eax
    17886     89/<- %ecx 4/r32/esp
    17887     #
    17888     (identifier? %ecx)
    17889     (check-ints-equal %eax 1 "F - test-is-identifier-underscore")
    17890     # . epilogue
    17891     89/<- %esp 5/r32/ebp
    17892     5d/pop-to-ebp
    17893     c3/return
    17894
    17895 test-is-identifier-a:
    17896     # . prologue
    17897     55/push-ebp
    17898     89/<- %ebp 4/r32/esp
    17899     # (eax..ecx) = "a$"
    17900     b8/copy-to-eax "a$"/imm32
    17901     8b/-> *eax 1/r32/ecx
    17902     8d/copy-address *(eax+ecx+4) 1/r32/ecx
    17903     05/add-to-eax 4/imm32
    17904     # var slice/ecx: slice = {eax, ecx}
    17905     51/push-ecx
    17906     50/push-eax
    17907     89/<- %ecx 4/r32/esp
    17908     #
    17909     (identifier? %ecx)
    17910     (check-ints-equal %eax 1 "F - test-is-identifier-a")
    17911     # . epilogue
    17912     89/<- %esp 5/r32/ebp
    17913     5d/pop-to-ebp
    17914     c3/return
    17915
    17916 test-is-identifier-z:
    17917     # . prologue
    17918     55/push-ebp
    17919     89/<- %ebp 4/r32/esp
    17920     # (eax..ecx) = "z$"
    17921     b8/copy-to-eax "z$"/imm32
    17922     8b/-> *eax 1/r32/ecx
    17923     8d/copy-address *(eax+ecx+4) 1/r32/ecx
    17924     05/add-to-eax 4/imm32
    17925     # var slice/ecx: slice = {eax, ecx}
    17926     51/push-ecx
    17927     50/push-eax
    17928     89/<- %ecx 4/r32/esp
    17929     #
    17930     (identifier? %ecx)
    17931     (check-ints-equal %eax 1 "F - test-is-identifier-z")
    17932     # . epilogue
    17933     89/<- %esp 5/r32/ebp
    17934     5d/pop-to-ebp
    17935     c3/return
    17936
    17937 test-is-identifier-A:
    17938     # . prologue
    17939     55/push-ebp
    17940     89/<- %ebp 4/r32/esp
    17941     # (eax..ecx) = "A$"
    17942     b8/copy-to-eax "A$"/imm32
    17943     8b/-> *eax 1/r32/ecx
    17944     8d/copy-address *(eax+ecx+4) 1/r32/ecx
    17945     05/add-to-eax 4/imm32
    17946     # var slice/ecx: slice = {eax, ecx}
    17947     51/push-ecx
    17948     50/push-eax
    17949     89/<- %ecx 4/r32/esp
    17950     #
    17951     (identifier? %ecx)
    17952     (check-ints-equal %eax 1 "F - test-is-identifier-A")
    17953     # . epilogue
    17954     89/<- %esp 5/r32/ebp
    17955     5d/pop-to-ebp
    17956     c3/return
    17957
    17958 test-is-identifier-Z:
    17959     # . prologue
    17960     55/push-ebp
    17961     89/<- %ebp 4/r32/esp
    17962     # (eax..ecx) = "Z$"
    17963     b8/copy-to-eax "Z$"/imm32
    17964     8b/-> *eax 1/r32/ecx
    17965     8d/copy-address *(eax+ecx+4) 1/r32/ecx
    17966     05/add-to-eax 4/imm32
    17967     # var slice/ecx: slice = {eax, ecx}
    17968     51/push-ecx
    17969     50/push-eax
    17970     89/<- %ecx 4/r32/esp
    17971     #
    17972     (identifier? %ecx)
    17973     (check-ints-equal %eax 1 "F - test-is-identifier-Z")
    17974     # . epilogue
    17975     89/<- %esp 5/r32/ebp
    17976     5d/pop-to-ebp
    17977     c3/return
    17978
    17979 test-is-identifier-at:
    17980     # character before 'A' is invalid
    17981     # . prologue
    17982     55/push-ebp
    17983     89/<- %ebp 4/r32/esp
    17984     # (eax..ecx) = "@a"
    17985     b8/copy-to-eax "@a"/imm32
    17986     8b/-> *eax 1/r32/ecx
    17987     8d/copy-address *(eax+ecx+4) 1/r32/ecx
    17988     05/add-to-eax 4/imm32
    17989     # var slice/ecx: slice = {eax, ecx}
    17990     51/push-ecx
    17991     50/push-eax
    17992     89/<- %ecx 4/r32/esp
    17993     #
    17994     (identifier? %ecx)
    17995     (check-ints-equal %eax 0 "F - test-is-identifier-@")
    17996     # . epilogue
    17997     89/<- %esp 5/r32/ebp
    17998     5d/pop-to-ebp
    17999     c3/return
    18000
    18001 test-is-identifier-square-bracket:
    18002     # character after 'Z' is invalid
    18003     # . prologue
    18004     55/push-ebp
    18005     89/<- %ebp 4/r32/esp
    18006     # (eax..ecx) = "[a"
    18007     b8/copy-to-eax "[a"/imm32
    18008     8b/-> *eax 1/r32/ecx
    18009     8d/copy-address *(eax+ecx+4) 1/r32/ecx
    18010     05/add-to-eax 4/imm32
    18011     # var slice/ecx: slice = {eax, ecx}
    18012     51/push-ecx
    18013     50/push-eax
    18014     89/<- %ecx 4/r32/esp
    18015     #
    18016     (identifier? %ecx)
    18017     (check-ints-equal %eax 0 "F - test-is-identifier-@")
    18018     # . epilogue
    18019     89/<- %esp 5/r32/ebp
    18020     5d/pop-to-ebp
    18021     c3/return
    18022
    18023 test-is-identifier-backtick:
    18024     # character before 'a' is invalid
    18025     # . prologue
    18026     55/push-ebp
    18027     89/<- %ebp 4/r32/esp
    18028     # (eax..ecx) = "`a"
    18029     b8/copy-to-eax "`a"/imm32
    18030     8b/-> *eax 1/r32/ecx
    18031     8d/copy-address *(eax+ecx+4) 1/r32/ecx
    18032     05/add-to-eax 4/imm32
    18033     # var slice/ecx: slice = {eax, ecx}
    18034     51/push-ecx
    18035     50/push-eax
    18036     89/<- %ecx 4/r32/esp
    18037     #
    18038     (identifier? %ecx)
    18039     (check-ints-equal %eax 0 "F - test-is-identifier-backtick")
    18040     # . epilogue
    18041     89/<- %esp 5/r32/ebp
    18042     5d/pop-to-ebp
    18043     c3/return
    18044
    18045 test-is-identifier-curly-brace-open:
    18046     # character after 'z' is invalid; also used for blocks
    18047     # . prologue
    18048     55/push-ebp
    18049     89/<- %ebp 4/r32/esp
    18050     # (eax..ecx) = "{a"
    18051     b8/copy-to-eax "{a"/imm32
    18052     8b/-> *eax 1/r32/ecx
    18053     8d/copy-address *(eax+ecx+4) 1/r32/ecx
    18054     05/add-to-eax 4/imm32
    18055     # var slice/ecx: slice = {eax, ecx}
    18056     51/push-ecx
    18057     50/push-eax
    18058     89/<- %ecx 4/r32/esp
    18059     #
    18060     (identifier? %ecx)
    18061     (check-ints-equal %eax 0 "F - test-is-identifier-curly-brace-open")
    18062     # . epilogue
    18063     89/<- %esp 5/r32/ebp
    18064     5d/pop-to-ebp
    18065     c3/return
    18066
    18067 test-is-identifier-curly-brace-close:
    18068     # . prologue
    18069     55/push-ebp
    18070     89/<- %ebp 4/r32/esp
    18071     # (eax..ecx) = "}a"
    18072     b8/copy-to-eax "}a"/imm32
    18073     8b/-> *eax 1/r32/ecx
    18074     8d/copy-address *(eax+ecx+4) 1/r32/ecx
    18075     05/add-to-eax 4/imm32
    18076     # var slice/ecx: slice = {eax, ecx}
    18077     51/push-ecx
    18078     50/push-eax
    18079     89/<- %ecx 4/r32/esp
    18080     #
    18081     (identifier? %ecx)
    18082     (check-ints-equal %eax 0 "F - test-is-identifier-curly-brace-close")
    18083     # . epilogue
    18084     89/<- %esp 5/r32/ebp
    18085     5d/pop-to-ebp
    18086     c3/return
    18087
    18088 test-is-identifier-hyphen:
    18089     # disallow leading '-' since '->' has special meaning
    18090     # . prologue
    18091     55/push-ebp
    18092     89/<- %ebp 4/r32/esp
    18093     # (eax..ecx) = "-a"
    18094     b8/copy-to-eax "-a"/imm32
    18095     8b/-> *eax 1/r32/ecx
    18096     8d/copy-address *(eax+ecx+4) 1/r32/ecx
    18097     05/add-to-eax 4/imm32
    18098     # var slice/ecx: slice = {eax, ecx}
    18099     51/push-ecx
    18100     50/push-eax
    18101     89/<- %ecx 4/r32/esp
    18102     #
    18103     (identifier? %ecx)
    18104     (check-ints-equal %eax 0 "F - test-is-identifier-hyphen")
    18105     # . epilogue
    18106     89/<- %esp 5/r32/ebp
    18107     5d/pop-to-ebp
    18108     c3/return
    18109
    18110 populate-mu-function-body:  # in: (addr buffered-file), out: (addr function), vars: (addr stack live-var), err: (addr buffered-file), ed: (addr exit-descriptor)
    18111     # . prologue
    18112     55/push-ebp
    18113     89/<- %ebp 4/r32/esp
    18114     # . save registers
    18115     50/push-eax
    18116     56/push-esi
    18117     57/push-edi
    18118     # esi = in
    18119     8b/-> *(ebp+8) 6/r32/esi
    18120     # edi = out
    18121     8b/-> *(ebp+0xc) 7/r32/edi
    18122     # initialize some global state
    18123     c7 0/subop/copy *Curr-block-depth 1/imm32
    18124     # parse-mu-block(in, vars, out, out->body)
    18125     8d/copy-address *(edi+0x18) 0/r32/eax  # Function-body
    18126     (parse-mu-block %esi *(ebp+0x10) %edi %eax *(ebp+0x14) *(ebp+0x18))
    18127 $populate-mu-function-body:end:
    18128     # . restore registers
    18129     5f/pop-to-edi
    18130     5e/pop-to-esi
    18131     58/pop-to-eax
    18132     # . epilogue
    18133     89/<- %esp 5/r32/ebp
    18134     5d/pop-to-ebp
    18135     c3/return
    18136
    18137 # parses a block, assuming that the leading '{' has already been read by the caller
    18138 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)
    18139     # pseudocode:
    18140     #   var line: (stream byte 512)
    18141     #   var word-slice: slice
    18142     #   allocate(Heap, Stmt-size, out)
    18143     #   var out-addr: (addr block) = lookup(*out)
    18144     #   out-addr->tag = 0/block
    18145     #   out-addr->var = some unique name
    18146     #   push(vars, {out-addr->var, false})
    18147     #   while true                                  # line loop
    18148     #     clear-stream(line)
    18149     #     read-line-buffered(in, line)
    18150     #     if (line->write == 0) break               # end of file
    18151     #     word-slice = next-mu-token(line)
    18152     #     if slice-empty?(word-slice)               # end of line
    18153     #       continue
    18154     #     else if slice-starts-with?(word-slice, "#")
    18155     #       continue
    18156     #     else if slice-equal?(word-slice, "{")
    18157     #       assert(no-tokens-in(line))
    18158     #       block = parse-mu-block(in, vars, fn)
    18159     #       append-to-block(out-addr, block)
    18160     #     else if slice-equal?(word-slice, "}")
    18161     #       break
    18162     #     else if slice-ends-with?(word-slice, ":")
    18163     #       # TODO: error-check the rest of 'line'
    18164     #       --word-slice->end to skip ':'
    18165     #       named-block = parse-mu-named-block(word-slice, in, vars, fn)
    18166     #       append-to-block(out-addr, named-block)
    18167     #     else if slice-equal?(word-slice, "var")
    18168     #       var-def = parse-mu-var-def(line, vars, fn)
    18169     #       append-to-block(out-addr, var-def)
    18170     #     else
    18171     #       stmt = parse-mu-stmt(line, vars, fn)
    18172     #       append-to-block(out-addr, stmt)
    18173     #   pop(vars)
    18174     #
    18175     # . prologue
    18176     55/push-ebp
    18177     89/<- %ebp 4/r32/esp
    18178     # . save registers
    18179     50/push-eax
    18180     51/push-ecx
    18181     52/push-edx
    18182     53/push-ebx
    18183     57/push-edi
    18184     # var line/ecx: (stream byte 512)
    18185     81 5/subop/subtract %esp 0x200/imm32
    18186     68/push 0x200/imm32/size
    18187     68/push 0/imm32/read
    18188     68/push 0/imm32/write
    18189     89/<- %ecx 4/r32/esp
    18190     # var word-slice/edx: slice
    18191     68/push 0/imm32/end
    18192     68/push 0/imm32/start
    18193     89/<- %edx 4/r32/esp
    18194     # allocate into out
    18195     (allocate Heap *Stmt-size *(ebp+0x14))
    18196     # var out-addr/edi: (addr block) = lookup(*out)
    18197     8b/-> *(ebp+0x14) 7/r32/edi
    18198     (lookup *edi *(edi+4))  # => eax
    18199     89/<- %edi 0/r32/eax
    18200     # out-addr->tag is 0 (block) by default
    18201     # set out-addr->var
    18202     8d/copy-address *(edi+0xc) 0/r32/eax  # Block-var
    18203     (new-block-name *(ebp+0x10) %eax)
    18204     # push(vars, out-addr->var)
    18205     (push *(ebp+0xc) *(edi+0xc))  # Block-var
    18206     (push *(ebp+0xc) *(edi+0x10))  # Block-var
    18207     (push *(ebp+0xc) 0)  # false
    18208     # increment *Curr-block-depth
    18209     ff 0/subop/increment *Curr-block-depth
    18210     {
    18211 $parse-mu-block:line-loop:
    18212       # line = read-line-buffered(in)
    18213       (clear-stream %ecx)
    18214       (read-line-buffered *(ebp+8) %ecx)
    18215 #?       (write-buffered Stderr "line: ")
    18216 #?       (write-stream-data Stderr %ecx)
    18217 #? #?       (write-buffered Stderr Newline)  # line has its own newline
    18218 #?       (flush Stderr)
    18219 #?       (rewind-stream %ecx)
    18220       # if (line->write == 0) break
    18221       81 7/subop/compare *ecx 0/imm32
    18222       0f 84/jump-if-= break/disp32
    18223 #?       (write-buffered Stderr "vars:\n")
    18224 #?       (dump-vars *(ebp+0xc))
    18225       # word-slice = next-mu-token(line)
    18226       (next-mu-token %ecx %edx)
    18227 #?       (write-buffered Stderr "word: ")
    18228 #?       (write-slice-buffered Stderr %edx)
    18229 #?       (write-buffered Stderr Newline)
    18230 #?       (flush Stderr)
    18231       # if slice-empty?(word-slice) continue
    18232       (slice-empty? %edx)
    18233       3d/compare-eax-and 0/imm32/false
    18234       0f 85/jump-if-!= loop/disp32
    18235       # if (slice-starts-with?(word-slice, '#') continue
    18236       # . eax = *word-slice->start
    18237       8b/-> *edx 0/r32/eax
    18238       8a/copy-byte *eax 0/r32/AL
    18239       25/and-eax-with 0xff/imm32
    18240       # . if (eax == '#') continue
    18241       3d/compare-eax-and 0x23/imm32/hash
    18242       0f 84/jump-if-= loop/disp32
    18243       # if slice-equal?(word-slice, "{")
    18244       {
    18245 $parse-mu-block:check-for-block:
    18246         (slice-equal? %edx "{")
    18247         3d/compare-eax-and 0/imm32/false
    18248         74/jump-if-= break/disp8
    18249         (check-no-tokens-left %ecx)
    18250         # parse new block and append
    18251         # . var tmp/eax: (handle block)
    18252         68/push 0/imm32
    18253         68/push 0/imm32
    18254         89/<- %eax 4/r32/esp
    18255         # .
    18256         (parse-mu-block *(ebp+8) *(ebp+0xc) *(ebp+0x10) %eax *(ebp+0x18) *(ebp+0x1c))
    18257         (append-to-block Heap %edi  *eax *(eax+4))
    18258         # . reclaim tmp
    18259         81 0/subop/add %esp 8/imm32
    18260         # .
    18261         e9/jump $parse-mu-block:line-loop/disp32
    18262       }
    18263       # if slice-equal?(word-slice, "}") break
    18264 $parse-mu-block:check-for-end:
    18265       (slice-equal? %edx "}")
    18266       3d/compare-eax-and 0/imm32/false
    18267       0f 85/jump-if-!= break/disp32
    18268       # if slice-ends-with?(word-slice, ":") parse named block and append
    18269       {
    18270 $parse-mu-block:check-for-named-block:
    18271         # . eax = *(word-slice->end-1)
    18272         8b/-> *(edx+4) 0/r32/eax
    18273         48/decrement-eax
    18274         8a/copy-byte *eax 0/r32/AL
    18275         25/and-eax-with 0xff/imm32
    18276         # . if (eax != ':') break
    18277         3d/compare-eax-and 0x3a/imm32/colon
    18278         0f 85/jump-if-!= break/disp32
    18279         # TODO: error-check the rest of 'line'
    18280         #
    18281         # skip ':'
    18282         ff 1/subop/decrement *(edx+4)  # Slice-end
    18283         # var tmp/eax: (handle block)
    18284         68/push 0/imm32
    18285         68/push 0/imm32
    18286         89/<- %eax 4/r32/esp
    18287         #
    18288         (parse-mu-named-block %edx *(ebp+8) *(ebp+0xc) *(ebp+0x10) %eax *(ebp+0x18) *(ebp+0x1c))
    18289         (append-to-block Heap %edi  *eax *(eax+4))
    18290         # reclaim tmp
    18291         81 0/subop/add %esp 8/imm32
    18292         #
    18293         e9/jump $parse-mu-block:line-loop/disp32
    18294       }
    18295       # if slice-equal?(word-slice, "var")
    18296       {
    18297 $parse-mu-block:check-for-var:
    18298         (slice-equal? %edx "var")
    18299         3d/compare-eax-and 0/imm32/false
    18300         74/jump-if-= break/disp8
    18301         # var tmp/eax: (handle block)
    18302         68/push 0/imm32
    18303         68/push 0/imm32
    18304         89/<- %eax 4/r32/esp
    18305         #
    18306         (parse-mu-var-def %ecx *(ebp+0xc) %eax *(ebp+0x10) *(ebp+0x18) *(ebp+0x1c))
    18307         (append-to-block Heap %edi  *eax *(eax+4))
    18308         # reclaim tmp
    18309         81 0/subop/add %esp 8/imm32
    18310         #
    18311         e9/jump $parse-mu-block:line-loop/disp32
    18312       }
    18313 $parse-mu-block:regular-stmt:
    18314       # otherwise
    18315       # var tmp/eax: (handle block)
    18316       68/push 0/imm32
    18317       68/push 0/imm32
    18318       89/<- %eax 4/r32/esp
    18319       #
    18320       (parse-mu-stmt %ecx *(ebp+0xc) *(ebp+0x10) %eax *(ebp+0x18) *(ebp+0x1c))
    18321       (append-to-block Heap %edi  *eax *(eax+4))
    18322       # reclaim tmp
    18323       81 0/subop/add %esp 8/imm32
    18324       #
    18325       e9/jump loop/disp32
    18326     } # end line loop
    18327     (clean-up-blocks *(ebp+0xc) *Curr-block-depth *(ebp+0x10))
    18328     # decrement *Curr-block-depth
    18329     ff 1/subop/decrement *Curr-block-depth
    18330     # pop(vars)
    18331     (pop *(ebp+0xc))  # => eax
    18332     (pop *(ebp+0xc))  # => eax
    18333     (pop *(ebp+0xc))  # => eax
    18334 $parse-mu-block:end:
    18335     # . reclaim locals
    18336     81 0/subop/add %esp 0x214/imm32
    18337     # . restore registers
    18338     5f/pop-to-edi
    18339     5b/pop-to-ebx
    18340     5a/pop-to-edx
    18341     59/pop-to-ecx
    18342     58/pop-to-eax
    18343     # . epilogue
    18344     89/<- %esp 5/r32/ebp
    18345     5d/pop-to-ebp
    18346     c3/return
    18347
    18348 $parse-mu-block:abort:
    18349     # error("'{' or '}' should be on its own line, but got '")
    18350     (write-buffered *(ebp+0x18) "'{' or '}' should be on its own line, but got '")
    18351     (rewind-stream %ecx)
    18352     (write-stream-data *(ebp+0x18) %ecx)
    18353     (write-buffered *(ebp+0x18) "'\n")
    18354     (flush *(ebp+0x18))
    18355     (stop *(ebp+0x1c) 1)
    18356     # never gets here
    18357
    18358 new-block-name:  # fn: (addr function), out: (addr handle var)
    18359     # . prologue
    18360     55/push-ebp
    18361     89/<- %ebp 4/r32/esp
    18362     # . save registers
    18363     50/push-eax
    18364     51/push-ecx
    18365     52/push-edx
    18366     # var n/ecx: int = len(fn->name) + 10 for an int + 2 for '$:'
    18367     8b/-> *(ebp+8) 0/r32/eax
    18368     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    18369     8b/-> *eax 0/r32/eax  # String-size
    18370     05/add-to-eax 0xd/imm32  # 10 + 2 for '$:'
    18371     89/<- %ecx 0/r32/eax
    18372     # var name/edx: (stream byte n)
    18373     29/subtract-from %esp 1/r32/ecx
    18374     ff 6/subop/push %ecx
    18375     68/push 0/imm32/read
    18376     68/push 0/imm32/write
    18377     89/<- %edx 4/r32/esp
    18378     (clear-stream %edx)
    18379     # eax = fn->name
    18380     8b/-> *(ebp+8) 0/r32/eax
    18381     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    18382     # construct result using Next-block-index (and increment it)
    18383     (write %edx "$")
    18384     (write %edx %eax)
    18385     (write %edx ":")
    18386     (write-int32-hex %edx *Next-block-index)
    18387     ff 0/subop/increment *Next-block-index
    18388     # var s/eax: slice = {name->data, name->data + name->write}  (clobbering edx)
    18389     # . eax = name->write
    18390     8b/-> *edx 0/r32/eax
    18391     # . edx = name->data
    18392     8d/copy-address *(edx+0xc) 2/r32/edx
    18393     # . eax = name->write + name->data
    18394     01/add-to %eax 2/r32/edx
    18395     # . push {edx, eax}
    18396     ff 6/subop/push %eax
    18397     ff 6/subop/push %edx
    18398     89/<- %eax 4/r32/esp
    18399     # out = new literal(s)
    18400     (new-literal Heap %eax *(ebp+0xc))
    18401 #?     8b/-> *(ebp+0xc) 0/r32/eax
    18402 #?     (write-buffered Stderr "type allocid in caller after new-literal: ")
    18403 #?     (write-int32-hex-buffered Stderr *(eax+8))
    18404 #?     (write-buffered Stderr " for var ")
    18405 #?     (write-int32-hex-buffered Stderr %eax)
    18406 #?     (write-buffered Stderr Newline)
    18407 #?     (flush Stderr)
    18408 $new-block-name:end:
    18409     # . reclaim locals
    18410     81 0/subop/add %ecx 0xc/imm32  # name.{read/write/len}
    18411     81 0/subop/add %ecx 8/imm32  # slice
    18412     01/add-to %esp 1/r32/ecx
    18413     # . restore registers
    18414     5a/pop-to-edx
    18415     59/pop-to-ecx
    18416     58/pop-to-eax
    18417     # . epilogue
    18418     89/<- %esp 5/r32/ebp
    18419     5d/pop-to-ebp
    18420     c3/return
    18421
    18422 check-no-tokens-left:  # line: (addr stream byte)
    18423     # . prologue
    18424     55/push-ebp
    18425     89/<- %ebp 4/r32/esp
    18426     # . save registers
    18427     50/push-eax
    18428     51/push-ecx
    18429     # var s/ecx: slice
    18430     68/push 0/imm32/end
    18431     68/push 0/imm32/start
    18432     89/<- %ecx 4/r32/esp
    18433     #
    18434     (next-mu-token *(ebp+8) %ecx)
    18435     # if slice-empty?(s) return
    18436     (slice-empty? %ecx)
    18437     3d/compare-eax-and 0/imm32/false
    18438     75/jump-if-!= $check-no-tokens-left:end/disp8
    18439     # if (slice-starts-with?(s, '#') return
    18440     # . eax = *s->start
    18441     8b/-> *edx 0/r32/eax
    18442     8a/copy-byte *eax 0/r32/AL
    18443     25/and-eax-with 0xff/imm32
    18444     # . if (eax == '#') continue
    18445     3d/compare-eax-and 0x23/imm32/hash
    18446     74/jump-if-= $check-no-tokens-left:end/disp8
    18447     # abort
    18448     (write-buffered Stderr "'{' or '}' should be on its own line, but got '")
    18449     (rewind-stream %ecx)
    18450     (write-stream 2 %ecx)
    18451     (write-buffered Stderr "'\n")
    18452     (flush Stderr)
    18453     # . syscall(exit, 1)
    18454     bb/copy-to-ebx  1/imm32
    18455     e8/call syscall_exit/disp32
    18456     # never gets here
    18457 $check-no-tokens-left:end:
    18458     # . reclaim locals
    18459     81 0/subop/add %esp 8/imm32
    18460     # . restore registers
    18461     59/pop-to-ecx
    18462     58/pop-to-eax
    18463     # . epilogue
    18464     89/<- %esp 5/r32/ebp
    18465     5d/pop-to-ebp
    18466     c3/return
    18467
    18468 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)
    18469     # pseudocode:
    18470     #   var v: (handle var)
    18471     #   new-literal(name, v)
    18472     #   push(vars, {v, false})
    18473     #   parse-mu-block(in, vars, fn, out)
    18474     #   pop(vars)
    18475     #   out->tag = block
    18476     #   out->var = v
    18477     #
    18478     # . prologue
    18479     55/push-ebp
    18480     89/<- %ebp 4/r32/esp
    18481     # . save registers
    18482     50/push-eax
    18483     51/push-ecx
    18484     57/push-edi
    18485     # var v/ecx: (handle var)
    18486     68/push 0/imm32
    18487     68/push 0/imm32
    18488     89/<- %ecx 4/r32/esp
    18489     #
    18490     (new-literal Heap *(ebp+8) %ecx)
    18491     # push(vars, v)
    18492     (push *(ebp+0x10) *ecx)
    18493     (push *(ebp+0x10) *(ecx+4))
    18494     (push *(ebp+0x10) 0)  # false
    18495     #
    18496     (parse-mu-block *(ebp+0xc) *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c) *(ebp+0x20))
    18497     # pop v off vars
    18498     (pop *(ebp+0x10))  # => eax
    18499     (pop *(ebp+0x10))  # => eax
    18500     (pop *(ebp+0x10))  # => eax
    18501     # var out-addr/edi: (addr stmt) = lookup(*out)
    18502     8b/-> *(ebp+0x18) 7/r32/edi
    18503     (lookup *edi *(edi+4))  # => eax
    18504     89/<- %edi 0/r32/eax
    18505     # out-addr->tag = named-block
    18506     c7 0/subop/copy *edi 0/imm32/block  # Stmt-tag
    18507     # out-addr->var = v
    18508     8b/-> *ecx 0/r32/eax
    18509     89/<- *(edi+0xc) 0/r32/eax  # Block-var
    18510     8b/-> *(ecx+4) 0/r32/eax
    18511     89/<- *(edi+0x10) 0/r32/eax  # Block-var
    18512 $parse-mu-named-block:end:
    18513     # . reclaim locals
    18514     81 0/subop/add %esp 8/imm32
    18515     # . restore registers
    18516     5f/pop-to-edi
    18517     59/pop-to-ecx
    18518     58/pop-to-eax
    18519     # . epilogue
    18520     89/<- %esp 5/r32/ebp
    18521     5d/pop-to-ebp
    18522     c3/return
    18523
    18524 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)
    18525     # . prologue
    18526     55/push-ebp
    18527     89/<- %ebp 4/r32/esp
    18528     # . save registers
    18529     50/push-eax
    18530     51/push-ecx
    18531     52/push-edx
    18532     56/push-esi
    18533     57/push-edi
    18534     # edi = out
    18535     8b/-> *(ebp+0x10) 7/r32/edi
    18536     # var word-slice/ecx: slice
    18537     68/push 0/imm32/end
    18538     68/push 0/imm32/start
    18539     89/<- %ecx 4/r32/esp
    18540     # var v/edx: (handle var)
    18541     68/push 0/imm32
    18542     68/push 0/imm32
    18543     89/<- %edx 4/r32/esp
    18544     # v = parse-var-with-type(next-mu-token(line))
    18545     (next-mu-token *(ebp+8) %ecx)
    18546     {
    18547       # just for tests, support null fn
    18548       8b/-> *(ebp+0x14) 0/r32/eax
    18549       3d/compare-eax-and 0/imm32
    18550       74/jump-if-= break/disp8
    18551       (lookup *eax *(eax+4))  # Var-name Var-name => eax
    18552     }
    18553     (parse-var-with-type %ecx *(ebp+8) %edx %eax *(ebp+0x18) *(ebp+0x1c))
    18554     # var v-addr/esi: (addr var)
    18555     (lookup *edx *(edx+4))  # => eax
    18556     89/<- %esi 0/r32/eax
    18557     # v->block-depth = *Curr-block-depth
    18558     8b/-> *Curr-block-depth 0/r32/eax
    18559     89/<- *(esi+0x10) 0/r32/eax  # Var-block-depth
    18560     # either v has no register and there's no more to this line
    18561     81 7/subop/compare *(esi+0x18) 0/imm32
    18562     {
    18563       75/jump-if-!= break/disp8
    18564       # if v-addr->type == byte, abort
    18565       (lookup *(esi+8) *(esi+0xc))  # Var-type Var-type => eax
    18566       (simple-mu-type? %eax 8)  # byte => eax
    18567       3d/compare-eax-and 0/imm32/false
    18568       0f 85/jump-if-!= $parse-mu-var-def:error-byte-on-stack/disp32
    18569       # ensure that there's nothing else on this line
    18570       (next-mu-token *(ebp+8) %ecx)
    18571       (slice-empty? %ecx)  # => eax
    18572       3d/compare-eax-and 0/imm32/false
    18573       0f 84/jump-if-= $parse-mu-var-def:error2/disp32
    18574       #
    18575       (new-var-def Heap  *edx *(edx+4)  %edi)
    18576       e9/jump $parse-mu-var-def:update-vars/disp32
    18577     }
    18578     # or v has a register and there's more to this line
    18579     {
    18580       0f 84/jump-if-= break/disp32
    18581       # if v-addr->type == byte, check for unsupported registers
    18582       {
    18583         (lookup *(esi+8) *(esi+0xc))  # Var-type Var-type => eax
    18584         (simple-mu-type? %eax 8)  # byte => eax
    18585         3d/compare-eax-and 0/imm32/false
    18586         74/jump-if-= break/disp8
    18587         (lookup *(esi+0x18) *(esi+0x1c))  # => eax
    18588         (string-equal? %eax "esi")  # => eax
    18589         3d/compare-eax-and 0/imm32/false
    18590         0f 85/jump-if-!= $parse-mu-var-def:error-byte-registers/disp32
    18591         (lookup *(esi+0x18) *(esi+0x1c))  # => eax
    18592         (string-equal? %eax "edi")  # => eax
    18593         3d/compare-eax-and 0/imm32/false
    18594         0f 85/jump-if-!= $parse-mu-var-def:error-byte-registers/disp32
    18595       }
    18596       # TODO: vars of type 'byte' should only be initialized by clearing to 0
    18597       # ensure that the next word is '<-'
    18598       (next-mu-token *(ebp+8) %ecx)
    18599       (slice-equal? %ecx "<-")  # => eax
    18600       3d/compare-eax-and 0/imm32/false
    18601       0f 84/jump-if-= $parse-mu-var-def:error1/disp32
    18602       #
    18603       (new-reg-var-def Heap  *edx *(edx+4)  %edi)
    18604       (lookup *edi *(edi+4))  # => eax
    18605       (add-operation-and-inputs-to-stmt %eax *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
    18606     }
    18607 $parse-mu-var-def:update-vars:
    18608     # push 'v' at end of function
    18609     (push *(ebp+0xc) *edx)
    18610     (push *(ebp+0xc) *(edx+4))
    18611     (push *(ebp+0xc) 0)  # Live-var-register-spilled is unused during parsing
    18612 $parse-mu-var-def:end:
    18613     # . reclaim locals
    18614     81 0/subop/add %esp 0x10/imm32
    18615     # . restore registers
    18616     5f/pop-to-edi
    18617     5e/pop-to-esi
    18618     5a/pop-to-edx
    18619     59/pop-to-ecx
    18620     58/pop-to-eax
    18621     # . epilogue
    18622     89/<- %esp 5/r32/ebp
    18623     5d/pop-to-ebp
    18624     c3/return
    18625
    18626 $parse-mu-var-def:error1:
    18627     (rewind-stream *(ebp+8))
    18628     # error("register variable requires a valid instruction to initialize but got '" line "'\n")
    18629     (write-buffered *(ebp+0x18) "register variable requires a valid instruction to initialize but got '")
    18630     (flush *(ebp+0x18))
    18631     (write-stream-data *(ebp+0x18) *(ebp+8))
    18632     (write-buffered *(ebp+0x18) "'\n")
    18633     (flush *(ebp+0x18))
    18634     (stop *(ebp+0x1c) 1)
    18635     # never gets here
    18636
    18637 $parse-mu-var-def:error2:
    18638     # error("fn " fn ": var " var ": variables on the stack can't take an initializer\n")
    18639     (write-buffered *(ebp+0x18) "fn ")
    18640     8b/-> *(ebp+0x14) 0/r32/eax
    18641     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    18642     (write-buffered *(ebp+0x18) %eax)
    18643     (write-buffered *(ebp+0x18) ": var ")
    18644     # var v-addr/eax: (addr var) = lookup(v)
    18645     (lookup *edx *(edx+4))  # => eax
    18646     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    18647     (write-buffered *(ebp+0x18) %eax)
    18648     (write-buffered *(ebp+0x18) ": variables on the stack can't take an initializer\n")
    18649     (flush *(ebp+0x18))
    18650     (stop *(ebp+0x1c) 1)
    18651     # never gets here
    18652
    18653 $parse-mu-var-def:error-byte-on-stack:
    18654     # error("fn " fn ": var '" var "' of type 'byte' cannot be on the stack\n")
    18655     (write-buffered *(ebp+0x18) "fn ")
    18656     8b/-> *(ebp+0x14) 0/r32/eax
    18657     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    18658     (write-buffered *(ebp+0x18) %eax)
    18659     (write-buffered *(ebp+0x18) ": var '")
    18660     # var v-addr/eax: (addr var) = lookup(v)
    18661     (lookup *edx *(edx+4))  # => eax
    18662     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    18663     (write-buffered *(ebp+0x18) %eax)
    18664     (write-buffered *(ebp+0x18) "' of type 'byte' cannot be on the stack\n")
    18665     (flush *(ebp+0x18))
    18666     (stop *(ebp+0x1c) 1)
    18667     # never gets here
    18668
    18669 $parse-mu-var-def:error-byte-registers:
    18670     # error("fn " fn ": var '" var "' of type 'byte' cannot be in esi or edi\n")
    18671     (write-buffered *(ebp+0x18) "fn ")
    18672     8b/-> *(ebp+0x14) 0/r32/eax
    18673     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    18674     (write-buffered *(ebp+0x18) %eax)
    18675     (write-buffered *(ebp+0x18) ": var '")
    18676     # var v-addr/eax: (addr var) = lookup(v)
    18677     (lookup *edx *(edx+4))  # => eax
    18678     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    18679     (write-buffered *(ebp+0x18) %eax)
    18680     (write-buffered *(ebp+0x18) "' of type 'byte' cannot be in esi or edi\n")
    18681     (flush *(ebp+0x18))
    18682     (stop *(ebp+0x1c) 1)
    18683     # never gets here
    18684
    18685 test-parse-mu-var-def:
    18686     # 'var n: int'
    18687     # . prologue
    18688     55/push-ebp
    18689     89/<- %ebp 4/r32/esp
    18690     # setup
    18691     8b/-> *Primitive-type-ids 0/r32/eax
    18692     89/<- *Type-id 0/r32/eax  # stream-write
    18693     (clear-stream _test-input-stream)
    18694     (write _test-input-stream "n: int\n")  # caller has consumed the 'var'
    18695     c7 0/subop/copy *Curr-block-depth 1/imm32
    18696     # var out/esi: (handle stmt)
    18697     68/push 0/imm32
    18698     68/push 0/imm32
    18699     89/<- %esi 4/r32/esp
    18700     # var vars/ecx: (stack (addr var) 16)
    18701     81 5/subop/subtract %esp 0xc0/imm32
    18702     68/push 0xc0/imm32/size
    18703     68/push 0/imm32/top
    18704     89/<- %ecx 4/r32/esp
    18705     (clear-stack %ecx)
    18706     # convert
    18707     (parse-mu-var-def _test-input-stream %ecx %esi 0 Stderr 0)
    18708     # var out-addr/esi: (addr stmt)
    18709     (lookup *esi *(esi+4))  # => eax
    18710     89/<- %esi 0/r32/eax
    18711     #
    18712     (check-ints-equal *esi 2 "F - test-parse-mu-var-def/tag")  # Stmt-tag is var-def
    18713     # var v/ecx: (addr var) = lookup(out->var)
    18714     (lookup *(esi+4) *(esi+8))  # Vardef-var Vardef-var => eax
    18715     89/<- %ecx 0/r32/eax
    18716     # v->name
    18717     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    18718     (check-strings-equal %eax "n" "F - test-parse-mu-var-def/var-name")
    18719     # v->register
    18720     (check-ints-equal *(ecx+0x18) 0 "F - test-parse-mu-var-def/var-register")  # Var-register
    18721     # v->block-depth
    18722     (check-ints-equal *(ecx+0x10) 1 "F - test-parse-mu-var-def/output-block-depth")  # Var-block-depth
    18723     # v->type == int
    18724     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
    18725     (check-ints-equal *eax 1 "F - test-parse-mu-var-def/var-type:0")  # Type-tree-is-atom
    18726     (check-ints-equal *(eax+4) 1 "F - test-parse-mu-var-def/var-type:1")  # Type-tree-value
    18727     (check-ints-equal *(eax+0xc) 0 "F - test-parse-mu-var-def/var-type:2")  # Type-tree-right
    18728     # . epilogue
    18729     89/<- %esp 5/r32/ebp
    18730     5d/pop-to-ebp
    18731     c3/return
    18732
    18733 test-parse-mu-reg-var-def:
    18734     # 'var n/eax: int <- copy 0'
    18735     # . prologue
    18736     55/push-ebp
    18737     89/<- %ebp 4/r32/esp
    18738     # setup
    18739     8b/-> *Primitive-type-ids 0/r32/eax
    18740     89/<- *Type-id 0/r32/eax  # stream-write
    18741     (clear-stream _test-input-stream)
    18742     (write _test-input-stream "n/eax: int <- copy 0\n")  # caller has consumed the 'var'
    18743     c7 0/subop/copy *Curr-block-depth 1/imm32
    18744     # var out/esi: (handle stmt)
    18745     68/push 0/imm32
    18746     68/push 0/imm32
    18747     89/<- %esi 4/r32/esp
    18748     # var vars/ecx: (stack (addr var) 16)
    18749     81 5/subop/subtract %esp 0xc0/imm32
    18750     68/push 0xc0/imm32/size
    18751     68/push 0/imm32/top
    18752     89/<- %ecx 4/r32/esp
    18753     (clear-stack %ecx)
    18754     # convert
    18755     (parse-mu-var-def _test-input-stream %ecx %esi 0 Stderr 0)
    18756     # var out-addr/esi: (addr stmt)
    18757     (lookup *esi *(esi+4))  # => eax
    18758     89/<- %esi 0/r32/eax
    18759     #
    18760     (check-ints-equal *esi 3 "F - test-parse-mu-reg-var-def/tag")  # Stmt-tag is reg-var-def
    18761     # var v/ecx: (addr var) = lookup(out->outputs->value)
    18762     # . eax: (addr stmt-var) = lookup(out->outputs)
    18763     (lookup *(esi+0x14) *(esi+0x18))  # Regvardef-outputs Regvardef-outputs => eax
    18764     # .
    18765     (check-ints-equal *(eax+8) 0 "F - test-parse-mu-reg-var-def/single-output")  # Stmt-var-next
    18766     # . eax: (addr var) = lookup(eax->value)
    18767     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    18768     # . ecx = eax
    18769     89/<- %ecx 0/r32/eax
    18770     # v->name
    18771     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    18772     (check-strings-equal %eax "n" "F - test-parse-mu-reg-var-def/output-name")  # Var-name
    18773     # v->register
    18774     (lookup *(ecx+0x18) *(ecx+0x1c))  # Var-register Var-register => eax
    18775     (check-strings-equal %eax "eax" "F - test-parse-mu-reg-var-def/output-register")
    18776     # v->block-depth
    18777     (check-ints-equal *(ecx+0x10) 1 "F - test-parse-mu-reg-var-def/output-block-depth")  # Var-block-depth
    18778     # v->type == int
    18779     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
    18780     (check-ints-equal *eax 1 "F - test-parse-mu-reg-var-def/output-type:0")  # Type-tree-is-atom
    18781     (check-ints-equal *(eax+4) 1 "F - test-parse-mu-reg-var-def/output-type:1")  # Type-tree-value
    18782     (check-ints-equal *(eax+0xc) 0 "F - test-parse-mu-reg-var-def/output-type:2")  # Type-tree-right
    18783     # . epilogue
    18784     89/<- %esp 5/r32/ebp
    18785     5d/pop-to-ebp
    18786     c3/return
    18787
    18788 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)
    18789     # pseudocode:
    18790     #   var name: slice
    18791     #   allocate(Heap, Stmt-size, out)
    18792     #   var out-addr: (addr stmt) = lookup(*out)
    18793     #   out-addr->tag = stmt
    18794     #   if stmt-has-outputs?(line)
    18795     #     while true
    18796     #       name = next-mu-token(line)
    18797     #       if (name == '<-') break
    18798     #       assert(identifier?(name))
    18799     #       var v: (handle var) = lookup-var(name, vars)
    18800     #       out-addr->outputs = append(v, out-addr->outputs)
    18801     #   add-operation-and-inputs-to-stmt(out-addr, line, vars)
    18802     #
    18803     # . prologue
    18804     55/push-ebp
    18805     89/<- %ebp 4/r32/esp
    18806     # . save registers
    18807     50/push-eax
    18808     51/push-ecx
    18809     52/push-edx
    18810     53/push-ebx
    18811     57/push-edi
    18812     # var name/ecx: slice
    18813     68/push 0/imm32/end
    18814     68/push 0/imm32/start
    18815     89/<- %ecx 4/r32/esp
    18816     # var is-deref?/edx: boolean = false
    18817     ba/copy-to-edx 0/imm32/false
    18818     # var v: (handle var)
    18819     68/push 0/imm32
    18820     68/push 0/imm32
    18821     89/<- %ebx 4/r32/esp
    18822     #
    18823     (allocate Heap *Stmt-size *(ebp+0x14))
    18824     # var out-addr/edi: (addr stmt) = lookup(*out)
    18825     8b/-> *(ebp+0x14) 7/r32/edi
    18826     (lookup *edi *(edi+4))  # => eax
    18827     89/<- %edi 0/r32/eax
    18828     # out-addr->tag = 1/stmt
    18829     c7 0/subop/copy *edi 1/imm32/stmt1  # Stmt-tag
    18830     {
    18831       (stmt-has-outputs? *(ebp+8))
    18832       3d/compare-eax-and 0/imm32/false
    18833       0f 84/jump-if-= break/disp32
    18834       {
    18835 $parse-mu-stmt:read-outputs:
    18836         # name = next-mu-token(line)
    18837         (next-mu-token *(ebp+8) %ecx)
    18838         # if slice-empty?(word-slice) break
    18839         (slice-empty? %ecx)  # => eax
    18840         3d/compare-eax-and 0/imm32/false
    18841         0f 85/jump-if-!= break/disp32
    18842         # if (name == "<-") break
    18843         (slice-equal? %ecx "<-")  # => eax
    18844         3d/compare-eax-and 0/imm32/false
    18845         0f 85/jump-if-!= break/disp32
    18846         # if slice-starts-with?(name, "*") abort
    18847         8b/-> *ecx 0/r32/eax  # Slice-start
    18848         8a/copy-byte *eax 0/r32/AL
    18849         25/and-eax-with 0xff/imm32
    18850         3d/compare-eax-and 0x2a/imm32/asterisk
    18851         0f 84/jump-if-= $parse-mu-stmt:error-output-dereferenced/disp32
    18852         # assert(identifier?(name))
    18853         (identifier? %ecx)  # => eax
    18854         3d/compare-eax-and 0/imm32/false
    18855         0f 84/jump-if-= $parse-mu-stmt:abort/disp32
    18856         #
    18857         (lookup-var %ecx *(ebp+0xc) %ebx *(ebp+0x10) *(ebp+0x18) *(ebp+0x1c))
    18858         8d/copy-address *(edi+0x14) 0/r32/eax  # Stmt1-outputs
    18859         (append-stmt-var Heap  *ebx *(ebx+4)  *(edi+0x14) *(edi+0x18)  0  %eax)  # Stmt1-outputs
    18860         #
    18861         e9/jump loop/disp32
    18862       }
    18863     }
    18864     (add-operation-and-inputs-to-stmt %edi *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x18) *(ebp+0x1c))
    18865 $parse-mu-stmt:end:
    18866     # . reclaim locals
    18867     81 0/subop/add %esp 0x10/imm32
    18868     # . restore registers
    18869     5f/pop-to-edi
    18870     5b/pop-to-ebx
    18871     5a/pop-to-edx
    18872     59/pop-to-ecx
    18873     58/pop-to-eax
    18874     # . epilogue
    18875     89/<- %esp 5/r32/ebp
    18876     5d/pop-to-ebp
    18877     c3/return
    18878
    18879 $parse-mu-stmt:abort:
    18880     # error("invalid identifier '" name "'\n")
    18881     (write-buffered *(ebp+0x18) "fn ")
    18882     8b/-> *(ebp+0x10) 0/r32/eax
    18883     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    18884     (write-buffered *(ebp+0x18) %eax)
    18885     (write-buffered *(ebp+0x18) ": invalid identifier '")
    18886     (write-slice-buffered *(ebp+0x18) %ecx)
    18887     (write-buffered *(ebp+0x18) "'\n")
    18888     (flush *(ebp+0x18))
    18889     (stop *(ebp+0x1c) 1)
    18890     # never gets here
    18891
    18892 $parse-mu-stmt:error-output-dereferenced:
    18893     # error("invalid identifier '" name "'\n")
    18894     (write-buffered *(ebp+0x18) "fn ")
    18895     8b/-> *(ebp+0x10) 0/r32/eax
    18896     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    18897     (write-buffered *(ebp+0x18) %eax)
    18898     (write-buffered *(ebp+0x18) ": output '")
    18899     (write-slice-buffered *(ebp+0x18) %ecx)
    18900     (write-buffered *(ebp+0x18) "' should write to a register, and therefore cannot be dereferenced\n")
    18901     (flush *(ebp+0x18))
    18902     (stop *(ebp+0x1c) 1)
    18903     # never gets here
    18904
    18905 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)
    18906     # pseudocode:
    18907     #   stmt->name = slice-to-string(next-mu-token(line))
    18908     #   while true
    18909     #     name = next-mu-token(line)
    18910     #     v = lookup-var-or-literal(name)
    18911     #     stmt->inouts = append(v, stmt->inouts)
    18912     #
    18913     # . prologue
    18914     55/push-ebp
    18915     89/<- %ebp 4/r32/esp
    18916     # . save registers
    18917     50/push-eax
    18918     51/push-ecx
    18919     52/push-edx
    18920     53/push-ebx
    18921     56/push-esi
    18922     57/push-edi
    18923     # edi = stmt
    18924     8b/-> *(ebp+8) 7/r32/edi
    18925     # var name/ecx: slice
    18926     68/push 0/imm32/end
    18927     68/push 0/imm32/start
    18928     89/<- %ecx 4/r32/esp
    18929     # var is-deref?/edx: boolean = false
    18930     ba/copy-to-edx 0/imm32/false
    18931     # var v/esi: (handle var)
    18932     68/push 0/imm32
    18933     68/push 0/imm32
    18934     89/<- %esi 4/r32/esp
    18935 $add-operation-and-inputs-to-stmt:read-operation:
    18936     (next-mu-token *(ebp+0xc) %ecx)
    18937     8d/copy-address *(edi+4) 0/r32/eax  # Stmt1-operation or Regvardef-operationStmt1-operation or Regvardef-operation
    18938     (slice-to-string Heap %ecx %eax)
    18939     # var is-get?/ebx: boolean = (name == "get")
    18940     (slice-equal? %ecx "get")  # => eax
    18941     89/<- %ebx 0/r32/eax
    18942     {
    18943 $add-operation-and-inputs-to-stmt:read-inouts:
    18944       # name = next-mu-token(line)
    18945       (next-mu-token *(ebp+0xc) %ecx)
    18946       # if slice-empty?(word-slice) break
    18947       (slice-empty? %ecx)  # => eax
    18948       3d/compare-eax-and 0/imm32/false
    18949       0f 85/jump-if-!= break/disp32
    18950       # if (name == "<-") abort
    18951       (slice-equal? %ecx "<-")
    18952       3d/compare-eax-and 0/imm32/false
    18953       0f 85/jump-if-!= $add-operation-and-inputs-to-stmt:abort/disp32
    18954       # if (get? && second operand) lookup or create offset
    18955       {
    18956         81 7/subop/compare %ebx 0/imm32/false
    18957         74/jump-if-= break/disp8
    18958         (lookup *(edi+0xc) *(edi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    18959         3d/compare-eax-and 0/imm32
    18960         74/jump-if-= break/disp8
    18961         (lookup-or-create-constant %eax %ecx %esi)
    18962 #?         (lookup *esi *(esi+4))
    18963 #?         (write-buffered Stderr "creating new output var ")
    18964 #?         (write-int32-hex-buffered Stderr %eax)
    18965 #?         (write-buffered Stderr " for field called ")
    18966 #?         (write-slice-buffered Stderr %ecx)
    18967 #?         (write-buffered Stderr "; var name ")
    18968 #?         (lookup *eax *(eax+4))  # Var-name
    18969 #?         (write-buffered Stderr %eax)
    18970 #?         (write-buffered Stderr Newline)
    18971 #?         (flush Stderr)
    18972         e9/jump $add-operation-and-inputs-to-stmt:save-var/disp32
    18973       }
    18974       # is-deref? = false
    18975       ba/copy-to-edx 0/imm32/false
    18976       # if (slice-starts-with?(name, '*')) ++name->start and set is-deref?
    18977       8b/-> *ecx 0/r32/eax  # Slice-start
    18978       8a/copy-byte *eax 0/r32/AL
    18979       25/and-eax-with 0xff/imm32
    18980       3d/compare-eax-and 0x2a/imm32/asterisk
    18981       {
    18982         75/jump-if-!= break/disp8
    18983 $add-operation-and-inputs-to-stmt:inout-is-deref:
    18984         ff 0/subop/increment *ecx
    18985         ba/copy-to-edx 1/imm32/true
    18986       }
    18987       (lookup-var-or-literal %ecx *(ebp+0x10) %esi *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
    18988       # if (deref?) some additional checks
    18989       81 7/subop/compare %edx 0/imm32/false
    18990       {
    18991         74/jump-if-= break/disp8
    18992         # if var is not in register, abort
    18993         (lookup *esi *(esi+4))  # => eax
    18994         81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
    18995         0f 84/jump-if-= $add-operation-and-inputs-to-stmt:error-deref-on-stack/disp32
    18996         # if var is not an address, abort
    18997         (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    18998         (mu-addr-type? %eax)  # => eax
    18999         3d/compare-eax-and 0/imm32/false
    19000         0f 84/jump-if-= $add-operation-and-inputs-to-stmt:error-deref-non-addr/disp32
    19001       }
    19002 $add-operation-and-inputs-to-stmt:save-var:
    19003       8d/copy-address *(edi+0xc) 0/r32/eax
    19004       (append-stmt-var Heap  *esi *(esi+4)  *(edi+0xc) *(edi+0x10)  %edx  %eax)  # Stmt1-inouts or Regvardef-inouts
    19005       #
    19006       e9/jump loop/disp32
    19007     }
    19008 $add-operation-and-inputs-to-stmt:end:
    19009     # . reclaim locals
    19010     81 0/subop/add %esp 0x10/imm32
    19011     # . restore registers
    19012     5f/pop-to-edi
    19013     5e/pop-to-esi
    19014     5b/pop-to-ebx
    19015     5a/pop-to-edx
    19016     59/pop-to-ecx
    19017     58/pop-to-eax
    19018     # . epilogue
    19019     89/<- %esp 5/r32/ebp
    19020     5d/pop-to-ebp
    19021     c3/return
    19022
    19023 $add-operation-and-inputs-to-stmt:abort:
    19024     # error("fn ___: invalid identifier in '" line "'\n")
    19025     (write-buffered *(ebp+0x18) "fn ")
    19026     8b/-> *(ebp+0x14) 0/r32/eax
    19027     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    19028     (write-buffered *(ebp+0x18) %eax)
    19029     (rewind-stream *(ebp+0xc))
    19030     (write-buffered *(ebp+0x18) ": invalid identifier in '")
    19031     (write-stream-data *(ebp+0x18) *(ebp+0xc))
    19032     (write-buffered *(ebp+0x18) "'\n")
    19033     (flush *(ebp+0x18))
    19034     (stop *(ebp+0x1c) 1)
    19035     # never gets here
    19036
    19037 $add-operation-and-inputs-to-stmt:error-deref-on-stack:
    19038     # error("fn ___: cannot dereference var ___ on stack\n")
    19039     (write-buffered *(ebp+0x18) "fn ")
    19040     8b/-> *(ebp+0x14) 0/r32/eax
    19041     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    19042     (write-buffered *(ebp+0x18) %eax)
    19043     (rewind-stream *(ebp+0xc))
    19044     (write-buffered *(ebp+0x18) ": cannot dereference var '")
    19045     (lookup *esi *(esi+4))  # => eax
    19046     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    19047     (write-buffered *(ebp+0x18) %eax)
    19048     (write-buffered *(ebp+0x18) "' on stack\n")
    19049     (flush *(ebp+0x18))
    19050     (stop *(ebp+0x1c) 1)
    19051     # never gets here
    19052
    19053 $add-operation-and-inputs-to-stmt:error-deref-non-addr:
    19054     # error("fn ___: cannot dereference non-addr var ___\n")
    19055     (write-buffered *(ebp+0x18) "fn ")
    19056     8b/-> *(ebp+0x14) 0/r32/eax
    19057     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    19058     (write-buffered *(ebp+0x18) %eax)
    19059     (rewind-stream *(ebp+0xc))
    19060     (write-buffered *(ebp+0x18) ": cannot dereference non-addr var '")
    19061     (lookup *esi *(esi+4))  # => eax
    19062     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    19063     (write-buffered *(ebp+0x18) %eax)
    19064     (write-buffered *(ebp+0x18) "'\n")
    19065     (flush *(ebp+0x18))
    19066     (stop *(ebp+0x1c) 1)
    19067     # never gets here
    19068
    19069 stmt-has-outputs?:  # line: (addr stream byte) -> result/eax: boolean
    19070     # . prologue
    19071     55/push-ebp
    19072     89/<- %ebp 4/r32/esp
    19073     # . save registers
    19074     51/push-ecx
    19075     # var word-slice/ecx: slice
    19076     68/push 0/imm32/end
    19077     68/push 0/imm32/start
    19078     89/<- %ecx 4/r32/esp
    19079     # result = false
    19080     b8/copy-to-eax 0/imm32/false
    19081     (rewind-stream *(ebp+8))
    19082     {
    19083       (next-mu-token *(ebp+8) %ecx)
    19084       # if slice-empty?(word-slice) break
    19085       (slice-empty? %ecx)
    19086       3d/compare-eax-and 0/imm32/false
    19087       b8/copy-to-eax 0/imm32/false/result  # restore result (if we're here it's still false)
    19088       0f 85/jump-if-!= break/disp32
    19089       # if slice-starts-with?(word-slice, '#') break
    19090       # . eax = *word-slice->start
    19091       8b/-> *ecx 0/r32/eax
    19092       8a/copy-byte *eax 0/r32/AL
    19093       25/and-eax-with 0xff/imm32
    19094       # . if (eax == '#') break
    19095       3d/compare-eax-and 0x23/imm32/hash
    19096       b8/copy-to-eax 0/imm32/false/result  # restore result (if we're here it's still false)
    19097       0f 84/jump-if-= break/disp32
    19098       # if slice-equal?(word-slice, '<-') return true
    19099       (slice-equal? %ecx "<-")
    19100       3d/compare-eax-and 0/imm32/false
    19101       74/jump-if-= loop/disp8
    19102       b8/copy-to-eax 1/imm32/true
    19103     }
    19104 $stmt-has-outputs:end:
    19105     (rewind-stream *(ebp+8))
    19106     # . reclaim locals
    19107     81 0/subop/add %esp 8/imm32
    19108     # . restore registers
    19109     59/pop-to-ecx
    19110     # . epilogue
    19111     89/<- %esp 5/r32/ebp
    19112     5d/pop-to-ebp
    19113     c3/return
    19114
    19115 # if 'name' starts with a digit, create a new literal var for it
    19116 # otherwise return first 'name' from the top (back) of 'vars' and abort if not found
    19117 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)
    19118     # . prologue
    19119     55/push-ebp
    19120     89/<- %ebp 4/r32/esp
    19121     # . save registers
    19122     50/push-eax
    19123     51/push-ecx
    19124     56/push-esi
    19125     # esi = name
    19126     8b/-> *(ebp+8) 6/r32/esi
    19127     # if slice-empty?(name) abort
    19128     (slice-empty? %esi)  # => eax
    19129     3d/compare-eax-and 0/imm32/false
    19130     0f 85/jump-if-!= $lookup-var-or-literal:abort/disp32
    19131     # var c/ecx: byte = *name->start
    19132     8b/-> *esi 1/r32/ecx
    19133     8a/copy-byte *ecx 1/r32/CL
    19134     81 4/subop/and %ecx 0xff/imm32
    19135     # if (decimal-digit?(c) || c == '-') return new var(name)
    19136     {
    19137       81 7/subop/compare %ecx 0x2d/imm32/dash
    19138       74/jump-if-= $lookup-var-or-literal:literal/disp8
    19139       (decimal-digit? %ecx)  # => eax
    19140       3d/compare-eax-and 0/imm32/false
    19141       74/jump-if-= break/disp8
    19142 $lookup-var-or-literal:literal:
    19143       (new-literal-integer Heap %esi *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
    19144       eb/jump $lookup-var-or-literal:end/disp8
    19145     }
    19146     # else if (c == '"') return new var(name)
    19147     {
    19148       81 7/subop/compare %ecx 0x22/imm32/dquote
    19149       75/jump-if-!= break/disp8
    19150 $lookup-var-or-literal:literal-string:
    19151       (new-literal-string Heap %esi *(ebp+0x10))
    19152       eb/jump $lookup-var-or-literal:end/disp8
    19153     }
    19154     # otherwise return lookup-var(name, vars)
    19155     {
    19156 $lookup-var-or-literal:var:
    19157       (lookup-var %esi *(ebp+0xc) *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
    19158     }
    19159 $lookup-var-or-literal:end:
    19160     # . restore registers
    19161     5e/pop-to-esi
    19162     59/pop-to-ecx
    19163     58/pop-to-eax
    19164     # . epilogue
    19165     89/<- %esp 5/r32/ebp
    19166     5d/pop-to-ebp
    19167     c3/return
    19168
    19169 $lookup-var-or-literal:abort:
    19170     (write-buffered *(ebp+0x18) "fn ")
    19171     8b/-> *(ebp+0x14) 0/r32/eax
    19172     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    19173     (write-buffered *(ebp+0x18) %eax)
    19174     (write-buffered *(ebp+0x18) ": empty variable!")
    19175     (flush *(ebp+0x18))
    19176     (stop *(ebp+0x1c) 1)
    19177     # never gets here
    19178
    19179 # return first 'name' from the top (back) of 'vars' and abort if not found
    19180 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)
    19181     # . prologue
    19182     55/push-ebp
    19183     89/<- %ebp 4/r32/esp
    19184     # . save registers
    19185     50/push-eax
    19186     #
    19187     (lookup-var-helper *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
    19188     # if (*out == 0) abort
    19189     8b/-> *(ebp+0x10) 0/r32/eax
    19190     81 7/subop/compare *eax 0/imm32
    19191     74/jump-if-= $lookup-var:abort/disp8
    19192 $lookup-var:end:
    19193     # . restore registers
    19194     58/pop-to-eax
    19195     # . epilogue
    19196     89/<- %esp 5/r32/ebp
    19197     5d/pop-to-ebp
    19198     c3/return
    19199
    19200 $lookup-var:abort:
    19201     (write-buffered *(ebp+0x18) "fn ")
    19202     8b/-> *(ebp+0x14) 0/r32/eax
    19203     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    19204     (write-buffered *(ebp+0x18) %eax)
    19205     (write-buffered *(ebp+0x18) ": unknown variable '")
    19206     (write-slice-buffered *(ebp+0x18) *(ebp+8))
    19207     (write-buffered *(ebp+0x18) "'\n")
    19208     (flush *(ebp+0x18))
    19209     (stop *(ebp+0x1c) 1)
    19210     # never gets here
    19211
    19212 # return first 'name' from the top (back) of 'vars', and 0/null if not found
    19213 # ensure that 'name' if in a register is the topmost variable in that register
    19214 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)
    19215     # pseudocode:
    19216     #   var curr: (addr handle var) = &vars->data[vars->top - 12]
    19217     #   var min = vars->data
    19218     #   while curr >= min
    19219     #     var v: (handle var) = *curr
    19220     #     if v->name == name
    19221     #       return
    19222     #     curr -= 12
    19223     #
    19224     # . prologue
    19225     55/push-ebp
    19226     89/<- %ebp 4/r32/esp
    19227     # . save registers
    19228     50/push-eax
    19229     51/push-ecx
    19230     52/push-edx
    19231     53/push-ebx
    19232     56/push-esi
    19233     57/push-edi
    19234     # clear out
    19235     (zero-out *(ebp+0x10) *Handle-size)
    19236     # esi = vars
    19237     8b/-> *(ebp+0xc) 6/r32/esi
    19238     # ebx = vars->top
    19239     8b/-> *esi 3/r32/ebx
    19240     # if (vars->top > vars->size) abort
    19241     3b/compare<- *(esi+4) 0/r32/eax
    19242     0f 8f/jump-if-> $lookup-var-helper:error1/disp32
    19243     # var min/edx: (addr handle var) = vars->data
    19244     8d/copy-address *(esi+8) 2/r32/edx
    19245     # var curr/ebx: (addr handle var) = &vars->data[vars->top - 12]
    19246     8d/copy-address *(esi+ebx-4) 3/r32/ebx  # vars + 8 + vars->type - 12
    19247     # var var-in-reg/edi: 16 addrs
    19248     68/push 0/imm32
    19249     68/push 0/imm32
    19250     68/push 0/imm32
    19251     68/push 0/imm32
    19252     68/push 0/imm32
    19253     68/push 0/imm32
    19254     68/push 0/imm32
    19255     68/push 0/imm32
    19256     68/push 0/imm32
    19257     68/push 0/imm32
    19258     68/push 0/imm32
    19259     68/push 0/imm32
    19260     68/push 0/imm32
    19261     68/push 0/imm32
    19262     68/push 0/imm32
    19263     68/push 0/imm32
    19264     89/<- %edi 4/r32/esp
    19265     {
    19266 $lookup-var-helper:loop:
    19267       # if (curr < min) return
    19268       39/compare %ebx 2/r32/edx
    19269       0f 82/jump-if-addr< break/disp32
    19270       # var v/ecx: (addr var) = lookup(*curr)
    19271       (lookup *ebx *(ebx+4))  # => eax
    19272       89/<- %ecx 0/r32/eax
    19273       # var vn/eax: (addr array byte) = lookup(v->name)
    19274       (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    19275       # if (vn == name) return curr
    19276       (slice-equal? *(ebp+8) %eax)  # => eax
    19277       3d/compare-eax-and 0/imm32/false
    19278       {
    19279         74/jump-if-= break/disp8
    19280 $lookup-var-helper:found:
    19281         # var vr/eax: (addr array byte) = lookup(v->register)
    19282         (lookup *(ecx+0x18) *(ecx+0x1c))  # Var-register Var-register => eax
    19283         3d/compare-eax-and 0/imm32
    19284         {
    19285           74/jump-if-= break/disp8
    19286 $lookup-var-helper:found-register:
    19287           # var reg/eax: int = get(Registers, vr)
    19288           (get Mu-registers-unique %eax 0xc "Mu-registers-unique")  # => eax
    19289           8b/-> *eax 0/r32/eax
    19290           # if (var-in-reg[reg]) error
    19291           8b/-> *(edi+eax<<2) 0/r32/eax
    19292           3d/compare-eax-and 0/imm32
    19293           0f 85/jump-if-!= $lookup-var-helper:error2/disp32
    19294         }
    19295 $lookup-var-helper:return:
    19296         # esi = out
    19297         8b/-> *(ebp+0x10) 6/r32/esi
    19298         # *out = *curr
    19299         8b/-> *ebx 0/r32/eax
    19300         89/<- *esi 0/r32/eax
    19301         8b/-> *(ebx+4) 0/r32/eax
    19302         89/<- *(esi+4) 0/r32/eax
    19303         # return
    19304         eb/jump $lookup-var-helper:end/disp8
    19305       }
    19306       # 'name' not yet found; update var-in-reg if v in register
    19307       # . var vr/eax: (addr array byte) = lookup(v->register)
    19308       (lookup *(ecx+0x18) *(ecx+0x1c))  # Var-register Var-register => eax
    19309       # . if (vr == 0) continue
    19310       3d/compare-eax-and 0/imm32
    19311       74/jump-if-= $lookup-var-helper:continue/disp8
    19312       # . var reg/eax: int = get(Registers, vr)
    19313       (get Mu-registers-unique %eax 0xc "Mu-registers-unique")  # => eax
    19314       8b/-> *eax 0/r32/eax
    19315       # . var-in-reg[reg] = v
    19316       89/<- *(edi+eax<<2) 1/r32/ecx
    19317 $lookup-var-helper:continue:
    19318       # curr -= 12
    19319       81 5/subop/subtract %ebx 0xc/imm32
    19320       e9/jump loop/disp32
    19321     }
    19322 $lookup-var-helper:end:
    19323     # . reclaim locals
    19324     81 0/subop/add %esp 0x40/imm32
    19325     # . restore registers
    19326     5f/pop-to-edi
    19327     5e/pop-to-esi
    19328     5b/pop-to-ebx
    19329     5a/pop-to-edx
    19330     59/pop-to-ecx
    19331     58/pop-to-eax
    19332     # . epilogue
    19333     89/<- %esp 5/r32/ebp
    19334     5d/pop-to-ebp
    19335     c3/return
    19336
    19337 $lookup-var-helper:error1:
    19338     (write-buffered *(ebp+0x18) "fn ")
    19339     8b/-> *(ebp+0x14) 0/r32/eax
    19340     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    19341     (write-buffered *(ebp+0x18) %eax)
    19342     (write-buffered *(ebp+0x18) ": malformed stack when looking up '")
    19343     (write-slice-buffered *(ebp+0x18) *(ebp+8))
    19344     (write-buffered *(ebp+0x18) "'\n")
    19345     (flush *(ebp+0x18))
    19346     (stop *(ebp+0x1c) 1)
    19347     # never gets here
    19348
    19349 $lookup-var-helper:error2:
    19350     # eax contains the conflicting var at this point
    19351     (write-buffered *(ebp+0x18) "fn ")
    19352     50/push-eax
    19353     8b/-> *(ebp+0x14) 0/r32/eax
    19354     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    19355     (write-buffered *(ebp+0x18) %eax)
    19356     58/pop-eax
    19357     (write-buffered *(ebp+0x18) ": register ")
    19358     50/push-eax
    19359     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    19360     (write-buffered *(ebp+0x18) %eax)
    19361     58/pop-to-eax
    19362     (write-buffered *(ebp+0x18) " reads var '")
    19363     (write-slice-buffered *(ebp+0x18) *(ebp+8))
    19364     (write-buffered *(ebp+0x18) "' after writing var '")
    19365     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    19366     (write-buffered *(ebp+0x18) %eax)
    19367     (write-buffered *(ebp+0x18) "'\n")
    19368     (flush *(ebp+0x18))
    19369     (stop *(ebp+0x1c) 1)
    19370     # never gets here
    19371
    19372 dump-vars:  # vars: (addr stack live-var)
    19373     # pseudocode:
    19374     #   var curr: (addr handle var) = &vars->data[vars->top - 12]
    19375     #   var min = vars->data
    19376     #   while curr >= min
    19377     #     var v: (handle var) = *curr
    19378     #     print v
    19379     #     curr -= 12
    19380     #
    19381     # . prologue
    19382     55/push-ebp
    19383     89/<- %ebp 4/r32/esp
    19384     # . save registers
    19385     52/push-edx
    19386     53/push-ebx
    19387     56/push-esi
    19388     # esi = vars
    19389     8b/-> *(ebp+8) 6/r32/esi
    19390     # ebx = vars->top
    19391     8b/-> *esi 3/r32/ebx
    19392     # var min/edx: (addr handle var) = vars->data
    19393     8d/copy-address *(esi+8) 2/r32/edx
    19394     # var curr/ebx: (addr handle var) = &vars->data[vars->top - 12]
    19395     8d/copy-address *(esi+ebx-4) 3/r32/ebx  # vars + 8 + vars->type - 12
    19396     {
    19397 $dump-vars:loop:
    19398       # if (curr < min) return
    19399       39/compare %ebx 2/r32/edx
    19400       0f 82/jump-if-addr< break/disp32
    19401       #
    19402       (write-buffered Stderr "  var@")
    19403       (dump-var 2 %ebx)
    19404       # curr -= 12
    19405       81 5/subop/subtract %ebx 0xc/imm32
    19406       e9/jump loop/disp32
    19407     }
    19408 $dump-vars:end:
    19409     # . restore registers
    19410     5e/pop-to-esi
    19411     5b/pop-to-ebx
    19412     5a/pop-to-edx
    19413     # . epilogue
    19414     89/<- %esp 5/r32/ebp
    19415     5d/pop-to-ebp
    19416     c3/return
    19417
    19418 == data
    19419 # Like Registers, but no esp or ebp
    19420 Mu-registers:  # (addr stream {(handle array byte), int})
    19421   # a table is a stream
    19422   0xa8/imm32/write
    19423   0/imm32/read
    19424   0xa8/imm32/length
    19425   # data
    19426   # general-purpose registers
    19427   # it is perfectly ok to use fake alloc-ids -- as long as you never try to reclaim them
    19428   0x11/imm32/alloc-id $Mu-register-eax/imm32 0/imm32
    19429   0x11/imm32/alloc-id $Mu-register-ecx/imm32 1/imm32
    19430   0x11/imm32/alloc-id $Mu-register-edx/imm32 2/imm32
    19431   0x11/imm32/alloc-id $Mu-register-ebx/imm32 3/imm32
    19432   0x11/imm32/alloc-id $Mu-register-esi/imm32 6/imm32
    19433   0x11/imm32/alloc-id $Mu-register-edi/imm32 7/imm32
    19434   # floating-point registers
    19435   0x11/imm32/alloc-id $Mu-register-xmm0/imm32 0/imm32
    19436   0x11/imm32/alloc-id $Mu-register-xmm1/imm32 1/imm32
    19437   0x11/imm32/alloc-id $Mu-register-xmm2/imm32 2/imm32
    19438   0x11/imm32/alloc-id $Mu-register-xmm3/imm32 3/imm32
    19439   0x11/imm32/alloc-id $Mu-register-xmm4/imm32 4/imm32
    19440   0x11/imm32/alloc-id $Mu-register-xmm5/imm32 5/imm32
    19441   0x11/imm32/alloc-id $Mu-register-xmm6/imm32 6/imm32
    19442   0x11/imm32/alloc-id $Mu-register-xmm7/imm32 7/imm32
    19443
    19444 # Like Mu-registers, but with unique codes for integer and floating-point
    19445 # registers.
    19446 # Don't use this for code-generation, only for checking.
    19447 Mu-registers-unique:  # (addr stream {(handle array byte), int})
    19448   # a table is a stream
    19449   0xa8/imm32/write
    19450   0/imm32/read
    19451   0xa8/imm32/length
    19452   # data
    19453   # general-purpose registers
    19454   0x11/imm32/alloc-id $Mu-register-eax/imm32 0/imm32
    19455   0x11/imm32/alloc-id $Mu-register-ecx/imm32 1/imm32
    19456   0x11/imm32/alloc-id $Mu-register-edx/imm32 2/imm32
    19457   0x11/imm32/alloc-id $Mu-register-ebx/imm32 3/imm32
    19458   0x11/imm32/alloc-id $Mu-register-esi/imm32 6/imm32
    19459   0x11/imm32/alloc-id $Mu-register-edi/imm32 7/imm32
    19460   # floating-point registers
    19461   0x11/imm32/alloc-id $Mu-register-xmm0/imm32 8/imm32
    19462   0x11/imm32/alloc-id $Mu-register-xmm1/imm32 9/imm32
    19463   0x11/imm32/alloc-id $Mu-register-xmm2/imm32 0xa/imm32
    19464   0x11/imm32/alloc-id $Mu-register-xmm3/imm32 0xb/imm32
    19465   0x11/imm32/alloc-id $Mu-register-xmm4/imm32 0xc/imm32
    19466   0x11/imm32/alloc-id $Mu-register-xmm5/imm32 0xd/imm32
    19467   0x11/imm32/alloc-id $Mu-register-xmm6/imm32 0xe/imm32
    19468   0x11/imm32/alloc-id $Mu-register-xmm7/imm32 0xf/imm32
    19469
    19470 $Mu-register-eax:
    19471   0x11/imm32/alloc-id
    19472   3/imm32/size
    19473   0x65/e 0x61/a 0x78/x
    19474
    19475 $Mu-register-ecx:
    19476   0x11/imm32/alloc-id
    19477   3/imm32/size
    19478   0x65/e 0x63/c 0x78/x
    19479
    19480 $Mu-register-edx:
    19481   0x11/imm32/alloc-id
    19482   3/imm32/size
    19483   0x65/e 0x64/d 0x78/x
    19484
    19485 $Mu-register-ebx:
    19486   0x11/imm32/alloc-id
    19487   3/imm32/size
    19488   0x65/e 0x62/b 0x78/x
    19489
    19490 $Mu-register-esi:
    19491   0x11/imm32/alloc-id
    19492   3/imm32/size
    19493   0x65/e 0x73/s 0x69/i
    19494
    19495 $Mu-register-edi:
    19496   0x11/imm32/alloc-id
    19497   3/imm32/size
    19498   0x65/e 0x64/d 0x69/i
    19499
    19500 $Mu-register-xmm0:
    19501   0x11/imm32/alloc-id:fake:payload
    19502   # "xmm0"
    19503   0x4/imm32/size
    19504   0x78/x 0x6d/m 0x6d/m 0x30/0
    19505
    19506 $Mu-register-xmm1:
    19507   0x11/imm32/alloc-id:fake:payload
    19508   # "xmm1"
    19509   0x4/imm32/size
    19510   0x78/x 0x6d/m 0x6d/m 0x31/1
    19511
    19512 $Mu-register-xmm2:
    19513   0x11/imm32/alloc-id:fake:payload
    19514   # "xmm2"
    19515   0x4/imm32/size
    19516   0x78/x 0x6d/m 0x6d/m 0x32/2
    19517
    19518 $Mu-register-xmm3:
    19519   0x11/imm32/alloc-id:fake:payload
    19520   # "xmm3"
    19521   0x4/imm32/size
    19522   0x78/x 0x6d/m 0x6d/m 0x33/3
    19523
    19524 $Mu-register-xmm4:
    19525   0x11/imm32/alloc-id:fake:payload
    19526   # "xmm4"
    19527   0x4/imm32/size
    19528   0x78/x 0x6d/m 0x6d/m 0x34/4
    19529
    19530 $Mu-register-xmm5:
    19531   0x11/imm32/alloc-id:fake:payload
    19532   # "xmm5"
    19533   0x4/imm32/size
    19534   0x78/x 0x6d/m 0x6d/m 0x35/5
    19535
    19536 $Mu-register-xmm6:
    19537   0x11/imm32/alloc-id:fake:payload
    19538   # "xmm6"
    19539   0x4/imm32/size
    19540   0x78/x 0x6d/m 0x6d/m 0x36/6
    19541
    19542 $Mu-register-xmm7:
    19543   0x11/imm32/alloc-id:fake:payload
    19544   # "xmm7"
    19545   0x4/imm32/size
    19546   0x78/x 0x6d/m 0x6d/m 0x37/7
    19547
    19548 == code
    19549
    19550 # push 'out' to 'vars' if not already there; it's assumed to be a fn output
    19551 maybe-define-var:  # out: (handle var), vars: (addr stack live-var)
    19552     # . prologue
    19553     55/push-ebp
    19554     89/<- %ebp 4/r32/esp
    19555     # . save registers
    19556     50/push-eax
    19557     # var out-addr/eax: (addr var)
    19558     (lookup *(ebp+8) *(ebp+0xc))  # => eax
    19559     #
    19560     (binding-exists? %eax *(ebp+0x10))  # => eax
    19561     3d/compare-eax-and 0/imm32/false
    19562     75/jump-if-!= $maybe-define-var:end/disp8
    19563     # otherwise update vars
    19564     (push *(ebp+0x10) *(ebp+8))
    19565     (push *(ebp+0x10) *(ebp+0xc))
    19566     (push *(ebp+0x10) 0)  # 'out' is always a fn output; never spill it
    19567 $maybe-define-var:end:
    19568     # . restore registers
    19569     58/pop-to-eax
    19570     # . epilogue
    19571     89/<- %esp 5/r32/ebp
    19572     5d/pop-to-ebp
    19573     c3/return
    19574
    19575 # simpler version of lookup-var-helper
    19576 binding-exists?:  # target: (addr var), vars: (addr stack live-var) -> result/eax: boolean
    19577     # pseudocode:
    19578     #   var curr: (addr handle var) = &vars->data[vars->top - 12]
    19579     #   var min = vars->data
    19580     #   while curr >= min
    19581     #     var v: (handle var) = *curr
    19582     #     if v->name == target->name
    19583     #       return true
    19584     #     curr -= 12
    19585     #   return false
    19586     #
    19587     # . prologue
    19588     55/push-ebp
    19589     89/<- %ebp 4/r32/esp
    19590     # . save registers
    19591     51/push-ecx
    19592     52/push-edx
    19593     56/push-esi
    19594     # var target-name/ecx: (addr array byte) = lookup(target->name)
    19595     8b/-> *(ebp+8) 0/r32/eax
    19596     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    19597     89/<- %ecx 0/r32/eax
    19598     # esi = vars
    19599     8b/-> *(ebp+0xc) 6/r32/esi
    19600     # eax = vars->top
    19601     8b/-> *esi 0/r32/eax
    19602     # var min/edx: (addr handle var) = vars->data
    19603     8d/copy-address *(esi+8) 2/r32/edx
    19604     # var curr/esi: (addr handle var) = &vars->data[vars->top - 12]
    19605     8d/copy-address *(esi+eax-4) 6/r32/esi  # vars + 8 + vars->type - 12
    19606     {
    19607 $binding-exists?:loop:
    19608       # if (curr < min) return
    19609       39/compare %esi 2/r32/edx
    19610       0f 82/jump-if-addr< break/disp32
    19611       # var v/eax: (addr var) = lookup(*curr)
    19612       (lookup *esi *(esi+4))  # => eax
    19613       # var vn/eax: (addr array byte) = lookup(v->name)
    19614       (lookup *eax *(eax+4))  # Var-name Var-name => eax
    19615       # if (vn == target-name) return true
    19616       (string-equal? %ecx %eax)  # => eax
    19617       3d/compare-eax-and 0/imm32/false
    19618       75/jump-if-!= $binding-exists?:end/disp8  # eax already contains true
    19619       # curr -= 12
    19620       81 5/subop/subtract %esi 0xc/imm32
    19621       e9/jump loop/disp32
    19622     }
    19623     b8/copy-to-eax 0/imm32/false
    19624 $binding-exists?:end:
    19625     # . restore registers
    19626     5e/pop-to-esi
    19627     5a/pop-to-edx
    19628     59/pop-to-ecx
    19629     # . epilogue
    19630     89/<- %esp 5/r32/ebp
    19631     5d/pop-to-ebp
    19632     c3/return
    19633
    19634 test-parse-mu-stmt:
    19635     # . prologue
    19636     55/push-ebp
    19637     89/<- %ebp 4/r32/esp
    19638     # setup
    19639     8b/-> *Primitive-type-ids 0/r32/eax
    19640     89/<- *Type-id 0/r32/eax  # stream-write
    19641     (clear-stream _test-input-stream)
    19642     (write _test-input-stream "increment n\n")
    19643     # var vars/ecx: (stack (addr var) 16)
    19644     81 5/subop/subtract %esp 0xc0/imm32
    19645     68/push 0xc0/imm32/size
    19646     68/push 0/imm32/top
    19647     89/<- %ecx 4/r32/esp
    19648     (clear-stack %ecx)
    19649     # var v/edx: (handle var)
    19650     68/push 0/imm32
    19651     68/push 0/imm32
    19652     89/<- %edx 4/r32/esp
    19653     # var s/eax: (handle array byte)
    19654     68/push 0/imm32
    19655     68/push 0/imm32
    19656     89/<- %eax 4/r32/esp
    19657     # v = new var("n")
    19658     (copy-array Heap "n" %eax)
    19659     (new-var Heap *eax *(eax+4) %edx)
    19660     #
    19661     (push %ecx *edx)
    19662     (push %ecx *(edx+4))
    19663     (push %ecx 0)
    19664     # var out/eax: (handle stmt)
    19665     68/push 0/imm32
    19666     68/push 0/imm32
    19667     89/<- %eax 4/r32/esp
    19668     # convert
    19669     (parse-mu-stmt _test-input-stream %ecx 0 %eax Stderr 0)
    19670     # var out-addr/edx: (addr stmt) = lookup(*out)
    19671     (lookup *eax *(eax+4))  # => eax
    19672     89/<- %edx 0/r32/eax
    19673     # out->tag
    19674     (check-ints-equal *edx 1 "F - test-parse-mu-stmt/tag")  # Stmt-tag is Stmt1
    19675     # out->operation
    19676     (lookup *(edx+4) *(edx+8))  # Stmt1-operation Stmt1-operation => eax
    19677     (check-strings-equal %eax "increment" "F - test-parse-mu-stmt/name")  # Stmt1-operation
    19678     # out->inouts->value->name
    19679     # . eax = out->inouts
    19680     (lookup *(edx+0xc) *(edx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    19681     # . eax = out->inouts->value
    19682     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    19683     # . eax = out->inouts->value->name
    19684     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    19685     # .
    19686     (check-strings-equal %eax "n" "F - test-parse-mu-stmt/inout:0")
    19687     # . epilogue
    19688     89/<- %esp 5/r32/ebp
    19689     5d/pop-to-ebp
    19690     c3/return
    19691
    19692 test-parse-mu-stmt-with-comma:
    19693     # . prologue
    19694     55/push-ebp
    19695     89/<- %ebp 4/r32/esp
    19696     # setup
    19697     8b/-> *Primitive-type-ids 0/r32/eax
    19698     89/<- *Type-id 0/r32/eax  # stream-write
    19699     (clear-stream _test-input-stream)
    19700     (write _test-input-stream "copy-to n, 3\n")
    19701     # var vars/ecx: (stack (addr var) 16)
    19702     81 5/subop/subtract %esp 0xc0/imm32
    19703     68/push 0xc0/imm32/size
    19704     68/push 0/imm32/top
    19705     89/<- %ecx 4/r32/esp
    19706     (clear-stack %ecx)
    19707     # var v/edx: (handle var)
    19708     68/push 0/imm32
    19709     68/push 0/imm32
    19710     89/<- %edx 4/r32/esp
    19711     # var s/eax: (handle array byte)
    19712     68/push 0/imm32
    19713     68/push 0/imm32
    19714     89/<- %eax 4/r32/esp
    19715     # v = new var("n")
    19716     (copy-array Heap "n" %eax)
    19717     (new-var Heap *eax *(eax+4) %edx)
    19718     #
    19719     (push %ecx *edx)
    19720     (push %ecx *(edx+4))
    19721     (push %ecx 0)
    19722     # var out/eax: (handle stmt)
    19723     68/push 0/imm32
    19724     68/push 0/imm32
    19725     89/<- %eax 4/r32/esp
    19726     # convert
    19727     (parse-mu-stmt _test-input-stream %ecx 0 %eax Stderr 0)
    19728     # var out-addr/edx: (addr stmt) = lookup(*out)
    19729     (lookup *eax *(eax+4))  # => eax
    19730     89/<- %edx 0/r32/eax
    19731     # out->tag
    19732     (check-ints-equal *edx 1 "F - test-parse-mu-stmt-with-comma/tag")  # Stmt-tag is Stmt1
    19733     # out->operation
    19734     (lookup *(edx+4) *(edx+8))  # Stmt1-operation Stmt1-operation => eax
    19735     (check-strings-equal %eax "copy-to" "F - test-parse-mu-stmt-with-comma/name")  # Stmt1-operation
    19736     # out->inouts->value->name
    19737     # . eax = out->inouts
    19738     (lookup *(edx+0xc) *(edx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    19739     # . eax = out->inouts->value
    19740     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    19741     # . eax = out->inouts->value->name
    19742     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    19743     # .
    19744     (check-strings-equal %eax "n" "F - test-parse-mu-stmt-with-comma/inout:0")
    19745     # . epilogue
    19746     89/<- %esp 5/r32/ebp
    19747     5d/pop-to-ebp
    19748     c3/return
    19749
    19750 new-var:  # ad: (addr allocation-descriptor), name: (handle array byte), out: (addr handle var)
    19751     # . prologue
    19752     55/push-ebp
    19753     89/<- %ebp 4/r32/esp
    19754     # . save registers
    19755     50/push-eax
    19756     51/push-ecx
    19757     # ecx = out
    19758     8b/-> *(ebp+0x14) 1/r32/ecx
    19759     #
    19760     (allocate *(ebp+8) *Var-size %ecx)
    19761     # var out-addr/eax: (addr var)
    19762     (lookup *ecx *(ecx+4))  # => eax
    19763     # out-addr->name = name
    19764     8b/-> *(ebp+0xc) 1/r32/ecx
    19765     89/<- *eax 1/r32/ecx  # Var-name
    19766     8b/-> *(ebp+0x10) 1/r32/ecx
    19767     89/<- *(eax+4) 1/r32/ecx  # Var-name
    19768 #?     (write-buffered Stderr "var ")
    19769 #?     (lookup *(ebp+0xc) *(ebp+0x10))
    19770 #?     (write-buffered Stderr %eax)
    19771 #?     (write-buffered Stderr " at ")
    19772 #?     8b/-> *(ebp+0x14) 1/r32/ecx
    19773 #?     (lookup *ecx *(ecx+4))  # => eax
    19774 #?     (write-int32-hex-buffered Stderr %eax)
    19775 #?     (write-buffered Stderr Newline)
    19776 #?     (flush Stderr)
    19777 $new-var:end:
    19778     # . restore registers
    19779     59/pop-to-ecx
    19780     58/pop-to-eax
    19781     # . epilogue
    19782     89/<- %esp 5/r32/ebp
    19783     5d/pop-to-ebp
    19784     c3/return
    19785
    19786 # WARNING: modifies name
    19787 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)
    19788     # . prologue
    19789     55/push-ebp
    19790     89/<- %ebp 4/r32/esp
    19791     # . save registers
    19792     50/push-eax
    19793     51/push-ecx
    19794     # first strip out metadata
    19795     8b/-> *(ebp+0xc) 1/r32/ecx
    19796     (next-token-from-slice *ecx *(ecx+4) 0x2f *(ebp+0xc))
    19797     # if (!is-hex-int?(name)) abort
    19798     (hex-int? *(ebp+0xc))  # => eax
    19799     3d/compare-eax-and 0/imm32/false
    19800     0f 84/jump-if-= $new-literal-integer:abort/disp32
    19801     # a little more error-checking
    19802     (check-mu-hex-int *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
    19803     # out = new var(s)
    19804     (new-var-from-slice *(ebp+8) *(ebp+0xc) *(ebp+0x10))
    19805     # var out-addr/ecx: (addr var) = lookup(*out)
    19806     8b/-> *(ebp+0x10) 0/r32/eax
    19807     (lookup *eax *(eax+4))  # => eax
    19808     89/<- %ecx 0/r32/eax
    19809     # out-addr->block-depth = *Curr-block-depth
    19810     8b/-> *Curr-block-depth 0/r32/eax
    19811     89/<- *(ecx+0x10) 0/r32/eax  # Var-block-depth
    19812     # out-addr->type = new tree()
    19813     8d/copy-address *(ecx+8) 0/r32/eax  # Var-type
    19814     (allocate *(ebp+8) *Type-tree-size %eax)
    19815     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
    19816     c7 0/subop/copy *eax 1/imm32/true  # Type-tree-is-atom
    19817     # nothing else to do; default type is 'literal'
    19818 $new-literal-integer:end:
    19819     # . reclaim locals
    19820     81 0/subop/add %esp 8/imm32
    19821     # . restore registers
    19822     59/pop-to-ecx
    19823     58/pop-to-eax
    19824     # . epilogue
    19825     89/<- %esp 5/r32/ebp
    19826     5d/pop-to-ebp
    19827     c3/return
    19828
    19829 $new-literal-integer:abort:
    19830     (write-buffered *(ebp+0x18) "fn ")
    19831     8b/-> *(ebp+0x14) 0/r32/eax
    19832     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    19833     (write-buffered *(ebp+0x18) %eax)
    19834     (write-buffered *(ebp+0x18) ": variable '")
    19835     (write-slice-buffered *(ebp+0x18) *(ebp+0xc))
    19836     (write-buffered *(ebp+0x18) "' cannot begin with a digit (or do you have a typo in a number?)\n")
    19837     (flush *(ebp+0x18))
    19838     (stop *(ebp+0x1c) 1)
    19839     # never gets here
    19840
    19841 # precondition: name is a valid hex integer; require a '0x' prefix
    19842 check-mu-hex-int:  # name: (addr slice), err: (addr buffered-file), ed: (addr exit-descriptor)
    19843     # . prologue
    19844     55/push-ebp
    19845     89/<- %ebp 4/r32/esp
    19846     # . save registers
    19847     50/push-eax
    19848     51/push-ecx
    19849     52/push-edx
    19850     # ecx = name
    19851     8b/-> *(ebp+8) 1/r32/ecx
    19852     # var start/edx: (addr byte) = name->start
    19853     8b/-> *ecx 2/r32/edx
    19854     # if (*start == '-') ++start
    19855     b8/copy-to-eax 0/imm32
    19856     8a/copy-byte *edx 0/r32/AL
    19857     3d/compare-eax-and 0x2d/imm32/dash
    19858     {
    19859       75/jump-if-!= break/disp8
    19860       42/increment-edx
    19861     }
    19862     # var end/ecx: (addr byte) = name->end
    19863     8b/-> *(ecx+4) 1/r32/ecx
    19864     # var len/eax: int = name->end - name->start
    19865     89/<- %eax 1/r32/ecx
    19866     29/subtract-from %eax 2/r32/edx
    19867     # if (len <= 1) return
    19868     3d/compare-eax-with 1/imm32
    19869     0f 8e/jump-if-<= $check-mu-hex-int:end/disp32
    19870 $check-mu-hex-int:length->-1:
    19871     # if slice-starts-with?({start, end}, "0x") return
    19872     # . var tmp = {start, end}
    19873     51/push-ecx
    19874     52/push-edx
    19875     89/<- %eax 4/r32/esp
    19876     # .
    19877     (slice-starts-with? %eax "0x")  # => eax
    19878     # . reclaim tmp
    19879     81 0/subop/add %esp 8/imm32
    19880     # .
    19881     3d/compare-eax-with 0/imm32/false
    19882     75/jump-if-!= $check-mu-hex-int:end/disp8
    19883 $check-mu-hex-int:abort:
    19884     # otherwise abort
    19885     (write-buffered *(ebp+0xc) "literal integers are always hex in Mu; start '")
    19886     (write-slice-buffered *(ebp+0xc) *(ebp+8))
    19887     (write-buffered *(ebp+0xc) "' with a '0x' to be unambiguous, converting it to hexadecimal as necessary.\n")
    19888     (flush *(ebp+0xc))
    19889     (stop *(ebp+0x10) 1)
    19890 $check-mu-hex-int:end:
    19891     # . restore registers
    19892     5a/pop-to-edx
    19893     59/pop-to-ecx
    19894     58/pop-to-eax
    19895     # . epilogue
    19896     89/<- %esp 5/r32/ebp
    19897     5d/pop-to-ebp
    19898     c3/return
    19899
    19900 new-literal:  # ad: (addr allocation-descriptor), name: (addr slice), out: (addr handle var)
    19901     # . prologue
    19902     55/push-ebp
    19903     89/<- %ebp 4/r32/esp
    19904     # . save registers
    19905     50/push-eax
    19906     51/push-ecx
    19907     # var s/ecx: (handle array byte)
    19908     68/push 0/imm32
    19909     68/push 0/imm32
    19910     89/<- %ecx 4/r32/esp
    19911     # s = slice-to-string(name)
    19912     (slice-to-string Heap *(ebp+0xc) %ecx)
    19913     # allocate to out
    19914     (new-var *(ebp+8) *ecx *(ecx+4) *(ebp+0x10))
    19915     # var out-addr/ecx: (addr var) = lookup(*out)
    19916     8b/-> *(ebp+0x10) 1/r32/ecx
    19917     (lookup *ecx *(ecx+4))  # => eax
    19918     89/<- %ecx 0/r32/eax
    19919     # out-addr->block-depth = *Curr-block-depth
    19920     8b/-> *Curr-block-depth 0/r32/eax
    19921     89/<- *(ecx+0x10) 0/r32/eax  # Var-block-depth
    19922     # out-addr->type/eax = new type
    19923     8d/copy-address *(ecx+8) 0/r32/eax  # Var-type
    19924     (allocate *(ebp+8) *Type-tree-size %eax)
    19925     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
    19926     # nothing else to do; default type is 'literal'
    19927     c7 0/subop/copy *eax 1/imm32/true  # Type-tree-is-atom
    19928 $new-literal:end:
    19929     # . reclaim locals
    19930     81 0/subop/add %esp 8/imm32
    19931     # . restore registers
    19932     59/pop-to-ecx
    19933     58/pop-to-eax
    19934     # . epilogue
    19935     89/<- %esp 5/r32/ebp
    19936     5d/pop-to-ebp
    19937     c3/return
    19938
    19939 new-literal-string:  # ad: (addr allocation-descriptor), name: (addr slice), out: (addr handle var)
    19940     # . prologue
    19941     55/push-ebp
    19942     89/<- %ebp 4/r32/esp
    19943     # . save registers
    19944     50/push-eax
    19945     51/push-ecx
    19946     # var s/ecx: (handle array byte)
    19947     68/push 0/imm32
    19948     68/push 0/imm32
    19949     89/<- %ecx 4/r32/esp
    19950     # s = slice-to-string(name)
    19951     (slice-to-string Heap *(ebp+0xc) %ecx)
    19952     # allocate to out
    19953     (new-var *(ebp+8) *ecx *(ecx+4) *(ebp+0x10))
    19954     # var out-addr/ecx: (addr var) = lookup(*out)
    19955     8b/-> *(ebp+0x10) 1/r32/ecx
    19956     (lookup *ecx *(ecx+4))  # => eax
    19957     89/<- %ecx 0/r32/eax
    19958     # out-addr->block-depth = *Curr-block-depth
    19959     8b/-> *Curr-block-depth 0/r32/eax
    19960     89/<- *(ecx+0x10) 0/r32/eax  # Var-block-depth
    19961     # out-addr->type/eax = new type
    19962     8d/copy-address *(ecx+8) 0/r32/eax  # Var-type
    19963     (allocate *(ebp+8) *Type-tree-size %eax)
    19964     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
    19965     # out-addr->type->value = literal-string
    19966     c7 0/subop/copy *(eax+4) 0x10/imm32/type-id-string-literal  # Type-tree-value
    19967     # out-addr->type->is-atom? = true
    19968     c7 0/subop/copy *eax 1/imm32/true  # Type-tree-is-atom
    19969 $new-literal-string:end:
    19970     # . reclaim locals
    19971     81 0/subop/add %esp 8/imm32
    19972     # . restore registers
    19973     59/pop-to-ecx
    19974     58/pop-to-eax
    19975     # . epilogue
    19976     89/<- %esp 5/r32/ebp
    19977     5d/pop-to-ebp
    19978     c3/return
    19979
    19980 new-var-from-slice:  # ad: (addr allocation-descriptor), name: (addr slice), out: (addr handle var)
    19981     # . prologue
    19982     55/push-ebp
    19983     89/<- %ebp 4/r32/esp
    19984     # . save registers
    19985     51/push-ecx
    19986     # var tmp/ecx: (handle array byte)
    19987     68/push 0/imm32
    19988     68/push 0/imm32
    19989     89/<- %ecx 4/r32/esp
    19990     # tmp = slice-to-string(name)
    19991     (slice-to-string Heap *(ebp+0xc) %ecx)
    19992     # out = new-var(tmp)
    19993     (new-var *(ebp+8) *ecx *(ecx+4) *(ebp+0x10))
    19994 $new-var-from-slice:end:
    19995     # . reclaim locals
    19996     81 0/subop/add %esp 8/imm32
    19997     # . restore registers
    19998     59/pop-to-ecx
    19999     # . epilogue
    20000     89/<- %esp 5/r32/ebp
    20001     5d/pop-to-ebp
    20002     c3/return
    20003
    20004 new-var-def:  # ad: (addr allocation-descriptor), var: (handle var), out: (addr handle stmt)
    20005     # . prologue
    20006     55/push-ebp
    20007     89/<- %ebp 4/r32/esp
    20008     # . save registers
    20009     50/push-eax
    20010     51/push-ecx
    20011     #
    20012     (allocate *(ebp+8) *Stmt-size *(ebp+0x14))
    20013     # var out-addr/eax: (addr stmt) = lookup(*out)
    20014     8b/-> *(ebp+0x14) 0/r32/eax
    20015     (lookup *eax *(eax+4))  # => eax
    20016     # out-addr->tag = stmt
    20017     c7 0/subop/copy *eax 2/imm32/tag/var-on-stack  # Stmt-tag
    20018     # result->var = var
    20019     8b/-> *(ebp+0xc) 1/r32/ecx
    20020     89/<- *(eax+4) 1/r32/ecx  # Vardef-var
    20021     8b/-> *(ebp+0x10) 1/r32/ecx
    20022     89/<- *(eax+8) 1/r32/ecx  # Vardef-var
    20023 $new-var-def:end:
    20024     # . restore registers
    20025     59/pop-to-ecx
    20026     58/pop-to-eax
    20027     # . epilogue
    20028     89/<- %esp 5/r32/ebp
    20029     5d/pop-to-ebp
    20030     c3/return
    20031
    20032 new-reg-var-def:  # ad: (addr allocation-descriptor), var: (handle var), out: (addr handle stmt)
    20033     # . prologue
    20034     55/push-ebp
    20035     89/<- %ebp 4/r32/esp
    20036     # . save registers
    20037     50/push-eax
    20038     # eax = out
    20039     8b/-> *(ebp+0x14) 0/r32/eax
    20040     #
    20041     (allocate *(ebp+8) *Stmt-size %eax)
    20042     # var out-addr/eax: (addr stmt) = lookup(*out)
    20043     (lookup *eax *(eax+4))  # => eax
    20044     # set tag
    20045     c7 0/subop/copy *eax 3/imm32/tag/var-in-register  # Stmt-tag
    20046     # set output
    20047     8d/copy-address *(eax+0x14) 0/r32/eax  # Regvardef-outputs
    20048     (append-stmt-var Heap  *(ebp+0xc) *(ebp+0x10)  0 0  0  %eax)
    20049 $new-reg-var-def:end:
    20050     # . restore registers
    20051     58/pop-to-eax
    20052     # . epilogue
    20053     89/<- %esp 5/r32/ebp
    20054     5d/pop-to-ebp
    20055     c3/return
    20056
    20057 append-list:  # ad: (addr allocation-descriptor), value: (handle _type), list: (handle list _type), out: (addr handle list _type)
    20058     # . prologue
    20059     55/push-ebp
    20060     89/<- %ebp 4/r32/esp
    20061     # . save registers
    20062     50/push-eax
    20063     51/push-ecx
    20064     57/push-edi
    20065     # edi = out
    20066     8b/-> *(ebp+0x1c) 7/r32/edi
    20067     # *out = new list
    20068     (allocate *(ebp+8) *List-size %edi)
    20069     # var out-addr/edi: (addr list _type) = lookup(*out)
    20070     (lookup *edi *(edi+4))  # => eax
    20071     89/<- %edi 0/r32/eax
    20072     # out-addr->value = value
    20073     8b/-> *(ebp+0xc) 0/r32/eax
    20074     89/<- *edi 0/r32/eax  # List-value
    20075     8b/-> *(ebp+0x10) 0/r32/eax
    20076     89/<- *(edi+4) 0/r32/eax  # List-value
    20077     # if (list == null) return
    20078     81 7/subop/compare *(ebp+0x14) 0/imm32
    20079     74/jump-if-= $append-list:end/disp8
    20080     # otherwise append
    20081 $append-list:non-empty-list:
    20082     # var curr/eax: (addr list _type) = lookup(list)
    20083     (lookup *(ebp+0x14) *(ebp+0x18))  # => eax
    20084     # while (curr->next != null) curr = curr->next
    20085     {
    20086       81 7/subop/compare *(eax+8) 0/imm32  # List-next
    20087       74/jump-if-= break/disp8
    20088       # curr = lookup(curr->next)
    20089       (lookup *(eax+8) *(eax+0xc))  # List-next, List-next => eax
    20090       #
    20091       eb/jump loop/disp8
    20092     }
    20093     # edi = out
    20094     8b/-> *(ebp+0x1c) 7/r32/edi
    20095     # curr->next = out
    20096     8b/-> *edi 1/r32/ecx
    20097     89/<- *(eax+8) 1/r32/ecx  # List-next
    20098     8b/-> *(edi+4) 1/r32/ecx
    20099     89/<- *(eax+0xc) 1/r32/ecx  # List-next
    20100     # out = list
    20101     8b/-> *(ebp+0x14) 1/r32/ecx
    20102     89/<- *edi 1/r32/ecx
    20103     8b/-> *(ebp+0x18) 1/r32/ecx
    20104     89/<- *(edi+4) 1/r32/ecx
    20105 $append-list:end:
    20106     # . restore registers
    20107     5f/pop-to-edi
    20108     59/pop-to-ecx
    20109     58/pop-to-eax
    20110     # . epilogue
    20111     89/<- %esp 5/r32/ebp
    20112     5d/pop-to-ebp
    20113     c3/return
    20114
    20115 append-stmt-var:  # ad: (addr allocation-descriptor), v: (handle var), vars: (handle stmt-var), is-deref?: boolean, out: (addr handle stmt-var)
    20116     # . prologue
    20117     55/push-ebp
    20118     89/<- %ebp 4/r32/esp
    20119     # . save registers
    20120     50/push-eax
    20121     51/push-ecx
    20122     57/push-edi
    20123     # edi = out
    20124     8b/-> *(ebp+0x20) 7/r32/edi
    20125     # out = new stmt-var
    20126     (allocate *(ebp+8) *Stmt-var-size %edi)
    20127     # var out-addr/ecx: (addr stmt-var) = lookup(*out)
    20128     (lookup *edi *(edi+4))  # => eax
    20129     89/<- %ecx 0/r32/eax
    20130     # out-addr->value = v
    20131     8b/-> *(ebp+0xc) 0/r32/eax
    20132     89/<- *ecx 0/r32/eax  # Stmt-var-value
    20133     8b/-> *(ebp+0x10) 0/r32/eax
    20134     89/<- *(ecx+4) 0/r32/eax  # Stmt-var-value
    20135     # out-addr->is-deref? = is-deref?
    20136     8b/-> *(ebp+0x1c) 0/r32/eax
    20137     89/<- *(ecx+0x10) 0/r32/eax  # Stmt-var-is-deref
    20138     # if (vars == null) return result
    20139     81 7/subop/compare *(ebp+0x14) 0/imm32/null
    20140     74/jump-if-= $append-stmt-var:end/disp8
    20141     # otherwise append
    20142     # var curr/eax: (addr stmt-var) = lookup(vars)
    20143     (lookup *(ebp+0x14) *(ebp+0x18))  # => eax
    20144     # while (curr->next != null) curr = curr->next
    20145     {
    20146       81 7/subop/compare *(eax+8) 0/imm32  # Stmt-var-next
    20147       74/jump-if-= break/disp8
    20148       # curr = lookup(curr->next)
    20149       (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next, Stmt-var-next => eax
    20150       #
    20151       eb/jump loop/disp8
    20152     }
    20153     # curr->next = out
    20154     8b/-> *edi 1/r32/ecx
    20155     89/<- *(eax+8) 1/r32/ecx  # Stmt-var-next
    20156     8b/-> *(edi+4) 1/r32/ecx
    20157     89/<- *(eax+0xc) 1/r32/ecx  # Stmt-var-next
    20158     # out = vars
    20159     8b/-> *(ebp+0x14) 1/r32/ecx
    20160     89/<- *edi 1/r32/ecx
    20161     8b/-> *(ebp+0x18) 1/r32/ecx
    20162     89/<- *(edi+4) 1/r32/ecx
    20163 $append-stmt-var:end:
    20164     # . restore registers
    20165     5f/pop-to-edi
    20166     59/pop-to-ecx
    20167     58/pop-to-eax
    20168     # . epilogue
    20169     89/<- %esp 5/r32/ebp
    20170     5d/pop-to-ebp
    20171     c3/return
    20172
    20173 append-to-block:  # ad: (addr allocation-descriptor), block: (addr block), x: (handle stmt)
    20174     # . prologue
    20175     55/push-ebp
    20176     89/<- %ebp 4/r32/esp
    20177     # . save registers
    20178     50/push-eax
    20179     56/push-esi
    20180     # esi = block
    20181     8b/-> *(ebp+0xc) 6/r32/esi
    20182     # block->stmts = append(x, block->stmts)
    20183     8d/copy-address *(esi+4) 0/r32/eax  # Block-stmts
    20184     (append-list *(ebp+8)  *(ebp+0x10) *(ebp+0x14)  *(esi+4) *(esi+8)  %eax)  # ad, x, x, Block-stmts, Block-stmts
    20185 $append-to-block:end:
    20186     # . restore registers
    20187     5e/pop-to-esi
    20188     58/pop-to-eax
    20189     # . epilogue
    20190     89/<- %esp 5/r32/ebp
    20191     5d/pop-to-ebp
    20192     c3/return
    20193
    20194 ## Parsing types
    20195 # We need to create metadata on user-defined types, and we need to use this
    20196 # metadata as we parse instructions.
    20197 # However, we also want to allow types to be used before their definitions.
    20198 # This means we can't ever assume any type data structures exist.
    20199
    20200 lookup-or-create-constant:  # container: (addr stmt-var), field-name: (addr slice), out: (addr handle var)
    20201     # . prologue
    20202     55/push-ebp
    20203     89/<- %ebp 4/r32/esp
    20204     # . save registers
    20205     50/push-eax
    20206     56/push-esi
    20207     # var container-type/esi: type-id
    20208     (container-type *(ebp+8))  # => eax
    20209     89/<- %esi 0/r32/eax
    20210     # var tmp/eax: (handle typeinfo) = find-or-create-typeinfo(container-type)
    20211     68/push 0/imm32
    20212     68/push 0/imm32
    20213     89/<- %eax 4/r32/esp
    20214     (find-or-create-typeinfo %esi %eax)
    20215     # var tmp-addr/eax: (addr typeinfo) = lookup(tmp)
    20216     (lookup *eax *(eax+4))  # => eax
    20217     # result = find-or-create-typeinfo-output-var(typeinfo, field-name)
    20218 #?     (write-buffered Stderr "constant: ")
    20219 #?     (write-slice-buffered Stderr *(ebp+0xc))
    20220 #?     (write-buffered Stderr Newline)
    20221 #?     (flush Stderr)
    20222     (find-or-create-typeinfo-output-var %eax *(ebp+0xc) *(ebp+0x10))
    20223 #?     8b/-> *(ebp+0x10) 0/r32/eax
    20224 #?     (write-buffered Stderr "@")
    20225 #?     (lookup *eax *(eax+4))
    20226 #?     (write-int32-hex-buffered Stderr %eax)
    20227 #?     (lookup *eax *(eax+4))
    20228 #?     (write-buffered Stderr %eax)
    20229 #?     (write-buffered Stderr Newline)
    20230 #?     (flush Stderr)
    20231 #?     (write-buffered Stderr "offset: ")
    20232 #?     8b/-> *(eax+0x14) 0/r32/eax
    20233 #?     (write-int32-hex-buffered Stderr %eax)
    20234 #?     (write-buffered Stderr Newline)
    20235 #?     (flush Stderr)
    20236 $lookup-or-create-constant:end:
    20237     # . reclaim locals
    20238     81 0/subop/add %esp 8/imm32
    20239     # . restore registers
    20240     5e/pop-to-esi
    20241     58/pop-to-eax
    20242     # . epilogue
    20243     89/<- %esp 5/r32/ebp
    20244     5d/pop-to-ebp
    20245     c3/return
    20246
    20247 # if addr var:
    20248 #   container->var->type->right->left->value
    20249 # otherwise
    20250 #   container->var->type->value
    20251 container-type:  # container: (addr stmt-var) -> result/eax: type-id
    20252     # . prologue
    20253     55/push-ebp
    20254     89/<- %ebp 4/r32/esp
    20255     #
    20256     8b/-> *(ebp+8) 0/r32/eax
    20257     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    20258     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    20259     {
    20260       81 7/subop/compare *(eax+8) 0/imm32  # Type-tree-right
    20261       74/jump-if-= break/disp8
    20262       (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
    20263       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    20264     }
    20265     8b/-> *(eax+4) 0/r32/eax  # Type-tree-value
    20266 $container-type:end:
    20267     # . epilogue
    20268     89/<- %esp 5/r32/ebp
    20269     5d/pop-to-ebp
    20270     c3/return
    20271
    20272 container?:  # t: type-id -> result/eax: boolean
    20273     # . prologue
    20274     55/push-ebp
    20275     89/<- %ebp 4/r32/esp
    20276     #
    20277     8b/-> *(ebp+8) 0/r32/eax
    20278     c1/shift 4/subop/left %eax 2/imm8
    20279     3b/compare 0/r32/eax *Primitive-type-ids
    20280     0f 9d/set-if->= %al
    20281     25/and-eax-with 0xff/imm32
    20282 $container?:end:
    20283     # . epilogue
    20284     89/<- %esp 5/r32/ebp
    20285     5d/pop-to-ebp
    20286     c3/return
    20287
    20288 find-or-create-typeinfo:  # t: type-id, out: (addr handle typeinfo)
    20289     # . prologue
    20290     55/push-ebp
    20291     89/<- %ebp 4/r32/esp
    20292     # . save registers
    20293     50/push-eax
    20294     51/push-ecx
    20295     52/push-edx
    20296     57/push-edi
    20297     # edi = out
    20298     8b/-> *(ebp+0xc) 7/r32/edi
    20299     # var fields/ecx: (handle table (handle array byte) (handle typeinfo-entry))
    20300     68/push 0/imm32
    20301     68/push 0/imm32
    20302     89/<- %ecx 4/r32/esp
    20303     # find-typeinfo(t, out)
    20304     (find-typeinfo *(ebp+8) %edi)
    20305     {
    20306       # if (*out != 0) break
    20307       81 7/subop/compare *edi 0/imm32
    20308       0f 85/jump-if-!= break/disp32
    20309 $find-or-create-typeinfo:create:
    20310       # *out = allocate
    20311       (allocate Heap *Typeinfo-size %edi)
    20312       # var tmp/eax: (addr typeinfo) = lookup(*out)
    20313       (lookup *edi *(edi+4))  # => eax
    20314 #?     (write-buffered Stderr "created typeinfo at ")
    20315 #?     (write-int32-hex-buffered Stderr %eax)
    20316 #?     (write-buffered Stderr " for type-id ")
    20317 #?     (write-int32-hex-buffered Stderr *(ebp+8))
    20318 #?     (write-buffered Stderr Newline)
    20319 #?     (flush Stderr)
    20320       # tmp->id = t
    20321       8b/-> *(ebp+8) 2/r32/edx
    20322       89/<- *eax 2/r32/edx  # Typeinfo-id
    20323       # tmp->fields = new table
    20324       # . fields = new table
    20325       (new-stream Heap 0x40 *Typeinfo-fields-row-size %ecx)
    20326       # . tmp->fields = fields
    20327       8b/-> *ecx 2/r32/edx
    20328       89/<- *(eax+4) 2/r32/edx  # Typeinfo-fields
    20329       8b/-> *(ecx+4) 2/r32/edx
    20330       89/<- *(eax+8) 2/r32/edx  # Typeinfo-fields
    20331       # tmp->next = Program->types
    20332       8b/-> *_Program-types 1/r32/ecx
    20333       89/<- *(eax+0x10) 1/r32/ecx  # Typeinfo-next
    20334       8b/-> *_Program-types->payload 1/r32/ecx
    20335       89/<- *(eax+0x14) 1/r32/ecx  # Typeinfo-next
    20336       # Program->types = out
    20337       8b/-> *edi 1/r32/ecx
    20338       89/<- *_Program-types 1/r32/ecx
    20339       8b/-> *(edi+4) 1/r32/ecx
    20340       89/<- *_Program-types->payload 1/r32/ecx
    20341     }
    20342 $find-or-create-typeinfo:end:
    20343     # . reclaim locals
    20344     81 0/subop/add %esp 8/imm32
    20345     # . restore registers
    20346     5f/pop-to-edi
    20347     5a/pop-to-edx
    20348     59/pop-to-ecx
    20349     58/pop-to-eax
    20350     # . epilogue
    20351     89/<- %esp 5/r32/ebp
    20352     5d/pop-to-ebp
    20353     c3/return
    20354
    20355 find-typeinfo:  # t: type-id, out: (addr handle typeinfo)
    20356     # . prologue
    20357     55/push-ebp
    20358     89/<- %ebp 4/r32/esp
    20359     # . save registers
    20360     50/push-eax
    20361     51/push-ecx
    20362     52/push-edx
    20363     57/push-edi
    20364     # ecx = t
    20365     8b/-> *(ebp+8) 1/r32/ecx
    20366     # edi = out
    20367     8b/-> *(ebp+0xc) 7/r32/edi
    20368     # *out = Program->types
    20369     8b/-> *_Program-types 0/r32/eax
    20370     89/<- *edi 0/r32/eax
    20371     8b/-> *_Program-types->payload 0/r32/eax
    20372     89/<- *(edi+4) 0/r32/eax
    20373     {
    20374 $find-typeinfo:loop:
    20375       # if (*out == 0) break
    20376       81 7/subop/compare *edi 0/imm32
    20377       74/jump-if-= break/disp8
    20378 $find-typeinfo:check:
    20379       # var tmp/eax: (addr typeinfo) = lookup(*out)
    20380       (lookup *edi *(edi+4))  # => eax
    20381       # if (tmp->id == t) break
    20382       39/compare *eax 1/r32/ecx  # Typeinfo-id
    20383       74/jump-if-= break/disp8
    20384 $find-typeinfo:continue:
    20385       # *out = tmp->next
    20386       8b/-> *(eax+0x10) 2/r32/edx  # Typeinfo-next
    20387       89/<- *edi 2/r32/edx
    20388       8b/-> *(eax+0x14) 2/r32/edx  # Typeinfo-next
    20389       89/<- *(edi+4) 2/r32/edx
    20390       #
    20391       eb/jump loop/disp8
    20392     }
    20393 $find-typeinfo:end:
    20394     # . restore registers
    20395     5f/pop-to-edi
    20396     5a/pop-to-edx
    20397     59/pop-to-ecx
    20398     58/pop-to-eax
    20399     # . epilogue
    20400     89/<- %esp 5/r32/ebp
    20401     5d/pop-to-ebp
    20402     c3/return
    20403
    20404 find-or-create-typeinfo-output-var:  # T: (addr typeinfo), f: (addr slice), out: (addr handle var)
    20405     # . prologue
    20406     55/push-ebp
    20407     89/<- %ebp 4/r32/esp
    20408     # . save registers
    20409     50/push-eax
    20410     52/push-edx
    20411     57/push-edi
    20412     # var dest/edi: (handle typeinfo-entry)
    20413     68/push 0/imm32
    20414     68/push 0/imm32
    20415     89/<- %edi 4/r32/esp
    20416     # find-or-create-typeinfo-fields(T, f, dest)
    20417     (find-or-create-typeinfo-fields *(ebp+8) *(ebp+0xc) %edi)
    20418     # var dest-addr/edi: (addr typeinfo-entry) = lookup(dest)
    20419     (lookup *edi *(edi+4))  # => eax
    20420     89/<- %edi 0/r32/eax
    20421     # if dest-addr->output-var doesn't exist, create it
    20422     {
    20423       81 7/subop/compare *(edi+0xc) 0/imm32  # Typeinfo-entry-output-var
    20424       0f 85/jump-if-!= break/disp32
    20425       # dest-addr->output-var = new var(dummy name, type, -1 offset)
    20426       # . var name/eax: (handle array byte) = "field"
    20427       68/push 0/imm32
    20428       68/push 0/imm32
    20429       89/<- %eax 4/r32/esp
    20430       (slice-to-string Heap *(ebp+0xc) %eax)
    20431       # . new var
    20432       8d/copy-address *(edi+0xc) 2/r32/edx
    20433       (new-var Heap  *eax *(eax+4)  %edx)
    20434       # . reclaim name
    20435       81 0/subop/add %esp 8/imm32
    20436       # var result/edx: (addr var) = lookup(dest-addr->output-var)
    20437       (lookup *(edi+0xc) *(edi+0x10))  # => eax
    20438       89/<- %edx 0/r32/eax
    20439       # result->type = new constant type
    20440       8d/copy-address *(edx+8) 0/r32/eax  # Var-type
    20441       (allocate Heap *Type-tree-size %eax)
    20442       (lookup *(edx+8) *(edx+0xc))  # => eax
    20443       c7 0/subop/copy *eax 1/imm32/true  # Type-tree-is-atom
    20444       c7 0/subop/copy *(eax+4) 6/imm32/constant  # Type-tree-value
    20445       c7 0/subop/copy *(eax+8) 0/imm32  # Type-tree-left
    20446       c7 0/subop/copy *(eax+0xc) 0/imm32  # Type-tree-right
    20447       c7 0/subop/copy *(eax+0x10) 0/imm32  # Type-tree-right
    20448       # result->offset isn't filled out yet
    20449       c7 0/subop/copy *(edx+0x14) -1/imm32/uninitialized  # Var-offset
    20450     }
    20451     # out = dest-addr->output-var
    20452     8b/-> *(ebp+0x10) 2/r32/edx
    20453     8b/-> *(edi+0xc) 0/r32/eax  # Typeinfo-entry-output-var
    20454     89/<- *edx 0/r32/eax
    20455     8b/-> *(edi+0x10) 0/r32/eax  # Typeinfo-entry-output-var
    20456     89/<- *(edx+4) 0/r32/eax
    20457 $find-or-create-typeinfo-output-var:end:
    20458     # . reclaim locals
    20459     81 0/subop/add %esp 8/imm32
    20460     # . restore registers
    20461     5f/pop-to-edi
    20462     5a/pop-to-edx
    20463     58/pop-to-eax
    20464     # . epilogue
    20465     89/<- %esp 5/r32/ebp
    20466     5d/pop-to-ebp
    20467     c3/return
    20468
    20469 find-or-create-typeinfo-fields:  # T: (addr typeinfo), f: (addr slice), out: (addr handle typeinfo-entry)
    20470     # . prologue
    20471     55/push-ebp
    20472     89/<- %ebp 4/r32/esp
    20473     # . save registers
    20474     50/push-eax
    20475     56/push-esi
    20476     57/push-edi
    20477     # eax = lookup(T->fields)
    20478     8b/-> *(ebp+8) 0/r32/eax
    20479     (lookup *(eax+4) *(eax+8))  # Typeinfo-fields Typeinfo-fields => eax
    20480     # edi = out
    20481     8b/-> *(ebp+0x10) 7/r32/edi
    20482     # var src/esi: (addr handle typeinfo-entry) = get-or-insert-slice(T->fields, f)
    20483     (get-or-insert-slice %eax *(ebp+0xc) *Typeinfo-fields-row-size Heap)  # => eax
    20484     89/<- %esi 0/r32/eax
    20485     # if src doesn't exist, allocate it
    20486     {
    20487       81 7/subop/compare *esi 0/imm32
    20488       75/jump-if-!= break/disp8
    20489       (allocate Heap *Typeinfo-entry-size %esi)
    20490 #?       (write-buffered Stderr "handle at ")
    20491 #?       (write-int32-hex-buffered Stderr %esi)
    20492 #?       (write-buffered Stderr ": ")
    20493 #?       (write-int32-hex-buffered Stderr *esi)
    20494 #?       (write-buffered Stderr " ")
    20495 #?       (write-int32-hex-buffered Stderr *(esi+4))
    20496 #?       (write-buffered Stderr Newline)
    20497 #?       (flush Stderr)
    20498 #?       (lookup *esi *(esi+4))
    20499 #?       (write-buffered Stderr "created typeinfo fields at ")
    20500 #?       (write-int32-hex-buffered Stderr %esi)
    20501 #?       (write-buffered Stderr " for ")
    20502 #?       (write-int32-hex-buffered Stderr *(ebp+8))
    20503 #?       (write-buffered Stderr Newline)
    20504 #?       (flush Stderr)
    20505     }
    20506     # *out = src
    20507     # . *edi = *src
    20508     8b/-> *esi 0/r32/eax
    20509     89/<- *edi 0/r32/eax
    20510     8b/-> *(esi+4) 0/r32/eax
    20511     89/<- *(edi+4) 0/r32/eax
    20512 $find-or-create-typeinfo-fields:end:
    20513     # . restore registers
    20514     5f/pop-to-edi
    20515     5e/pop-to-esi
    20516     58/pop-to-eax
    20517     # . epilogue
    20518     89/<- %esp 5/r32/ebp
    20519     5d/pop-to-ebp
    20520     c3/return
    20521
    20522 populate-mu-type:  # in: (addr stream byte), t: (addr typeinfo), err: (addr buffered-file), ed: (addr exit-descriptor)
    20523     # pseudocode:
    20524     #   var line: (stream byte 512)
    20525     #   curr-index = 0
    20526     #   while true
    20527     #     clear-stream(line)
    20528     #     read-line-buffered(in, line)
    20529     #     if line->write == 0
    20530     #       abort
    20531     #     word-slice = next-mu-token(line)
    20532     #     if slice-empty?(word-slice)               # end of line
    20533     #       continue
    20534     #     if slice-equal?(word-slice, "}")
    20535     #       break
    20536     #     var v: (handle var) = parse-var-with-type(word-slice, line)
    20537     #     var r: (handle typeinfo-fields) = find-or-create-typeinfo-fields(t, word-slice/v->name)
    20538     #     TODO: ensure that r->first is null
    20539     #     r->index = curr-index
    20540     #     curr-index++
    20541     #     r->input-var = v
    20542     #     if r->output-var == 0
    20543     #       r->output-var = new literal
    20544     #     TODO: ensure nothing else in line
    20545     # t->total-size-in-bytes = -2 (not yet initialized)
    20546     #
    20547     # . prologue
    20548     55/push-ebp
    20549     89/<- %ebp 4/r32/esp
    20550     # var curr-index: int at *(ebp-4)
    20551     68/push 0/imm32
    20552     # . save registers
    20553     50/push-eax
    20554     51/push-ecx
    20555     52/push-edx
    20556     53/push-ebx
    20557     56/push-esi
    20558     57/push-edi
    20559     # edi = t
    20560     8b/-> *(ebp+0xc) 7/r32/edi
    20561     # var line/ecx: (stream byte 512)
    20562     81 5/subop/subtract %esp 0x200/imm32
    20563     68/push 0x200/imm32/size
    20564     68/push 0/imm32/read
    20565     68/push 0/imm32/write
    20566     89/<- %ecx 4/r32/esp
    20567     # var word-slice/edx: slice
    20568     68/push 0/imm32/end
    20569     68/push 0/imm32/start
    20570     89/<- %edx 4/r32/esp
    20571     # var v/esi: (handle var)
    20572     68/push 0/imm32
    20573     68/push 0/imm32
    20574     89/<- %esi 4/r32/esp
    20575     # var r/ebx: (handle typeinfo-entry)
    20576     68/push 0/imm32
    20577     68/push 0/imm32
    20578     89/<- %ebx 4/r32/esp
    20579     {
    20580 $populate-mu-type:line-loop:
    20581       (clear-stream %ecx)
    20582       (read-line-buffered *(ebp+8) %ecx)
    20583       # if (line->write == 0) abort
    20584       81 7/subop/compare *ecx 0/imm32
    20585       0f 84/jump-if-= $populate-mu-type:error1/disp32
    20586 +--  6 lines: #?       # dump line -----------------------------------------------------------------------------------------------------------------------------------------
    20592       (next-mu-token %ecx %edx)
    20593       # if slice-empty?(word-slice) continue
    20594       (slice-empty? %edx)  # => eax
    20595       3d/compare-eax-and 0/imm32
    20596       0f 85/jump-if-!= loop/disp32
    20597       # if slice-equal?(word-slice, "}") break
    20598       (slice-equal? %edx "}")
    20599       3d/compare-eax-and 0/imm32
    20600       0f 85/jump-if-!= break/disp32
    20601 $populate-mu-type:parse-element:
    20602       # v = parse-var-with-type(word-slice, first-line)
    20603       # must do this first to strip the trailing ':' from word-slice before
    20604       # using it in find-or-create-typeinfo-fields below
    20605       # TODO: clean up that mutation in parse-var-with-type
    20606       (type-name *edi)  # Typeinfo-id => eax
    20607       (parse-var-with-type %edx %ecx %esi %eax *(ebp+0x10) *(ebp+0x14))
    20608       # if v is an addr, abort
    20609       (lookup *esi *(esi+4))  # => eax
    20610       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    20611       (mu-addr-type? %eax)  # => eax
    20612       3d/compare-eax-and 0/imm32/false
    20613       0f 85/jump-if-!= $populate-mu-type:error2/disp32
    20614       # if v is an array, abort  (we could support it, but initialization gets complex)
    20615       (lookup *esi *(esi+4))  # => eax
    20616       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    20617       (mu-array-type? %eax)  # => eax
    20618       3d/compare-eax-and 0/imm32/false
    20619       0f 85/jump-if-!= $populate-mu-type:error3/disp32
    20620       # if v is a byte, abort
    20621       (lookup *esi *(esi+4))  # => eax
    20622       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    20623       (simple-mu-type? %eax 8)  # byte => eax
    20624       3d/compare-eax-and 0/imm32/false
    20625       0f 85/jump-if-!= $populate-mu-type:error4/disp32
    20626       # if v is a slice, abort
    20627       (lookup *esi *(esi+4))  # => eax
    20628       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    20629       (simple-mu-type? %eax 0xc)  # slice => eax
    20630       3d/compare-eax-and 0/imm32/false
    20631       0f 85/jump-if-!= $populate-mu-type:error5/disp32
    20632       # if v is a stream, abort  (we could support it, but initialization gets even more complex)
    20633       (lookup *esi *(esi+4))  # => eax
    20634       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    20635       (mu-stream-type? %eax)  # => eax
    20636       3d/compare-eax-and 0/imm32/false
    20637       0f 85/jump-if-!= $populate-mu-type:error6/disp32
    20638       # var tmp/ecx
    20639       51/push-ecx
    20640 $populate-mu-type:create-typeinfo-fields:
    20641       # var r/ebx: (handle typeinfo-entry)
    20642       (find-or-create-typeinfo-fields %edi %edx %ebx)
    20643       # r->index = curr-index
    20644       (lookup *ebx *(ebx+4))  # => eax
    20645       8b/-> *(ebp-4) 1/r32/ecx
    20646 #?       (write-buffered Stderr "saving index ")
    20647 #?       (write-int32-hex-buffered Stderr %ecx)
    20648 #?       (write-buffered Stderr " at ")
    20649 #?       (write-int32-hex-buffered Stderr %edi)
    20650 #?       (write-buffered Stderr Newline)
    20651 #?       (flush Stderr)
    20652       89/<- *(eax+8) 1/r32/ecx  # Typeinfo-entry-index
    20653       # ++curr-index
    20654       ff 0/subop/increment *(ebp-4)
    20655 $populate-mu-type:set-input-type:
    20656       # r->input-var = v
    20657       8b/-> *esi 1/r32/ecx
    20658       89/<- *eax 1/r32/ecx  # Typeinfo-entry-input-var
    20659       8b/-> *(esi+4) 1/r32/ecx
    20660       89/<- *(eax+4) 1/r32/ecx  # Typeinfo-entry-input-var
    20661       # restore line
    20662       59/pop-to-ecx
    20663       {
    20664 $populate-mu-type:create-output-type:
    20665         # if (r->output-var == 0) create a new var with some placeholder data
    20666         81 7/subop/compare *(eax+0xc) 0/imm32  # Typeinfo-entry-output-var
    20667         75/jump-if-!= break/disp8
    20668         8d/copy-address *(eax+0xc) 0/r32/eax  # Typeinfo-entry-output-var
    20669         (new-literal Heap %edx %eax)
    20670       }
    20671       e9/jump loop/disp32
    20672     }
    20673 $populate-mu-type:invalidate-total-size-in-bytes:
    20674     # Offsets and total size may not be accurate here since we may not yet
    20675     # have encountered the element types.
    20676     # We'll recompute them separately after parsing the entire program.
    20677     c7 0/subop/copy *(edi+0xc) -2/imm32/uninitialized  # Typeinfo-total-size-in-bytes
    20678 $populate-mu-type:end:
    20679     # . reclaim locals
    20680     81 0/subop/add %esp 0x224/imm32
    20681     # . restore registers
    20682     5f/pop-to-edi
    20683     5e/pop-to-esi
    20684     5b/pop-to-ebx
    20685     5a/pop-to-edx
    20686     59/pop-to-ecx
    20687     58/pop-to-eax
    20688     # reclaim curr-index
    20689     81 0/subop/add %esp 4/imm32
    20690     # . epilogue
    20691     89/<- %esp 5/r32/ebp
    20692     5d/pop-to-ebp
    20693     c3/return
    20694
    20695 $populate-mu-type:error1:
    20696     # error("incomplete type definition '" t->name "'\n")
    20697     (write-buffered *(ebp+0x10) "incomplete type definition '")
    20698     (type-name *edi)  # Typeinfo-id => eax
    20699     (write-buffered *(ebp+0x10) %eax)
    20700     (write-buffered *(ebp+0x10) "\n")
    20701     (flush *(ebp+0x10))
    20702     (stop *(ebp+0x14) 1)
    20703     # never gets here
    20704
    20705 $populate-mu-type:error2:
    20706     (write-buffered *(ebp+0x10) "type ")
    20707     (type-name *edi)  # Typeinfo-id => eax
    20708     (write-buffered *(ebp+0x10) %eax)
    20709     (write-buffered *(ebp+0x10) ": 'addr' elements not allowed\n")
    20710     (flush *(ebp+0x10))
    20711     (stop *(ebp+0x14) 1)
    20712     # never gets here
    20713
    20714 $populate-mu-type:error3:
    20715     (write-buffered *(ebp+0x10) "type ")
    20716     (type-name *edi)  # Typeinfo-id => eax
    20717     (write-buffered *(ebp+0x10) %eax)
    20718     (write-buffered *(ebp+0x10) ": 'array' elements not allowed for now\n")
    20719     (flush *(ebp+0x10))
    20720     (stop *(ebp+0x14) 1)
    20721     # never gets here
    20722
    20723 $populate-mu-type:error4:
    20724     (write-buffered *(ebp+0x10) "type ")
    20725     (type-name *edi)  # Typeinfo-id => eax
    20726     (write-buffered *(ebp+0x10) %eax)
    20727     (write-buffered *(ebp+0x10) ": 'byte' elements not allowed\n")
    20728     (flush *(ebp+0x10))
    20729     (stop *(ebp+0x14) 1)
    20730     # never gets here
    20731
    20732 $populate-mu-type:error5:
    20733     (write-buffered *(ebp+0x10) "type ")
    20734     (type-name *edi)  # Typeinfo-id => eax
    20735     (write-buffered *(ebp+0x10) %eax)
    20736     (write-buffered *(ebp+0x10) ": 'slice' elements not allowed\n")
    20737     (flush *(ebp+0x10))
    20738     (stop *(ebp+0x14) 1)
    20739     # never gets here
    20740
    20741 $populate-mu-type:error6:
    20742     (write-buffered *(ebp+0x10) "type ")
    20743     (type-name *edi)  # Typeinfo-id => eax
    20744     (write-buffered *(ebp+0x10) %eax)
    20745     (write-buffered *(ebp+0x10) ": 'stream' elements not allowed for now\n")
    20746     (flush *(ebp+0x10))
    20747     (stop *(ebp+0x14) 1)
    20748     # never gets here
    20749
    20750 type-name:  # index: int -> result/eax: (addr array byte)
    20751     # . prologue
    20752     55/push-ebp
    20753     89/<- %ebp 4/r32/esp
    20754     #
    20755     (index Type-id *(ebp+8))
    20756 $type-name:end:
    20757     # . epilogue
    20758     89/<- %esp 5/r32/ebp
    20759     5d/pop-to-ebp
    20760     c3/return
    20761
    20762 index:  # arr: (addr stream (handle array byte)), index: int -> result/eax: (addr array byte)
    20763     # . prologue
    20764     55/push-ebp
    20765     89/<- %ebp 4/r32/esp
    20766     # . save registers
    20767     56/push-esi
    20768     # TODO: bounds-check index
    20769     # esi = arr
    20770     8b/-> *(ebp+8) 6/r32/esi
    20771     # eax = index
    20772     8b/-> *(ebp+0xc) 0/r32/eax
    20773     # eax = *(arr + 12 + index)
    20774     8b/-> *(esi+eax<<2+0xc) 0/r32/eax
    20775 $index:end:
    20776     # . restore registers
    20777     5e/pop-to-esi
    20778     # . epilogue
    20779     89/<- %esp 5/r32/ebp
    20780     5d/pop-to-ebp
    20781     c3/return
    20782
    20783 #######################################################
    20784 # Compute type sizes
    20785 #######################################################
    20786
    20787 # Compute the sizes of all user-defined types.
    20788 # We'll need the sizes of their elements, which may be other user-defined
    20789 # types, which we will compute as needed.
    20790
    20791 # Initially, all user-defined types have their sizes set to -2 (invalid)
    20792 populate-mu-type-sizes:  # err: (addr buffered-file), ed: (addr exit-descriptor)
    20793     # . prologue
    20794     55/push-ebp
    20795     89/<- %ebp 4/r32/esp
    20796 $populate-mu-type-sizes:total-sizes:
    20797     # var curr/eax: (addr typeinfo) = lookup(Program->types)
    20798     (lookup *_Program-types *_Program-types->payload)  # => eax
    20799     {
    20800       # if (curr == null) break
    20801       3d/compare-eax-and 0/imm32/null
    20802       74/jump-if-= break/disp8
    20803       (populate-mu-type-sizes-in-type %eax *(ebp+8) *(ebp+0xc))
    20804       # curr = lookup(curr->next)
    20805       (lookup *(eax+0x10) *(eax+0x14))  # Typeinfo-next Typeinfo-next => eax
    20806       eb/jump loop/disp8
    20807     }
    20808 $populate-mu-type-sizes:offsets:
    20809     # curr = *Program->types
    20810     (lookup *_Program-types *_Program-types->payload)  # => eax
    20811     {
    20812       # if (curr == null) break
    20813       3d/compare-eax-and 0/imm32/null
    20814       74/jump-if-= break/disp8
    20815       (populate-mu-type-offsets %eax *(ebp+8) *(ebp+0xc))
    20816       # curr = curr->next
    20817       (lookup *(eax+0x10) *(eax+0x14))  # Typeinfo-next Typeinfo-next => eax
    20818       eb/jump loop/disp8
    20819     }
    20820 $populate-mu-type-sizes:end:
    20821     # . epilogue
    20822     89/<- %esp 5/r32/ebp
    20823     5d/pop-to-ebp
    20824     c3/return
    20825
    20826 # compute sizes of all fields, recursing as necessary
    20827 # sum up all their sizes to arrive at total size
    20828 # fields may be out of order, but that doesn't affect the answer
    20829 populate-mu-type-sizes-in-type:  # T: (addr typeinfo), err: (addr buffered-file), ed: (addr exit-descriptor)
    20830     # . prologue
    20831     55/push-ebp
    20832     89/<- %ebp 4/r32/esp
    20833     # . save registers
    20834     50/push-eax
    20835     51/push-ecx
    20836     52/push-edx
    20837     56/push-esi
    20838     57/push-edi
    20839     # esi = T
    20840     8b/-> *(ebp+8) 6/r32/esi
    20841     # if T is already computed, return
    20842     81 7/subop/compare *(esi+0xc) 0/imm32  # Typeinfo-total-size-in-bytes
    20843     0f 8d/jump-if->= $populate-mu-type-sizes-in-type:end/disp32
    20844     # if T is being computed, abort
    20845     81 7/subop/compare *(esi+0xc) -1/imm32/being-computed  # Typeinfo-total-size-in-bytes
    20846     0f 84/jump-if-= $populate-mu-type-sizes-in-type:abort/disp32
    20847     # tag T (-2 to -1) to avoid infinite recursion
    20848     c7 0/subop/copy *(esi+0xc) -1/imm32/being-computed  # Typeinfo-total-size-in-bytes
    20849     # var total-size/edi: int = 0
    20850     bf/copy-to-edi 0/imm32
    20851     # - for every field, if it's a user-defined type, compute its size
    20852     # var table/ecx: (addr table (handle array byte) (handle typeinfo-entry)) = lookup(T->fields)
    20853     (lookup *(esi+4) *(esi+8))  # Typeinfo-fields Typeinfo-fields => eax
    20854     89/<- %ecx 0/r32/eax
    20855     # var table-size/edx: int = table->write
    20856     8b/-> *ecx 2/r32/edx  # stream-write
    20857     # var curr/ecx: (addr table_row) = table->data
    20858     8d/copy-address *(ecx+0xc) 1/r32/ecx
    20859     # var max/edx: (addr table_row) = table->data + table->write
    20860     8d/copy-address *(ecx+edx) 2/r32/edx
    20861     {
    20862 $populate-mu-type-sizes-in-type:loop:
    20863       # if (curr >= max) break
    20864       39/compare %ecx 2/r32/edx
    20865       73/jump-if-addr>= break/disp8
    20866       # var t/eax: (addr typeinfo-entry) = lookup(curr->value)
    20867       (lookup *(ecx+8) *(ecx+0xc))  # => eax
    20868       # if (t->input-var == 0) silently ignore it; we'll emit a nice error message while type-checking
    20869       81 7/subop/compare *eax 0/imm32  # Typeinfo-entry-input-var
    20870       74/jump-if-= $populate-mu-type-sizes-in-type:end/disp8
    20871       # compute size of t->input-var
    20872       (lookup *eax *(eax+4))  # Typeinfo-entry-input-var Typeinfo-entry-input-var => eax
    20873       (compute-size-of-var %eax *(ebp+0xc) *(ebp+0x10))  # => eax
    20874       # result += eax
    20875       01/add-to %edi 0/r32/eax
    20876       # curr += row-size
    20877       81 0/subop/add %ecx 0x10/imm32  # Typeinfo-fields-row-size
    20878       #
    20879       eb/jump loop/disp8
    20880     }
    20881     # - save result
    20882     89/<- *(esi+0xc) 7/r32/edi  # Typeinfo-total-size-in-bytes
    20883 $populate-mu-type-sizes-in-type:end:
    20884     # . restore registers
    20885     5f/pop-to-edi
    20886     5e/pop-to-esi
    20887     5a/pop-to-edx
    20888     59/pop-to-ecx
    20889     58/pop-to-eax
    20890     # . epilogue
    20891     89/<- %esp 5/r32/ebp
    20892     5d/pop-to-ebp
    20893     c3/return
    20894
    20895 $populate-mu-type-sizes-in-type:abort:
    20896     (write-buffered *(ebp+0xc) "cycle in type definitions\n")
    20897     (flush *(ebp+0xc))
    20898     (stop *(ebp+0x10) 1)
    20899     # never gets here
    20900
    20901 # Analogous to size-of, except we need to compute what size-of can just read
    20902 # off the right data structures.
    20903 compute-size-of-var:  # in: (addr var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
    20904     # . prologue
    20905     55/push-ebp
    20906     89/<- %ebp 4/r32/esp
    20907     # . push registers
    20908     51/push-ecx
    20909     # var t/ecx: (addr type-tree) = lookup(v->type)
    20910     8b/-> *(ebp+8) 1/r32/ecx
    20911     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
    20912     89/<- %ecx 0/r32/eax
    20913     # if (t->is-atom == false) t = lookup(t->left)
    20914     {
    20915       81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
    20916       75/jump-if-!= break/disp8
    20917       (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
    20918       89/<- %ecx 0/r32/eax
    20919     }
    20920     # TODO: ensure t is an atom
    20921     (compute-size-of-type-id *(ecx+4) *(ebp+0xc) *(ebp+0x10))  # Type-tree-value => eax
    20922 $compute-size-of-var:end:
    20923     # . restore registers
    20924     59/pop-to-ecx
    20925     # . epilogue
    20926     89/<- %esp 5/r32/ebp
    20927     5d/pop-to-ebp
    20928     c3/return
    20929
    20930 compute-size-of-type-id:  # t: type-id, err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
    20931     # . prologue
    20932     55/push-ebp
    20933     89/<- %ebp 4/r32/esp
    20934     # . save registers
    20935     51/push-ecx
    20936     # var out/ecx: (handle typeinfo)
    20937     68/push 0/imm32
    20938     68/push 0/imm32
    20939     89/<- %ecx 4/r32/esp
    20940     # eax = t
    20941     8b/-> *(ebp+8) 0/r32/eax
    20942     # if t is a literal, return 0
    20943     3d/compare-eax-and 0/imm32/literal
    20944     0f 84/jump-if-= $compute-size-of-type-id:end/disp32  # eax changes type from type-id to int
    20945     # if t is a byte, return 4 (because we don't really support non-multiples of 4)
    20946     3d/compare-eax-and 8/imm32/byte
    20947     {
    20948       75/jump-if-!= break/disp8
    20949       b8/copy-to-eax 4/imm32
    20950       eb/jump $compute-size-of-type-id:end/disp8
    20951     }
    20952     # if t is a handle, return 8
    20953     3d/compare-eax-and 4/imm32/handle
    20954     {
    20955       75/jump-if-!= break/disp8
    20956       b8/copy-to-eax 8/imm32
    20957       eb/jump $compute-size-of-type-id:end/disp8  # eax changes type from type-id to int
    20958     }
    20959     # if t is a slice, return 8
    20960     3d/compare-eax-and 0xc/imm32/slice
    20961     {
    20962       75/jump-if-!= break/disp8
    20963       b8/copy-to-eax 8/imm32
    20964       eb/jump $compute-size-of-type-id:end/disp8  # eax changes type from type-id to int
    20965     }
    20966     # if t is a user-defined type, compute its size
    20967     # TODO: support non-atom type
    20968     (find-typeinfo %eax %ecx)
    20969     {
    20970       81 7/subop/compare *ecx 0/imm32
    20971       74/jump-if-= break/disp8
    20972 $compute-size-of-type-id:user-defined:
    20973       (lookup *ecx *(ecx+4))  # => eax
    20974       (populate-mu-type-sizes-in-type %eax *(ebp+0xc) *(ebp+0x10))
    20975       8b/-> *(eax+0xc) 0/r32/eax  # Typeinfo-total-size-in-bytes
    20976       eb/jump $compute-size-of-type-id:end/disp8
    20977     }
    20978     # otherwise return the word size
    20979     b8/copy-to-eax 4/imm32
    20980 $compute-size-of-type-id:end:
    20981     # . reclaim locals
    20982     81 0/subop/add %esp 8/imm32
    20983     # . restore registers
    20984     59/pop-to-ecx
    20985     # . epilogue
    20986     89/<- %esp 5/r32/ebp
    20987     5d/pop-to-ebp
    20988     c3/return
    20989
    20990 # at this point we have total sizes for all user-defined types
    20991 # compute offsets for each element
    20992 # complication: fields may be out of order
    20993 populate-mu-type-offsets:  # in: (addr typeinfo), err: (addr buffered-file), ed: (addr exit-descriptor)
    20994     # . prologue
    20995     55/push-ebp
    20996     89/<- %ebp 4/r32/esp
    20997     # . save registers
    20998     50/push-eax
    20999     51/push-ecx
    21000     52/push-edx
    21001     53/push-ebx
    21002     56/push-esi
    21003     57/push-edi
    21004 #?     (dump-typeinfos "aaa\n")
    21005     # var curr-offset/edi: int = 0
    21006     bf/copy-to-edi 0/imm32
    21007     # var table/ecx: (addr table string_key (handle typeinfo-entry)) = lookup(in->fields)
    21008     8b/-> *(ebp+8) 1/r32/ecx
    21009     (lookup *(ecx+4) *(ecx+8))  # Typeinfo-fields Typeinfo-fields => eax
    21010     89/<- %ecx 0/r32/eax
    21011     # var num-elems/edx: int = table->write / Typeinfo-fields-row-size
    21012     8b/-> *ecx 2/r32/edx  # stream-write
    21013     c1 5/subop/shift-right-logical  %edx 4/imm8
    21014     # var i/ebx: int = 0
    21015     bb/copy-to-ebx 0/imm32
    21016     {
    21017 $populate-mu-type-offsets:loop:
    21018       39/compare %ebx 2/r32/edx
    21019       0f 8d/jump-if->= break/disp32
    21020 #?       (write-buffered Stderr "looking up index ")
    21021 #?       (write-int32-hex-buffered Stderr %ebx)
    21022 #?       (write-buffered Stderr " in ")
    21023 #?       (write-int32-hex-buffered Stderr *(ebp+8))
    21024 #?       (write-buffered Stderr Newline)
    21025 #?       (flush Stderr)
    21026       # var v/esi: (addr typeinfo-entry)
    21027       (locate-typeinfo-entry-with-index %ecx %ebx *(ebp+0xc) *(ebp+0x10))  # => eax
    21028       89/<- %esi 0/r32/eax
    21029       # if v is null, silently move on; we'll emit a nice error message while type-checking
    21030       81 7/subop/compare %esi 0/imm32  # Typeinfo-entry-input-var
    21031       74/jump-if-= $populate-mu-type-offsets:end/disp8
    21032       # if (v->input-var == 0) silently ignore v; we'll emit a nice error message while type-checking
    21033       81 7/subop/compare *esi 0/imm32  # Typeinfo-entry-input-var
    21034       74/jump-if-= $populate-mu-type-offsets:end/disp8
    21035       # v->output-var->offset = curr-offset
    21036       # . eax: (addr var)
    21037       (lookup *(esi+0xc) *(esi+0x10))  # Typeinfo-entry-output-var Typeinfo-entry-output-var => eax
    21038       89/<- *(eax+0x14) 7/r32/edi  # Var-offset
    21039       # curr-offset += size-of(v->input-var)
    21040       (lookup *esi *(esi+4))  # Typeinfo-entry-input-var Typeinfo-entry-input-var => eax
    21041       (size-of %eax)  # => eax
    21042       01/add-to %edi 0/r32/eax
    21043       # ++i
    21044       43/increment-ebx
    21045       e9/jump loop/disp32
    21046     }
    21047 $populate-mu-type-offsets:end:
    21048     # . restore registers
    21049     5f/pop-to-edi
    21050     5e/pop-to-esi
    21051     5b/pop-to-ebx
    21052     5a/pop-to-edx
    21053     59/pop-to-ecx
    21054     58/pop-to-eax
    21055     # . epilogue
    21056     89/<- %esp 5/r32/ebp
    21057     5d/pop-to-ebp
    21058     c3/return
    21059
    21060 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)
    21061     # . prologue
    21062     55/push-ebp
    21063     89/<- %ebp 4/r32/esp
    21064     # . save registers
    21065     51/push-ecx
    21066     52/push-edx
    21067     53/push-ebx
    21068     56/push-esi
    21069     57/push-edi
    21070     # esi = table
    21071     8b/-> *(ebp+8) 6/r32/esi
    21072     # var curr/ecx: (addr row (handle array byte) (handle typeinfo-entry)) = table->data
    21073     8d/copy-address *(esi+0xc) 1/r32/ecx
    21074     # var max/edx: (addr byte) = &table->data[table->write]
    21075     8b/-> *esi 2/r32/edx
    21076     8d/copy-address *(ecx+edx) 2/r32/edx
    21077     {
    21078 $locate-typeinfo-entry-with-index:loop:
    21079       39/compare %ecx 2/r32/edx
    21080       73/jump-if-addr>= break/disp8
    21081       # var v/eax: (addr typeinfo-entry)
    21082       (lookup *(ecx+8) *(ecx+0xc))  # => eax
    21083       # if (v->index == idx) return v
    21084       8b/-> *(eax+8) 3/r32/ebx  # Typeinfo-entry-index
    21085 #?       (write-buffered Stderr "comparing ")
    21086 #?       (write-int32-hex-buffered Stderr %ebx)
    21087 #?       (write-buffered Stderr " and ")
    21088 #?       (write-int32-hex-buffered Stderr *(ebp+0xc))
    21089 #?       (write-buffered Stderr Newline)
    21090 #?       (flush Stderr)
    21091       39/compare *(ebp+0xc) 3/r32/ebx
    21092       74/jump-if-= $locate-typeinfo-entry-with-index:end/disp8
    21093       # curr += Typeinfo-entry-size
    21094       81 0/subop/add %ecx 0x10/imm32  # Typeinfo-entry-size
    21095       #
    21096       eb/jump loop/disp8
    21097     }
    21098     # return 0
    21099     b8/copy-to-eax 0/imm32
    21100 $locate-typeinfo-entry-with-index:end:
    21101 #?     (write-buffered Stderr "returning ")
    21102 #?     (write-int32-hex-buffered Stderr %eax)
    21103 #?     (write-buffered Stderr Newline)
    21104 #?     (flush Stderr)
    21105     # . restore registers
    21106     5f/pop-to-edi
    21107     5e/pop-to-esi
    21108     5b/pop-to-ebx
    21109     5a/pop-to-edx
    21110     59/pop-to-ecx
    21111     # . epilogue
    21112     89/<- %esp 5/r32/ebp
    21113     5d/pop-to-ebp
    21114     c3/return
    21115
    21116 dump-typeinfos:  # hdr: (addr array byte)
    21117     # . prologue
    21118     55/push-ebp
    21119     89/<- %ebp 4/r32/esp
    21120     # . save registers
    21121     50/push-eax
    21122     #
    21123     (write-buffered Stderr *(ebp+8))
    21124     (flush Stderr)
    21125     # var curr/eax: (addr typeinfo) = lookup(Program->types)
    21126     (lookup *_Program-types *_Program-types->payload)  # => eax
    21127     {
    21128       # if (curr == null) break
    21129       3d/compare-eax-and 0/imm32
    21130       74/jump-if-= break/disp8
    21131       (write-buffered Stderr "---\n")
    21132       (flush Stderr)
    21133       (dump-typeinfo %eax)
    21134       # curr = lookup(curr->next)
    21135       (lookup *(eax+0x10) *(eax+0x14))  # Typeinfo-next Typeinfo-next => eax
    21136       eb/jump loop/disp8
    21137     }
    21138 $dump-typeinfos:end:
    21139     # . restore registers
    21140     58/pop-to-eax
    21141     # . epilogue
    21142     89/<- %esp 5/r32/ebp
    21143     5d/pop-to-ebp
    21144     c3/return
    21145
    21146 dump-typeinfo:  # in: (addr typeinfo)
    21147     # . prologue
    21148     55/push-ebp
    21149     89/<- %ebp 4/r32/esp
    21150     # . save registers
    21151     50/push-eax
    21152     51/push-ecx
    21153     52/push-edx
    21154     53/push-ebx
    21155     56/push-esi
    21156     57/push-edi
    21157     # esi = in
    21158     8b/-> *(ebp+8) 6/r32/esi
    21159     # var table/ecx: (addr table (handle array byte) (handle typeinfo-entry)) = lookup(T->fields)
    21160     (lookup *(esi+4) *(esi+8))  # Typeinfo-fields Typeinfo-fields => eax
    21161     89/<- %ecx 0/r32/eax
    21162     (write-buffered Stderr "id:")
    21163     (write-int32-hex-buffered Stderr *esi)
    21164     (write-buffered Stderr "\n")
    21165     (write-buffered Stderr "fields @ ")
    21166     (write-int32-hex-buffered Stderr %ecx)
    21167     (write-buffered Stderr Newline)
    21168     (flush Stderr)
    21169     (write-buffered Stderr "  write: ")
    21170     (write-int32-hex-buffered Stderr *ecx)
    21171     (write-buffered Stderr Newline)
    21172     (flush Stderr)
    21173     (write-buffered Stderr "  read: ")
    21174     (write-int32-hex-buffered Stderr *(ecx+4))
    21175     (write-buffered Stderr Newline)
    21176     (flush Stderr)
    21177     (write-buffered Stderr "  size: ")
    21178     (write-int32-hex-buffered Stderr *(ecx+8))
    21179     (write-buffered Stderr Newline)
    21180     (flush Stderr)
    21181     # var table-size/edx: int = table->write
    21182     8b/-> *ecx 2/r32/edx  # stream-write
    21183     # var curr/ecx: (addr table_row) = table->data
    21184     8d/copy-address *(ecx+0xc) 1/r32/ecx
    21185     # var max/edx: (addr table_row) = table->data + table->write
    21186     8d/copy-address *(ecx+edx) 2/r32/edx
    21187     {
    21188 $dump-typeinfo:loop:
    21189       # if (curr >= max) break
    21190       39/compare %ecx 2/r32/edx
    21191       0f 83/jump-if-addr>= break/disp32
    21192       (write-buffered Stderr "  row:\n")
    21193       (write-buffered Stderr "    key: ")
    21194       (write-int32-hex-buffered Stderr *ecx)
    21195       (write-buffered Stderr ",")
    21196       (write-int32-hex-buffered Stderr *(ecx+4))
    21197       (write-buffered Stderr " = '")
    21198       (lookup *ecx *(ecx+4))
    21199       (write-buffered Stderr %eax)
    21200       (write-buffered Stderr "' @ ")
    21201       (write-int32-hex-buffered Stderr %eax)
    21202       (write-buffered Stderr Newline)
    21203       (flush Stderr)
    21204       (write-buffered Stderr "    value: ")
    21205       (write-int32-hex-buffered Stderr *(ecx+8))
    21206       (write-buffered Stderr ",")
    21207       (write-int32-hex-buffered Stderr *(ecx+0xc))
    21208       (write-buffered Stderr " = typeinfo-entry@")
    21209       (lookup *(ecx+8) *(ecx+0xc))
    21210       (write-int32-hex-buffered Stderr %eax)
    21211       (write-buffered Stderr Newline)
    21212       (flush Stderr)
    21213       (write-buffered Stderr "        input var@")
    21214       (dump-var 5 %eax)
    21215       (lookup *(ecx+8) *(ecx+0xc))
    21216       (write-buffered Stderr "        index: ")
    21217       (write-int32-hex-buffered Stderr *(eax+8))
    21218       (write-buffered Stderr Newline)
    21219       (flush Stderr)
    21220       (write-buffered Stderr "        output var@")
    21221       8d/copy-address *(eax+0xc) 0/r32/eax  # Typeinfo-entry-output-var
    21222       (dump-var 5 %eax)
    21223       (flush Stderr)
    21224       # curr += row-size
    21225       81 0/subop/add %ecx 0x10/imm32  # Typeinfo-fields-row-size
    21226       #
    21227       e9/jump loop/disp32
    21228     }
    21229 $dump-typeinfo:end:
    21230     # . restore registers
    21231     5f/pop-to-edi
    21232     5e/pop-to-esi
    21233     5b/pop-to-ebx
    21234     5a/pop-to-edx
    21235     59/pop-to-ecx
    21236     58/pop-to-eax
    21237     # . epilogue
    21238     89/<- %esp 5/r32/ebp
    21239     5d/pop-to-ebp
    21240     c3/return
    21241
    21242 dump-var:  # indent: int, v: (addr handle var)
    21243     # . prologue
    21244     55/push-ebp
    21245     89/<- %ebp 4/r32/esp
    21246     # . save registers
    21247     50/push-eax
    21248     53/push-ebx
    21249     # eax = v
    21250     8b/-> *(ebp+0xc) 0/r32/eax
    21251     #
    21252     (write-int32-hex-buffered Stderr *eax)
    21253     (write-buffered Stderr ",")
    21254     (write-int32-hex-buffered Stderr *(eax+4))
    21255     (write-buffered Stderr "->")
    21256     (lookup *eax *(eax+4))
    21257     (write-int32-hex-buffered Stderr %eax)
    21258     (write-buffered Stderr Newline)
    21259     (flush Stderr)
    21260     {
    21261       3d/compare-eax-and 0/imm32
    21262       0f 84/jump-if-= break/disp32
    21263       (emit-indent Stderr *(ebp+8))
    21264       (write-buffered Stderr "name: ")
    21265       89/<- %ebx 0/r32/eax
    21266       (write-int32-hex-buffered Stderr *ebx)  # Var-name
    21267       (write-buffered Stderr ",")
    21268       (write-int32-hex-buffered Stderr *(ebx+4))  # Var-name
    21269       (write-buffered Stderr "->")
    21270       (lookup *ebx *(ebx+4))  # Var-name
    21271       (write-int32-hex-buffered Stderr %eax)
    21272       {
    21273         3d/compare-eax-and 0/imm32
    21274         74/jump-if-= break/disp8
    21275         (write-buffered Stderr Space)
    21276         (write-buffered Stderr %eax)
    21277       }
    21278       (write-buffered Stderr Newline)
    21279       (flush Stderr)
    21280       (emit-indent Stderr *(ebp+8))
    21281       (write-buffered Stderr "block depth: ")
    21282       (write-int32-hex-buffered Stderr *(ebx+0x10))  # Var-block-depth
    21283       (write-buffered Stderr Newline)
    21284       (flush Stderr)
    21285       (emit-indent Stderr *(ebp+8))
    21286       (write-buffered Stderr "stack offset: ")
    21287       (write-int32-hex-buffered Stderr *(ebx+0x14))  # Var-offset
    21288       (write-buffered Stderr Newline)
    21289       (flush Stderr)
    21290       (emit-indent Stderr *(ebp+8))
    21291       (write-buffered Stderr "reg: ")
    21292       (write-int32-hex-buffered Stderr *(ebx+0x18))  # Var-register
    21293       (write-buffered Stderr ",")
    21294       (write-int32-hex-buffered Stderr *(ebx+0x1c))  # Var-register
    21295       (write-buffered Stderr "->")
    21296       (flush Stderr)
    21297       (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register
    21298       (write-int32-hex-buffered Stderr %eax)
    21299       {
    21300         3d/compare-eax-and 0/imm32
    21301         74/jump-if-= break/disp8
    21302         (write-buffered Stderr Space)
    21303         (write-buffered Stderr %eax)
    21304       }
    21305       (write-buffered Stderr Newline)
    21306       (flush Stderr)
    21307     }
    21308 $dump-var:end:
    21309     # . restore registers
    21310     5b/pop-to-ebx
    21311     58/pop-to-eax
    21312     # . epilogue
    21313     89/<- %esp 5/r32/ebp
    21314     5d/pop-to-ebp
    21315     c3/return
    21316
    21317 #######################################################
    21318 # Type-checking
    21319 #######################################################
    21320
    21321 check-mu-types:  # err: (addr buffered-file), ed: (addr exit-descriptor)
    21322     # . prologue
    21323     55/push-ebp
    21324     89/<- %ebp 4/r32/esp
    21325     # . save registers
    21326     50/push-eax
    21327     # var curr/eax: (addr function) = lookup(Program->functions)
    21328     (lookup *_Program-functions *_Program-functions->payload)  # => eax
    21329     {
    21330 $check-mu-types:loop:
    21331       # if (curr == null) break
    21332       3d/compare-eax-and 0/imm32
    21333       0f 84/jump-if-= break/disp32
    21334 +--  8 lines: #?       # dump curr->name -----------------------------------------------------------------------------------------------------------------------------------
    21342       (check-mu-function %eax *(ebp+8) *(ebp+0xc))
    21343       # curr = lookup(curr->next)
    21344       (lookup *(eax+0x20) *(eax+0x24))  # Function-next Function-next => eax
    21345       e9/jump loop/disp32
    21346     }
    21347 $check-mu-types:end:
    21348     # . restore registers
    21349     58/pop-to-eax
    21350     # . epilogue
    21351     89/<- %esp 5/r32/ebp
    21352     5d/pop-to-ebp
    21353     c3/return
    21354
    21355 check-mu-function:  # fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    21356     # . prologue
    21357     55/push-ebp
    21358     89/<- %ebp 4/r32/esp
    21359     # . save registers
    21360     50/push-eax
    21361     56/push-esi
    21362     # esi = f
    21363     8b/-> *(ebp+8) 6/r32/esi
    21364     # outputs
    21365     (lookup *(esi+0x10) *(esi+0x14))  # Function-outputs Function-outputs => eax
    21366     (check-all-unique-registers %eax %esi *(ebp+0xc) *(ebp+0x10))
    21367     # body
    21368     (lookup *(esi+0x18) *(esi+0x1c))  # Function-body Function-body => eax
    21369     (check-mu-block %eax *(ebp+8) *(ebp+0xc) *(ebp+0x10))
    21370     # if function has no outputs, we're done
    21371     81 7/subop/compare *(esi+0x10) 0/imm32
    21372     74/jump-if-= $check-mu-function:end/disp8
    21373     # some final checks on body
    21374     (check-final-stmt-is-return %eax %esi *(ebp+0xc) *(ebp+0x10))
    21375     (check-no-breaks %eax %esi *(ebp+0xc) *(ebp+0x10))
    21376 $check-mu-function:end:
    21377     # . restore registers
    21378     5e/pop-to-esi
    21379     58/pop-to-eax
    21380     # . epilogue
    21381     89/<- %esp 5/r32/ebp
    21382     5d/pop-to-ebp
    21383     c3/return
    21384
    21385 check-mu-block:  # block: (addr block), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    21386     # . prologue
    21387     55/push-ebp
    21388     89/<- %ebp 4/r32/esp
    21389     # . save registers
    21390     50/push-eax
    21391     # eax = block
    21392     8b/-> *(ebp+8) 0/r32/eax
    21393     # var stmts/eax: (addr list stmt) = lookup(block->statements)
    21394     (lookup *(eax+4) *(eax+8))  # Block-stmts Block-stmts => eax
    21395     #
    21396     {
    21397 $check-mu-block:check-empty:
    21398       3d/compare-eax-and 0/imm32
    21399       0f 84/jump-if-= break/disp32
    21400       # emit block->statements
    21401       (check-mu-stmt-list %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21402     }
    21403 $check-mu-block:end:
    21404     # . restore registers
    21405     58/pop-to-eax
    21406     # . epilogue
    21407     89/<- %esp 5/r32/ebp
    21408     5d/pop-to-ebp
    21409     c3/return
    21410
    21411 check-mu-stmt-list:  # stmts: (addr list stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    21412     # . prologue
    21413     55/push-ebp
    21414     89/<- %ebp 4/r32/esp
    21415     # . save registers
    21416     50/push-eax
    21417     56/push-esi
    21418     # esi = stmts
    21419     8b/-> *(ebp+8) 6/r32/esi
    21420     {
    21421 $check-mu-stmt-list:loop:
    21422       81 7/subop/compare %esi 0/imm32
    21423       0f 84/jump-if-= break/disp32
    21424       # var curr-stmt/eax: (addr stmt) = lookup(stmts->value)
    21425       (lookup *esi *(esi+4))  # List-value List-value => eax
    21426       {
    21427 $check-mu-stmt-list:check-for-block:
    21428         81 7/subop/compare *eax 0/imm32/block  # Stmt-tag
    21429         75/jump-if-!= break/disp8
    21430 $check-mu-stmt-list:block:
    21431         (check-mu-block %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21432         eb/jump $check-mu-stmt-list:continue/disp8
    21433       }
    21434       {
    21435 $check-mu-stmt-list:check-for-stmt1:
    21436         81 7/subop/compare *eax 1/imm32/stmt1  # Stmt-tag
    21437         0f 85/jump-if-!= break/disp32
    21438 $check-mu-stmt-list:stmt1:
    21439         (check-mu-stmt %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21440         eb/jump $check-mu-stmt-list:continue/disp8
    21441       }
    21442       {
    21443 $check-mu-stmt-list:check-for-reg-var-def:
    21444         81 7/subop/compare *eax 3/imm32/reg-var-def  # Stmt-tag
    21445         0f 85/jump-if-!= break/disp32
    21446 $check-mu-stmt-list:reg-var-def:
    21447         (check-mu-stmt %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21448         eb/jump $check-mu-stmt-list:continue/disp8
    21449       }
    21450 $check-mu-stmt-list:continue:
    21451       # TODO: raise an error on unrecognized Stmt-tag
    21452       (lookup *(esi+8) *(esi+0xc))  # List-next List-next => eax
    21453       89/<- %esi 0/r32/eax
    21454       e9/jump loop/disp32
    21455     }
    21456 $check-mu-stmt-list:end:
    21457     # . restore registers
    21458     5e/pop-to-esi
    21459     58/pop-to-eax
    21460     # . epilogue
    21461     89/<- %esp 5/r32/ebp
    21462     5d/pop-to-ebp
    21463     c3/return
    21464
    21465 check-mu-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    21466     # . prologue
    21467     55/push-ebp
    21468     89/<- %ebp 4/r32/esp
    21469     # . save registers
    21470     50/push-eax
    21471     # - if stmt's operation matches a primitive, check against it
    21472     (has-primitive-name? *(ebp+8))  # => eax
    21473     3d/compare-eax-and 0/imm32/false
    21474     {
    21475       74/jump-if-= break/disp8
    21476       (check-mu-primitive *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21477       e9/jump $check-mu-stmt:end/disp32
    21478     }
    21479     # - otherwise find a function to check against
    21480     # var f/eax: (addr function) = lookup(*Program->functions)
    21481     (lookup *_Program-functions *_Program-functions->payload)  # => eax
    21482     (find-matching-function %eax *(ebp+8))  # => eax
    21483     3d/compare-eax-and 0/imm32
    21484     {
    21485       74/jump-if-= break/disp8
    21486       (check-mu-call *(ebp+8) %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21487       eb/jump $check-mu-stmt:end/disp8
    21488     }
    21489     # var f/eax: (addr function) = lookup(*Program->signatures)
    21490     (lookup *_Program-signatures *_Program-signatures->payload)  # => eax
    21491     (find-matching-function %eax *(ebp+8))  # => eax
    21492     3d/compare-eax-and 0/imm32
    21493     {
    21494       74/jump-if-= break/disp8
    21495       (check-mu-call *(ebp+8) %eax *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21496       eb/jump $check-mu-stmt:end/disp8
    21497     }
    21498     # - otherwise abort
    21499     e9/jump $check-mu-stmt:unknown-call/disp32
    21500 $check-mu-stmt:end:
    21501     # . restore registers
    21502     58/pop-to-eax
    21503     # . epilogue
    21504     89/<- %esp 5/r32/ebp
    21505     5d/pop-to-ebp
    21506     c3/return
    21507
    21508 $check-mu-stmt:unknown-call:
    21509     (write-buffered *(ebp+0x10) "unknown function '")
    21510     8b/-> *(ebp+8) 0/r32/eax
    21511     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
    21512     (write-buffered *(ebp+0x10) %eax)
    21513     (write-buffered *(ebp+0x10) "'\n")
    21514     (flush *(ebp+0x10))
    21515     (stop *(ebp+0x14) 1)
    21516     # never gets here
    21517
    21518 has-primitive-name?:  # stmt: (addr stmt) -> result/eax: boolean
    21519     # . prologue
    21520     55/push-ebp
    21521     89/<- %ebp 4/r32/esp
    21522     # . save registers
    21523     51/push-ecx
    21524     56/push-esi
    21525     # var name/esi: (addr array byte) = lookup(stmt->operation)
    21526     8b/-> *(ebp+8) 6/r32/esi
    21527     (lookup *(esi+4) *(esi+8))  # Stmt1-operation Stmt1-operation => eax
    21528     89/<- %esi 0/r32/eax
    21529     # if (name == "return") return true
    21530     (string-equal? %esi "return")  # => eax
    21531     3d/compare-eax-and 0/imm32/false
    21532     0f 85/jump-if-!= $has-primitive-name?:end/disp32
    21533     # if (name == "get") return true
    21534     (string-equal? %esi "get")  # => eax
    21535     3d/compare-eax-and 0/imm32/false
    21536     0f 85/jump-if-!= $has-primitive-name?:end/disp32
    21537     # if (name == "index") return true
    21538     (string-equal? %esi "index")  # => eax
    21539     3d/compare-eax-and 0/imm32/false
    21540     0f 85/jump-if-!= $has-primitive-name?:end/disp32
    21541     # if (name == "length") return true
    21542     (string-equal? %esi "length")  # => eax
    21543     3d/compare-eax-and 0/imm32/false
    21544     0f 85/jump-if-!= $has-primitive-name?:end/disp32
    21545     # if (name == "compute-offset") return true
    21546     (string-equal? %esi "compute-offset")  # => eax
    21547     3d/compare-eax-and 0/imm32/false
    21548     0f 85/jump-if-!= $has-primitive-name?:end/disp32
    21549     # if (name == "copy-object") return true
    21550     (string-equal? %esi "copy-object")  # => eax
    21551     3d/compare-eax-and 0/imm32/false
    21552     0f 85/jump-if-!= $has-primitive-name?:end/disp32
    21553     # if (name == "clear-object") return true
    21554     (string-equal? %esi "clear-object")  # => eax
    21555     3d/compare-eax-and 0/imm32/false
    21556     0f 85/jump-if-!= $has-primitive-name?:end/disp32
    21557     # if (name == "allocate") return true
    21558     (string-equal? %esi "allocate")  # => eax
    21559     3d/compare-eax-and 0/imm32/false
    21560     0f 85/jump-if-!= $has-primitive-name?:end/disp32
    21561     # if (name == "populate") return true
    21562     (string-equal? %esi "populate")  # => eax
    21563     3d/compare-eax-and 0/imm32/false
    21564     0f 85/jump-if-!= $has-primitive-name?:end/disp32
    21565     # if (name == "populate-stream") return true
    21566     (string-equal? %esi "populate-stream")  # => eax
    21567     3d/compare-eax-and 0/imm32/false
    21568     0f 85/jump-if-!= $has-primitive-name?:end/disp32
    21569     # if (name == "read-from-stream") return true
    21570     (string-equal? %esi "read-from-stream")  # => eax
    21571     3d/compare-eax-and 0/imm32/false
    21572     0f 85/jump-if-!= $has-primitive-name?:end/disp32
    21573     # if (name == "write-to-stream") return true
    21574     (string-equal? %esi "write-to-stream")  # => eax
    21575     3d/compare-eax-and 0/imm32/false
    21576     0f 85/jump-if-!= $has-primitive-name?:end/disp32
    21577     # var curr/ecx: (addr primitive) = Primitives
    21578     b9/copy-to-ecx Primitives/imm32
    21579     {
    21580 $has-primitive-name?:loop:
    21581       # if (curr == null) break
    21582       81 7/subop/compare %ecx 0/imm32
    21583       74/jump-if-= break/disp8
    21584       # if (primitive->name == name) return true
    21585       (lookup *ecx *(ecx+4))  # Primitive-name Primitive-name => eax
    21586 #?       (write-buffered Stderr %eax)
    21587 #?       (write-buffered Stderr Newline)
    21588 #?       (flush Stderr)
    21589       (string-equal? %esi %eax)  # => eax
    21590       3d/compare-eax-and 0/imm32/false
    21591       75/jump-if-!= $has-primitive-name?:end/disp8
    21592 $has-primitive-name?:next-primitive:
    21593       # curr = curr->next
    21594       (lookup *(ecx+0x3c) *(ecx+0x40))  # Primitive-next Primitive-next => eax
    21595       89/<- %ecx 0/r32/eax
    21596       #
    21597       e9/jump loop/disp32
    21598     }
    21599     # return null
    21600     b8/copy-to-eax 0/imm32
    21601 $has-primitive-name?:end:
    21602     # . restore registers
    21603     5e/pop-to-esi
    21604     59/pop-to-ecx
    21605     # . epilogue
    21606     89/<- %esp 5/r32/ebp
    21607     5d/pop-to-ebp
    21608     c3/return
    21609
    21610 check-mu-primitive:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    21611     # . prologue
    21612     55/push-ebp
    21613     89/<- %ebp 4/r32/esp
    21614     # . save registers
    21615     50/push-eax
    21616     51/push-ecx
    21617     # var op/ecx: (addr array byte) = lookup(stmt->operation)
    21618     8b/-> *(ebp+8) 0/r32/eax
    21619     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
    21620     89/<- %ecx 0/r32/eax
    21621     # if (op == "copy") check-mu-copy-stmt
    21622     {
    21623       (string-equal? %ecx "copy")  # => eax
    21624       3d/compare-eax-and 0/imm32/false
    21625       74/jump-if-= break/disp8
    21626       (check-mu-copy-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21627       e9/jump $check-mu-primitive:end/disp32
    21628     }
    21629     # if (op == "copy-to") check-mu-copy-to-stmt
    21630     {
    21631       (string-equal? %ecx "copy-to")  # => eax
    21632       3d/compare-eax-and 0/imm32/false
    21633       74/jump-if-= break/disp8
    21634       (check-mu-copy-to-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21635       e9/jump $check-mu-primitive:end/disp32
    21636     }
    21637     # if (op == "copy-byte") check-mu-copy-byte-stmt
    21638     {
    21639       (string-equal? %ecx "copy-byte")  # => eax
    21640       3d/compare-eax-and 0/imm32/false
    21641       74/jump-if-= break/disp8
    21642       (check-mu-copy-byte-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21643       e9/jump $check-mu-primitive:end/disp32
    21644     }
    21645     # if (op == "copy-byte-to") check-mu-copy-byte-to-stmt
    21646     {
    21647       (string-equal? %ecx "copy-byte-to")  # => eax
    21648       3d/compare-eax-and 0/imm32/false
    21649       74/jump-if-= break/disp8
    21650       (check-mu-copy-byte-to-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21651       e9/jump $check-mu-primitive:end/disp32
    21652     }
    21653     # if (op == "compare") check-mu-compare-stmt
    21654     {
    21655       (string-equal? %ecx "compare")  # => eax
    21656       3d/compare-eax-and 0/imm32/false
    21657       74/jump-if-= break/disp8
    21658       (check-mu-compare-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21659       e9/jump $check-mu-primitive:end/disp32
    21660     }
    21661     # if (op == "address") check-mu-address-stmt
    21662     {
    21663       (string-equal? %ecx "address")  # => eax
    21664       3d/compare-eax-and 0/imm32/false
    21665       74/jump-if-= break/disp8
    21666       (check-mu-address-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21667       e9/jump $check-mu-primitive:end/disp32
    21668     }
    21669     # if (op == "return") check-mu-return-stmt
    21670     {
    21671       (string-equal? %ecx "return")  # => eax
    21672       3d/compare-eax-and 0/imm32/false
    21673       74/jump-if-= break/disp8
    21674       (check-mu-return-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21675       e9/jump $check-mu-primitive:end/disp32
    21676     }
    21677     # if (op == "get") check-mu-get-stmt
    21678     {
    21679       (string-equal? %ecx "get")  # => eax
    21680       3d/compare-eax-and 0/imm32/false
    21681       74/jump-if-= break/disp8
    21682       (check-mu-get-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21683       e9/jump $check-mu-primitive:end/disp32
    21684     }
    21685     # if (op == "index") check-mu-index-stmt
    21686     {
    21687       (string-equal? %ecx "index")  # => eax
    21688       3d/compare-eax-and 0/imm32/false
    21689       74/jump-if-= break/disp8
    21690       (check-mu-index-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21691       e9/jump $check-mu-primitive:end/disp32
    21692     }
    21693     # if (op == "length") check-mu-length-stmt
    21694     {
    21695       (string-equal? %ecx "length")  # => eax
    21696       3d/compare-eax-and 0/imm32/false
    21697       74/jump-if-= break/disp8
    21698       (check-mu-length-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21699       e9/jump $check-mu-primitive:end/disp32
    21700     }
    21701     # if (op == "compute-offset") check-mu-compute-offset-stmt
    21702     {
    21703       (string-equal? %ecx "compute-offset")  # => eax
    21704       3d/compare-eax-and 0/imm32/false
    21705       74/jump-if-= break/disp8
    21706       (check-mu-compute-offset-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21707       e9/jump $check-mu-primitive:end/disp32
    21708     }
    21709     # if (op == "copy-object") check-mu-copy-object-stmt
    21710     {
    21711       (string-equal? %ecx "copy-object")  # => eax
    21712       3d/compare-eax-and 0/imm32/false
    21713       74/jump-if-= break/disp8
    21714       (check-mu-copy-object-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21715       e9/jump $check-mu-primitive:end/disp32
    21716     }
    21717     # if (op == "clear-object") check-mu-clear-object-stmt
    21718     {
    21719       (string-equal? %ecx "clear-object")  # => eax
    21720       3d/compare-eax-and 0/imm32/false
    21721       74/jump-if-= break/disp8
    21722       (check-mu-clear-object-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21723       e9/jump $check-mu-primitive:end/disp32
    21724     }
    21725     # if (op == "allocate") check-mu-allocate-stmt
    21726     {
    21727       (string-equal? %ecx "allocate")  # => eax
    21728       3d/compare-eax-and 0/imm32/false
    21729       74/jump-if-= break/disp8
    21730       (check-mu-allocate-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21731       e9/jump $check-mu-primitive:end/disp32
    21732     }
    21733     # if (op == "populate") check-mu-populate-stmt
    21734     {
    21735       (string-equal? %ecx "populate")  # => eax
    21736       3d/compare-eax-and 0/imm32/false
    21737       74/jump-if-= break/disp8
    21738       (check-mu-populate-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21739       e9/jump $check-mu-primitive:end/disp32
    21740     }
    21741     # if (op == "populate-stream") check-mu-populate-stream-stmt
    21742     {
    21743       (string-equal? %ecx "populate-stream")  # => eax
    21744       3d/compare-eax-and 0/imm32/false
    21745       74/jump-if-= break/disp8
    21746       (check-mu-populate-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21747       e9/jump $check-mu-primitive:end/disp32
    21748     }
    21749     # if (op == "read-from-stream") check-mu-read-from-stream-stmt
    21750     {
    21751       (string-equal? %ecx "read-from-stream")  # => eax
    21752       3d/compare-eax-and 0/imm32/false
    21753       74/jump-if-= break/disp8
    21754       (check-mu-read-from-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21755       e9/jump $check-mu-primitive:end/disp32
    21756     }
    21757     # if (op == "write-to-stream") check-mu-write-to-stream-stmt
    21758     {
    21759       (string-equal? %ecx "write-to-stream")  # => eax
    21760       3d/compare-eax-and 0/imm32/false
    21761       74/jump-if-= break/disp8
    21762       (check-mu-write-to-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21763       e9/jump $check-mu-primitive:end/disp32
    21764     }
    21765     # if (op == "convert") check-mu-convert-stmt
    21766     {
    21767       (string-equal? %ecx "convert")  # => eax
    21768       3d/compare-eax-and 0/imm32/false
    21769       74/jump-if-= break/disp8
    21770       (check-mu-convert-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21771       e9/jump $check-mu-primitive:end/disp32
    21772     }
    21773     # otherwise check-numberlike-stmt
    21774     (check-mu-numberlike-primitive *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21775 $check-mu-primitive:end:
    21776     # . restore registers
    21777     59/pop-to-ecx
    21778     58/pop-to-eax
    21779     # . epilogue
    21780     89/<- %esp 5/r32/ebp
    21781     5d/pop-to-ebp
    21782     c3/return
    21783
    21784 # by default, Mu primitives should only operate on 'number-like' types
    21785 check-mu-numberlike-primitive:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    21786     # . prologue
    21787     55/push-ebp
    21788     89/<- %ebp 4/r32/esp
    21789     # . save registers
    21790     50/push-eax
    21791     51/push-ecx
    21792     56/push-esi
    21793     # esi = stmt
    21794     8b/-> *(ebp+8) 6/r32/esi
    21795     # var gas/ecx: int = 2
    21796     b9/copy-to-ecx 2/imm32
    21797     # - check at most 1 output
    21798     # var output/eax: (addr stmt-var) = stmt->outputs
    21799     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    21800     {
    21801       3d/compare-eax-and 0/imm32
    21802       74/jump-if-= break/disp8
    21803 $check-mu-numberlike-primitive:output:
    21804       (check-mu-numberlike-output %eax *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21805       (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    21806       3d/compare-eax-and 0/imm32
    21807       0f 85/jump-if-!= $check-mu-numberlike-primitive:error-too-many-outputs/disp32
    21808       # check output is in a register
    21809       # --gas
    21810       49/decrement-ecx
    21811     }
    21812     # - check first inout
    21813     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    21814     {
    21815       3d/compare-eax-and 0/imm32
    21816       0f 84/jump-if-= $check-mu-numberlike-primitive:end/disp32
    21817 $check-mu-numberlike-primitive:first-inout:
    21818       (check-mu-numberlike-arg %eax *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21819       # --gas
    21820       49/decrement-ecx
    21821     }
    21822     # - check second inout
    21823     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    21824     {
    21825       3d/compare-eax-and 0/imm32
    21826       74/jump-if-= $check-mu-numberlike-primitive:end/disp8
    21827 $check-mu-numberlike-primitive:second-inout:
    21828       # is a second inout allowed?
    21829       81 7/subop/compare %ecx 0/imm32
    21830       0f 84/jump-if-= $check-mu-numberlike-primitive:error-too-many-inouts/disp32
    21831 $check-mu-numberlike-primitive:second-inout-permitted:
    21832       (check-mu-numberlike-arg %eax *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    21833     }
    21834 $check-mu-numberlike-primitive:third-inout:
    21835     # if there's a third arg, raise an error
    21836     81 7/subop/compare *(eax+8) 0/imm32  # Stmt-var-next
    21837     0f 85/jump-if-!= $check-mu-numberlike-primitive:error-too-many-inouts/disp32
    21838 $check-mu-numberlike-primitive:end:
    21839     # . restore registers
    21840     5e/pop-to-esi
    21841     59/pop-to-ecx
    21842     58/pop-to-eax
    21843     # . epilogue
    21844     89/<- %esp 5/r32/ebp
    21845     5d/pop-to-ebp
    21846     c3/return
    21847
    21848 $check-mu-numberlike-primitive:error-too-many-inouts:
    21849     (write-buffered *(ebp+0x10) "fn ")
    21850     8b/-> *(ebp+0xc) 0/r32/eax
    21851     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    21852     (write-buffered *(ebp+0x10) %eax)
    21853     (write-buffered *(ebp+0x10) ": stmt ")
    21854     (lookup *(esi+4) *(esi+8))  # Stmt1-operation Stmt1-operation => eax
    21855     (write-buffered *(ebp+0x10) %eax)
    21856     (write-buffered *(ebp+0x10) ": too many inouts; most primitives support at most two arguments, across inouts and outputs\n")
    21857     (flush *(ebp+0x10))
    21858     (stop *(ebp+0x14) 1)
    21859     # never gets here
    21860
    21861 $check-mu-numberlike-primitive:error-too-many-outputs:
    21862     (write-buffered *(ebp+0x10) "fn ")
    21863     8b/-> *(ebp+0xc) 0/r32/eax
    21864     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    21865     (write-buffered *(ebp+0x10) %eax)
    21866     (write-buffered *(ebp+0x10) ": stmt ")
    21867     (lookup *(esi+4) *(esi+8))  # Stmt1-operation Stmt1-operation => eax
    21868     (write-buffered *(ebp+0x10) %eax)
    21869     (write-buffered *(ebp+0x10) ": too many outputs; most primitives support at most one output\n")
    21870     (flush *(ebp+0x10))
    21871     (stop *(ebp+0x14) 1)
    21872     # never gets here
    21873
    21874 check-mu-numberlike-arg:  # v: (addr stmt-var), stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    21875     # . prologue
    21876     55/push-ebp
    21877     89/<- %ebp 4/r32/esp
    21878     # . save registers
    21879     50/push-eax
    21880     56/push-esi
    21881     # var t/esi: (addr type-tree) = lookup(v->value->type)
    21882     8b/-> *(ebp+8) 0/r32/eax
    21883     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    21884     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    21885     89/<- %esi 0/r32/eax
    21886 $check-mu-numberlike-arg:check-literal:
    21887     # if t is an int, return
    21888     (simple-mu-type? %esi 0)  # literal => eax
    21889     3d/compare-eax-and 0/imm32/false
    21890     0f 85/jump-if-!= $check-mu-numberlike-arg:end/disp32
    21891 $check-mu-numberlike-arg:check-addr:
    21892     # if t is an addr and v is dereferenced, return whether t->payload is an addr
    21893     {
    21894       (mu-addr-type? %esi)  # => eax
    21895       3d/compare-eax-and 0/imm32/false
    21896       74/jump-if-= break/disp8
    21897       8b/-> *(ebp+8) 0/r32/eax
    21898       8b/-> *(eax+0x10) 0/r32/eax  # Stmt-var-is-deref
    21899       3d/compare-eax-and 0/imm32/false
    21900       {
    21901         74/jump-if-= break/disp8
    21902         (lookup *(esi+0xc) *(esi+0x10))  # Type-tree-right Type-tree-right => eax
    21903         # if t->right is null, t = t->left
    21904         81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
    21905         {
    21906           75/jump-if-!= break/disp8
    21907           (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    21908         }
    21909         (mu-addr-type? %eax)  # => eax
    21910         3d/compare-eax-and 0/imm32/false
    21911         74/jump-if-= $check-mu-numberlike-arg:end/disp8
    21912       }
    21913     }
    21914 $check-mu-numberlike-arg:output-checks:
    21915     (check-mu-numberlike-output *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14) *(ebp+0x18))
    21916 $check-mu-numberlike-arg:end:
    21917     # . restore registers
    21918     5e/pop-to-esi
    21919     58/pop-to-eax
    21920     # . epilogue
    21921     89/<- %esp 5/r32/ebp
    21922     5d/pop-to-ebp
    21923     c3/return
    21924
    21925 check-mu-numberlike-output:  # v: (addr stmt-var), stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    21926     # . prologue
    21927     55/push-ebp
    21928     89/<- %ebp 4/r32/esp
    21929     # . save registers
    21930     50/push-eax
    21931     #
    21932     (mu-numberlike-output-var? *(ebp+8))  # => eax
    21933     3d/compare-eax-and 0/imm32/false
    21934     0f 84/jump-if-= $check-mu-numberlike-output:fail/disp32
    21935 $check-mu-numberlike-output:end:
    21936     # . restore registers
    21937     58/pop-to-eax
    21938     # . epilogue
    21939     89/<- %esp 5/r32/ebp
    21940     5d/pop-to-ebp
    21941     c3/return
    21942
    21943 $check-mu-numberlike-output:fail:
    21944     # otherwise raise an error
    21945     (write-buffered *(ebp+0x14) "fn ")
    21946     8b/-> *(ebp+0x10) 0/r32/eax
    21947     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    21948     (write-buffered *(ebp+0x14) %eax)
    21949     (write-buffered *(ebp+0x14) ": stmt ")
    21950     8b/-> *(ebp+0xc) 0/r32/eax
    21951     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
    21952     (write-buffered *(ebp+0x14) %eax)
    21953     (write-buffered *(ebp+0x14) ": '")
    21954     8b/-> *(ebp+8) 0/r32/eax
    21955     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    21956     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    21957     (write-buffered *(ebp+0x14) %eax)
    21958     (write-buffered *(ebp+0x14) "' must be a non-addr non-offset scalar\n")
    21959     (flush *(ebp+0x14))
    21960     (stop *(ebp+0x18) 1)
    21961     # never gets here
    21962
    21963 mu-numberlike-output-var?:  # v: (addr stmt-var) -> result/eax: boolean
    21964     # . prologue
    21965     55/push-ebp
    21966     89/<- %ebp 4/r32/esp
    21967     #
    21968     8b/-> *(ebp+8) 0/r32/eax
    21969     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    21970     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    21971     (mu-numberlike-output? %eax)  # => eax
    21972 $mu-numberlike-output-var?:end:
    21973     # . epilogue
    21974     89/<- %esp 5/r32/ebp
    21975     5d/pop-to-ebp
    21976     c3/return
    21977
    21978 mu-numberlike-output?:  # v: (addr type-tree) -> result/eax: boolean
    21979     # . prologue
    21980     55/push-ebp
    21981     89/<- %ebp 4/r32/esp
    21982     # . save registers
    21983     56/push-esi
    21984     # var t/esi: (addr type-tree) = lookup(v->value->type)
    21985     8b/-> *(ebp+8) 6/r32/esi
    21986 $mu-numberlike-output?:check-int:
    21987     # if t is an int, return
    21988     (simple-mu-type? %esi 1)  # int => eax
    21989     3d/compare-eax-and 0/imm32/false
    21990     0f 85/jump-if-!= $mu-numberlike-output?:return-true/disp32
    21991 $mu-numberlike-output?:check-float:
    21992     # if t is a float, return
    21993     (simple-mu-type? %esi 0xf)  # float => eax
    21994     3d/compare-eax-and 0/imm32/false
    21995     75/jump-if-!= $mu-numberlike-output?:return-true/disp8
    21996 $mu-numberlike-output?:check-boolean:
    21997     # if t is a boolean, return
    21998     (simple-mu-type? %esi 5)  # boolean => eax
    21999     3d/compare-eax-and 0/imm32/false
    22000     75/jump-if-!= $mu-numberlike-output?:return-true/disp8
    22001 $mu-numberlike-output?:check-byte:
    22002     # if t is a byte, return
    22003     (simple-mu-type? %esi 8)  # byte => eax
    22004     3d/compare-eax-and 0/imm32/false
    22005     75/jump-if-!= $mu-numberlike-output?:return-true/disp8
    22006 $mu-numberlike-output?:check-code-point:
    22007     # if t is a code-point, return
    22008     (simple-mu-type? %esi 0xd)  # code-point => eax
    22009     3d/compare-eax-and 0/imm32/false
    22010     75/jump-if-!= $mu-numberlike-output?:return-true/disp8
    22011 $mu-numberlike-output?:check-grapheme:
    22012     # if t is a grapheme, return
    22013     (simple-mu-type? %esi 0xe)  # grapheme => eax
    22014     3d/compare-eax-and 0/imm32/false
    22015     75/jump-if-!= $mu-numberlike-output?:return-true/disp8
    22016 $mu-numberlike-output?:return-false:
    22017     b8/copy-to-eax 0/imm32/false
    22018     eb/jump $mu-numberlike-output?:end/disp8
    22019 $mu-numberlike-output?:return-true:
    22020     b8/copy-to-eax 1/imm32/true
    22021 $mu-numberlike-output?:end:
    22022     # . restore registers
    22023     5e/pop-to-esi
    22024     # . epilogue
    22025     89/<- %esp 5/r32/ebp
    22026     5d/pop-to-ebp
    22027     c3/return
    22028
    22029 check-mu-copy-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    22030     # . prologue
    22031     55/push-ebp
    22032     89/<- %ebp 4/r32/esp
    22033     # . save registers
    22034     50/push-eax
    22035     51/push-ecx
    22036     52/push-edx
    22037     56/push-esi
    22038     57/push-edi
    22039     # var type-parameters/edx: (addr table (handle array byte) (addr type-tree) 8)
    22040     81 5/subop/subtract %esp 0x60/imm32
    22041     68/push 0x60/imm32/size
    22042     68/push 0/imm32/read
    22043     68/push 0/imm32/write
    22044     89/<- %edx 4/r32/esp
    22045 $check-mu-copy-stmt:get-output:
    22046     # esi = stmt
    22047     8b/-> *(ebp+8) 6/r32/esi
    22048     # var output/edi: (addr stmt-var) = stmt->outputs
    22049     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    22050     89/<- %edi 0/r32/eax
    22051     # zero outputs
    22052     3d/compare-eax-and 0/imm32
    22053     0f 84/jump-if-= $check-mu-copy-stmt:error-no-output/disp32
    22054     # > 1 output
    22055     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
    22056     3d/compare-eax-and 0/imm32
    22057     0f 85/jump-if-!= $check-mu-copy-stmt:error-too-many-outputs/disp32
    22058 $check-mu-copy-stmt:get-inout:
    22059     # var inout/esi: (addr stmt-var) = stmt->inouts
    22060     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    22061     89/<- %esi 0/r32/eax
    22062     # zero inouts
    22063     3d/compare-eax-and 0/imm32
    22064     0f 84/jump-if-= $check-mu-copy-stmt:error-no-inout/disp32
    22065     # > 1 inout
    22066     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
    22067     3d/compare-eax-and 0/imm32
    22068     0f 85/jump-if-!= $check-mu-copy-stmt:error-too-many-inouts/disp32
    22069 $check-mu-copy-stmt:types:
    22070     # if inout is not a scalar, abort
    22071     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    22072     (size-of %eax)  # => eax
    22073     3d/compare-eax-and 4/imm32
    22074     0f 8f/jump-if-> $check-mu-copy-stmt:error-inout-too-large/disp32
    22075     # var inout-type/ecx: (addr type-tree) = inout->value->type
    22076     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    22077     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    22078     89/<- %ecx 0/r32/eax
    22079     # if (inout->is-deref?) inout-type = inout-type->payload
    22080     8b/-> *(esi+0x10) 0/r32/eax  # Stmt-var-is-deref
    22081     3d/compare-eax-and 0/imm32/false
    22082     {
    22083       74/jump-if-= break/disp8
    22084       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
    22085       # if inout-type->right is null, t = inout-type->left
    22086       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
    22087       {
    22088         75/jump-if-!= break/disp8
    22089         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    22090       }
    22091       89/<- %ecx 0/r32/eax
    22092     }
    22093     # if output not in register, abort
    22094     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    22095     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    22096     3d/compare-eax-and 0/imm32
    22097     0f 84/jump-if-= $check-mu-copy-stmt:error-output-not-in-register/disp32
    22098     # var output-type/eax: (addr type-tree) = output->value->type
    22099     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    22100     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    22101     # if (inout-type == output-type) return
    22102     (type-match? %eax %ecx %edx)  # => eax
    22103     3d/compare-eax-and 0/imm32
    22104     0f 85/jump-if-!= $check-mu-copy-stmt:end/disp32
    22105     # if output is an addr and inout is 0, return
    22106     {
    22107       (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    22108       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    22109       (mu-addr-type? %eax)  # => eax
    22110       3d/compare-eax-and 0/imm32/false
    22111       74/jump-if-= break/disp8
    22112       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    22113       (lookup *eax *(eax+4))  # Var-name Var-name => eax
    22114       (string-equal? %eax "0")  # => eax
    22115       3d/compare-eax-and 0/imm32/false
    22116       74/jump-if-= break/disp8
    22117       e9/jump $check-mu-copy-stmt:end/disp32
    22118     }
    22119     # if output is an offset and inout is 0, return
    22120     {
    22121       (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    22122       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    22123       81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
    22124       75/jump-if-!= break/disp8
    22125       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    22126       (simple-mu-type? %eax 7)  # offset => eax
    22127       3d/compare-eax-and 0/imm32/false
    22128       74/jump-if-= break/disp8
    22129       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    22130       (lookup *eax *(eax+4))  # Var-name Var-name => eax
    22131       (string-equal? %eax "0")  # => eax
    22132       3d/compare-eax-and 0/imm32/false
    22133       74/jump-if-= break/disp8
    22134       e9/jump $check-mu-copy-stmt:end/disp32
    22135     }
    22136     # if output is a byte, abort if inout is not a literal. Otherwise return.
    22137     {
    22138       (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    22139       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    22140       (simple-mu-type? %eax 8)  # byte => eax
    22141       3d/compare-eax-and 0/imm32/false
    22142       74/jump-if-= break/disp8
    22143       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    22144       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    22145       (simple-mu-type? %eax 0)  # literal => eax
    22146       3d/compare-eax-and 0/imm32/false
    22147       0f 84/jump-if-= $check-mu-copy-stmt:error-non-literal-to-byte/disp32
    22148       eb/jump $check-mu-copy-stmt:end/disp8
    22149     }
    22150     # if output is not number-like, abort
    22151     (check-mu-numberlike-output %edi *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    22152 $check-mu-copy-stmt:end:
    22153     # . reclaim locals
    22154     81 0/subop/add %esp 0x6c/imm32
    22155     # . restore registers
    22156     5f/pop-to-edi
    22157     5e/pop-to-esi
    22158     5a/pop-to-edx
    22159     59/pop-to-ecx
    22160     58/pop-to-eax
    22161     # . epilogue
    22162     89/<- %esp 5/r32/ebp
    22163     5d/pop-to-ebp
    22164     c3/return
    22165
    22166 $check-mu-copy-stmt:error-no-inout:
    22167     (write-buffered *(ebp+0x10) "fn ")
    22168     8b/-> *(ebp+0xc) 0/r32/eax
    22169     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22170     (write-buffered *(ebp+0x10) %eax)
    22171     (write-buffered *(ebp+0x10) ": stmt 'copy' expects an inout\n")
    22172     (flush *(ebp+0x10))
    22173     (stop *(ebp+0x14) 1)
    22174     # never gets here
    22175
    22176 $check-mu-copy-stmt:error-too-many-inouts:
    22177     (write-buffered *(ebp+0x10) "fn ")
    22178     8b/-> *(ebp+0xc) 0/r32/eax
    22179     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22180     (write-buffered *(ebp+0x10) %eax)
    22181     (write-buffered *(ebp+0x10) ": stmt 'copy' must have just one inout\n")
    22182     (flush *(ebp+0x10))
    22183     (stop *(ebp+0x14) 1)
    22184     # never gets here
    22185
    22186 $check-mu-copy-stmt:error-no-output:
    22187     (write-buffered *(ebp+0x10) "fn ")
    22188     8b/-> *(ebp+0xc) 0/r32/eax
    22189     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22190     (write-buffered *(ebp+0x10) %eax)
    22191     (write-buffered *(ebp+0x10) ": stmt 'copy' expects an output\n")
    22192     (flush *(ebp+0x10))
    22193     (stop *(ebp+0x14) 1)
    22194     # never gets here
    22195
    22196 $check-mu-copy-stmt:error-output-not-in-register:
    22197     (write-buffered *(ebp+0x10) "fn ")
    22198     8b/-> *(ebp+0xc) 0/r32/eax
    22199     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22200     (write-buffered *(ebp+0x10) %eax)
    22201     (write-buffered *(ebp+0x10) ": stmt copy: output '")
    22202     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    22203     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    22204     (write-buffered *(ebp+0x10) %eax)
    22205     (write-buffered *(ebp+0x10) "' not in a register\n")
    22206     (flush *(ebp+0x10))
    22207     (stop *(ebp+0x14) 1)
    22208     # never gets here
    22209
    22210 $check-mu-copy-stmt:error-too-many-outputs:
    22211     (write-buffered *(ebp+0x10) "fn ")
    22212     8b/-> *(ebp+0xc) 0/r32/eax
    22213     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22214     (write-buffered *(ebp+0x10) %eax)
    22215     (write-buffered *(ebp+0x10) ": stmt 'copy' must have just one output\n")
    22216     (flush *(ebp+0x10))
    22217     (stop *(ebp+0x14) 1)
    22218     # never gets here
    22219
    22220 $check-mu-copy-stmt:error-inout-too-large:
    22221     (write-buffered *(ebp+0x10) "fn ")
    22222     8b/-> *(ebp+0xc) 0/r32/eax
    22223     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22224     (write-buffered *(ebp+0x10) %eax)
    22225     (write-buffered *(ebp+0x10) ": stmt copy: '")
    22226     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    22227     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    22228     (write-buffered *(ebp+0x10) %eax)
    22229     (write-buffered *(ebp+0x10) "' is too large to fit in a register\n")
    22230     (flush *(ebp+0x10))
    22231     (stop *(ebp+0x14) 1)
    22232     # never gets here
    22233
    22234 $check-mu-copy-stmt:error-non-literal-to-byte:
    22235     (write-buffered *(ebp+0x10) "fn ")
    22236     8b/-> *(ebp+0xc) 0/r32/eax
    22237     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22238     (write-buffered *(ebp+0x10) %eax)
    22239     (write-buffered *(ebp+0x10) ": stmt copy: cannot copy non-literal to '")
    22240     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    22241     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    22242     (write-buffered *(ebp+0x10) %eax)
    22243     (write-buffered *(ebp+0x10) "' of type byte; use copy-byte\n")
    22244     (flush *(ebp+0x10))
    22245     (stop *(ebp+0x14) 1)
    22246     # never gets here
    22247
    22248 check-mu-copy-to-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    22249     # . prologue
    22250     55/push-ebp
    22251     89/<- %ebp 4/r32/esp
    22252     # . save registers
    22253     50/push-eax
    22254     51/push-ecx
    22255     52/push-edx
    22256     53/push-ebx
    22257     56/push-esi
    22258     57/push-edi
    22259     # var type-parameters/edx: (addr table (handle array byte) (addr type-tree) 8)
    22260     81 5/subop/subtract %esp 0x60/imm32
    22261     68/push 0x60/imm32/size
    22262     68/push 0/imm32/read
    22263     68/push 0/imm32/write
    22264     89/<- %edx 4/r32/esp
    22265     # esi = stmt
    22266     8b/-> *(ebp+8) 6/r32/esi
    22267 $check-mu-copy-to-stmt:check-for-output:
    22268     # if stmt->outputs abort
    22269     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    22270     3d/compare-eax-and 0/imm32
    22271     0f 85/jump-if-!= $check-mu-copy-to-stmt:error-too-many-outputs/disp32
    22272 $check-mu-copy-to-stmt:get-dest:
    22273     # var dest/edi: (addr stmt-var) = stmt->inouts
    22274     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    22275     89/<- %edi 0/r32/eax
    22276     # zero inouts
    22277     3d/compare-eax-and 0/imm32
    22278     0f 84/jump-if-= $check-mu-copy-to-stmt:error-incorrect-inouts/disp32
    22279 $check-mu-copy-to-stmt:get-src:
    22280     # var src/esi: (addr stmt-var) = dest->next
    22281     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
    22282     89/<- %esi 0/r32/eax
    22283     # 1 inout
    22284     3d/compare-eax-and 0/imm32
    22285     0f 84/jump-if-= $check-mu-copy-to-stmt:error-incorrect-inouts/disp32
    22286     # > 2 inouts
    22287     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
    22288     3d/compare-eax-and 0/imm32
    22289     0f 85/jump-if-!= $check-mu-copy-to-stmt:error-incorrect-inouts/disp32
    22290 $check-mu-copy-to-stmt:types:
    22291     # if src is not a scalar, abort
    22292     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    22293     (size-of %eax)  # => eax
    22294     3d/compare-eax-and 4/imm32
    22295     0f 8f/jump-if-> $check-mu-copy-to-stmt:error-src-too-large/disp32
    22296     # var src-type/ecx: (addr type-tree) = src->value->type
    22297     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    22298     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    22299     89/<- %ecx 0/r32/eax
    22300     # if src not in register or literal, abort
    22301     # (we can't use stack-offset because it hasn't been computed yet)
    22302     {
    22303       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    22304       (lookup *(eax+0x8) *(eax+0xc))  # Var-type Var-type => eax
    22305       (simple-mu-type? %eax 0)  # => eax
    22306       3d/compare-eax-and 0/imm32
    22307       75/jump-if-!= break/disp8
    22308       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    22309       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    22310       3d/compare-eax-and 0/imm32
    22311       75/jump-if-!= break/disp8
    22312       e9/jump $check-mu-copy-to-stmt:error-src-not-literal-or-in-register/disp32
    22313     }
    22314     # var dest-type/ebx: (addr type-tree) = dest->value->type
    22315     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    22316     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    22317     89/<- %ebx 0/r32/eax
    22318     # if (dest->is-deref?) dest-type = dest-type->payload
    22319 $check-mu-copy-to-stmt:check-dest-deref:
    22320     8b/-> *(edi+0x10) 0/r32/eax  # Stmt-var-is-deref
    22321     3d/compare-eax-and 0/imm32/false
    22322     {
    22323       74/jump-if-= break/disp8
    22324       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
    22325 $check-mu-copy-to-stmt:dest-is-deref:
    22326       # if dest-type->right is null, dest-type = dest-type->left
    22327       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
    22328       {
    22329         75/jump-if-!= break/disp8
    22330 $check-mu-copy-to-stmt:dest-is-deref2:
    22331         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    22332       }
    22333       89/<- %ebx 0/r32/eax
    22334     }
    22335     # if dest is a byte and src is not a literal, abort
    22336     {
    22337 $check-mu-copy-to-stmt:final-check-byte:
    22338       (simple-mu-type? %ebx 8)  # byte => eax
    22339       3d/compare-eax-and 0/imm32/false
    22340       74/jump-if-= break/disp8
    22341       (simple-mu-type? %ecx 0)  # literal => eax
    22342       3d/compare-eax-and 0/imm32/false
    22343       0f 84/jump-if-= $check-mu-copy-to-stmt:error-non-literal-to-byte/disp32
    22344     }
    22345     # if (src-type == dest-type) return
    22346     (type-match? %ebx %ecx %edx)  # => eax
    22347     3d/compare-eax-and 0/imm32
    22348     0f 85/jump-if-!= $check-mu-copy-to-stmt:end/disp32
    22349     # if dest is an addr and src is 0, return
    22350     {
    22351 $check-mu-copy-to-stmt:final-check-addr:
    22352       (mu-addr-type? %ebx)  # => eax
    22353       3d/compare-eax-and 0/imm32/false
    22354       74/jump-if-= break/disp8
    22355       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    22356       (lookup *eax *(eax+4))  # Var-name Var-name => eax
    22357       (string-equal? %eax "0")  # => eax
    22358       3d/compare-eax-and 0/imm32/false
    22359       74/jump-if-= break/disp8
    22360       e9/jump $check-mu-copy-to-stmt:end/disp32
    22361     }
    22362     # if dest is an offset and src is 0, return
    22363     {
    22364 $check-mu-copy-to-stmt:final-check-offset:
    22365       81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
    22366       75/jump-if-!= break/disp8
    22367       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
    22368       (simple-mu-type? %eax 7)  # offset => eax
    22369       3d/compare-eax-and 0/imm32/false
    22370       74/jump-if-= break/disp8
    22371       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    22372       (lookup *eax *(eax+4))  # Var-name Var-name => eax
    22373       (string-equal? %eax "0")  # => eax
    22374       3d/compare-eax-and 0/imm32/false
    22375       74/jump-if-= break/disp8
    22376       e9/jump $check-mu-copy-to-stmt:end/disp32
    22377     }
    22378     # if dest is not number-like, abort
    22379     (check-mu-numberlike-arg %edi *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    22380 $check-mu-copy-to-stmt:end:
    22381     # . reclaim locals
    22382     81 0/subop/add %esp 0x6c/imm32
    22383     # . restore registers
    22384     5f/pop-to-edi
    22385     5e/pop-to-esi
    22386     5b/pop-to-ebx
    22387     5a/pop-to-edx
    22388     59/pop-to-ecx
    22389     58/pop-to-eax
    22390     # . epilogue
    22391     89/<- %esp 5/r32/ebp
    22392     5d/pop-to-ebp
    22393     c3/return
    22394
    22395 $check-mu-copy-to-stmt:error-incorrect-inouts:
    22396     (write-buffered *(ebp+0x10) "fn ")
    22397     8b/-> *(ebp+0xc) 0/r32/eax
    22398     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22399     (write-buffered *(ebp+0x10) %eax)
    22400     (write-buffered *(ebp+0x10) ": stmt 'copy-to' must have two inouts\n")
    22401     (flush *(ebp+0x10))
    22402     (stop *(ebp+0x14) 1)
    22403     # never gets here
    22404
    22405 $check-mu-copy-to-stmt:error-too-many-outputs:
    22406     (write-buffered *(ebp+0x10) "fn ")
    22407     8b/-> *(ebp+0xc) 0/r32/eax
    22408     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22409     (write-buffered *(ebp+0x10) %eax)
    22410     (write-buffered *(ebp+0x10) ": stmt 'copy-to' must not have any outputs\n")
    22411     (flush *(ebp+0x10))
    22412     (stop *(ebp+0x14) 1)
    22413     # never gets here
    22414
    22415 $check-mu-copy-to-stmt:error-src-not-literal-or-in-register:
    22416     (write-buffered *(ebp+0x10) "fn ")
    22417     8b/-> *(ebp+0xc) 0/r32/eax
    22418     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22419     (write-buffered *(ebp+0x10) %eax)
    22420     (write-buffered *(ebp+0x10) ": stmt copy-to: source (second inout) is in memory\n")
    22421     (flush *(ebp+0x10))
    22422     (stop *(ebp+0x14) 1)
    22423     # never gets here
    22424
    22425 $check-mu-copy-to-stmt:error-src-too-large:
    22426     (write-buffered *(ebp+0x10) "fn ")
    22427     8b/-> *(ebp+0xc) 0/r32/eax
    22428     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22429     (write-buffered *(ebp+0x10) %eax)
    22430     (write-buffered *(ebp+0x10) ": stmt copy-to: '")
    22431     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    22432     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    22433     (write-buffered *(ebp+0x10) %eax)
    22434     (write-buffered *(ebp+0x10) "' is too large to copy\n")
    22435     (flush *(ebp+0x10))
    22436     (stop *(ebp+0x14) 1)
    22437     # never gets here
    22438
    22439 $check-mu-copy-to-stmt:error-non-literal-to-byte:
    22440     (write-buffered *(ebp+0x10) "fn ")
    22441     8b/-> *(ebp+0xc) 0/r32/eax
    22442     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22443     (write-buffered *(ebp+0x10) %eax)
    22444     (write-buffered *(ebp+0x10) ": stmt copy-to: cannot copy non-literal to type byte; use copy-byte-to\n")
    22445     (flush *(ebp+0x10))
    22446     (stop *(ebp+0x14) 1)
    22447     # never gets here
    22448
    22449 check-mu-copy-byte-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    22450     # . prologue
    22451     55/push-ebp
    22452     89/<- %ebp 4/r32/esp
    22453     # . save registers
    22454     50/push-eax
    22455     51/push-ecx
    22456     52/push-edx
    22457     56/push-esi
    22458     57/push-edi
    22459     # var type-parameters/edx: (addr table (handle array byte) (addr type-tree) 8)
    22460     81 5/subop/subtract %esp 0x60/imm32
    22461     68/push 0x60/imm32/size
    22462     68/push 0/imm32/read
    22463     68/push 0/imm32/write
    22464     89/<- %edx 4/r32/esp
    22465 $check-mu-copy-byte-stmt:get-output:
    22466     # esi = stmt
    22467     8b/-> *(ebp+8) 6/r32/esi
    22468     # var output/edi: (addr stmt-var) = stmt->outputs
    22469     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    22470     89/<- %edi 0/r32/eax
    22471     # zero outputs
    22472     3d/compare-eax-and 0/imm32
    22473     0f 84/jump-if-= $check-mu-copy-byte-stmt:error-no-output/disp32
    22474     # > 1 output
    22475     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
    22476     3d/compare-eax-and 0/imm32
    22477     0f 85/jump-if-!= $check-mu-copy-byte-stmt:error-too-many-outputs/disp32
    22478 $check-mu-copy-byte-stmt:get-inout:
    22479     # var inout/esi: (addr stmt-var) = stmt->inouts
    22480     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    22481     89/<- %esi 0/r32/eax
    22482     # zero inouts
    22483     3d/compare-eax-and 0/imm32
    22484     0f 84/jump-if-= $check-mu-copy-byte-stmt:error-no-inout/disp32
    22485     # > 1 inout
    22486     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
    22487     3d/compare-eax-and 0/imm32
    22488     0f 85/jump-if-!= $check-mu-copy-byte-stmt:error-too-many-inouts/disp32
    22489 $check-mu-copy-byte-stmt:types:
    22490     # if inout is not a scalar, abort
    22491     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    22492     (size-of %eax)  # => eax
    22493     3d/compare-eax-and 4/imm32
    22494     0f 8f/jump-if-> $check-mu-copy-byte-stmt:error-inout-too-large/disp32
    22495     # var inout-type/ecx: (addr type-tree) = inout->value->type
    22496     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    22497     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    22498     89/<- %ecx 0/r32/eax
    22499 $check-mu-copy-byte-stmt:check-inout-deref:
    22500     # if (inout->is-deref?) inout-type = inout-type->payload
    22501     8b/-> *(esi+0x10) 0/r32/eax  # Stmt-var-is-deref
    22502     3d/compare-eax-and 0/imm32/false
    22503     {
    22504       74/jump-if-= break/disp8
    22505 $check-mu-copy-byte-stmt:inout-is-deref:
    22506       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
    22507       # if inout-type->right is null, t = inout-type->left
    22508       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
    22509       {
    22510         75/jump-if-!= break/disp8
    22511 $check-mu-copy-byte-stmt:inout-is-deref2:
    22512         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    22513       }
    22514       89/<- %ecx 0/r32/eax
    22515     }
    22516     # if output not in register, abort
    22517     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    22518     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    22519     3d/compare-eax-and 0/imm32
    22520     0f 84/jump-if-= $check-mu-copy-byte-stmt:error-output-not-in-register/disp32
    22521     # var output-type/eax: (addr type-tree) = output->value->type
    22522     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    22523     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    22524     # if output is not of type byte, abort
    22525     (simple-mu-type? %eax 8)  # byte => eax
    22526     3d/compare-eax-and 0/imm32
    22527     0f 84/jump-if-= $check-mu-copy-byte-stmt:error-invalid-output-type/disp32
    22528 $check-mu-copy-byte-stmt:end:
    22529     # . reclaim locals
    22530     81 0/subop/add %esp 0x6c/imm32
    22531     # . restore registers
    22532     5f/pop-to-edi
    22533     5e/pop-to-esi
    22534     5a/pop-to-edx
    22535     59/pop-to-ecx
    22536     58/pop-to-eax
    22537     # . epilogue
    22538     89/<- %esp 5/r32/ebp
    22539     5d/pop-to-ebp
    22540     c3/return
    22541
    22542 $check-mu-copy-byte-stmt:error-no-inout:
    22543     (write-buffered *(ebp+0x10) "fn ")
    22544     8b/-> *(ebp+0xc) 0/r32/eax
    22545     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22546     (write-buffered *(ebp+0x10) %eax)
    22547     (write-buffered *(ebp+0x10) ": stmt 'copy-byte' expects an inout\n")
    22548     (flush *(ebp+0x10))
    22549     (stop *(ebp+0x14) 1)
    22550     # never gets here
    22551
    22552 $check-mu-copy-byte-stmt:error-too-many-inouts:
    22553     (write-buffered *(ebp+0x10) "fn ")
    22554     8b/-> *(ebp+0xc) 0/r32/eax
    22555     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22556     (write-buffered *(ebp+0x10) %eax)
    22557     (write-buffered *(ebp+0x10) ": stmt 'copy-byte' must have just one inout\n")
    22558     (flush *(ebp+0x10))
    22559     (stop *(ebp+0x14) 1)
    22560     # never gets here
    22561
    22562 $check-mu-copy-byte-stmt:error-no-output:
    22563     (write-buffered *(ebp+0x10) "fn ")
    22564     8b/-> *(ebp+0xc) 0/r32/eax
    22565     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22566     (write-buffered *(ebp+0x10) %eax)
    22567     (write-buffered *(ebp+0x10) ": stmt 'copy-byte' expects an output\n")
    22568     (flush *(ebp+0x10))
    22569     (stop *(ebp+0x14) 1)
    22570     # never gets here
    22571
    22572 $check-mu-copy-byte-stmt:error-output-not-in-register:
    22573     (write-buffered *(ebp+0x10) "fn ")
    22574     8b/-> *(ebp+0xc) 0/r32/eax
    22575     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22576     (write-buffered *(ebp+0x10) %eax)
    22577     (write-buffered *(ebp+0x10) ": stmt copy-byte: output '")
    22578     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    22579     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    22580     (write-buffered *(ebp+0x10) %eax)
    22581     (write-buffered *(ebp+0x10) "' not in a register\n")
    22582     (flush *(ebp+0x10))
    22583     (stop *(ebp+0x14) 1)
    22584     # never gets here
    22585
    22586 $check-mu-copy-byte-stmt:error-too-many-outputs:
    22587     (write-buffered *(ebp+0x10) "fn ")
    22588     8b/-> *(ebp+0xc) 0/r32/eax
    22589     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22590     (write-buffered *(ebp+0x10) %eax)
    22591     (write-buffered *(ebp+0x10) ": stmt 'copy-byte' must have just one output\n")
    22592     (flush *(ebp+0x10))
    22593     (stop *(ebp+0x14) 1)
    22594     # never gets here
    22595
    22596 $check-mu-copy-byte-stmt:error-invalid-output-type:
    22597     (write-buffered *(ebp+0x10) "fn ")
    22598     8b/-> *(ebp+0xc) 0/r32/eax
    22599     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22600     (write-buffered *(ebp+0x10) %eax)
    22601     (write-buffered *(ebp+0x10) ": stmt 'copy-byte' must write to output of type byte\n")
    22602     (flush *(ebp+0x10))
    22603     (stop *(ebp+0x14) 1)
    22604     # never gets here
    22605
    22606 $check-mu-copy-byte-stmt:error-inout-too-large:
    22607     (write-buffered *(ebp+0x10) "fn ")
    22608     8b/-> *(ebp+0xc) 0/r32/eax
    22609     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22610     (write-buffered *(ebp+0x10) %eax)
    22611     (write-buffered *(ebp+0x10) ": stmt copy-byte: '")
    22612     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    22613     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    22614     (write-buffered *(ebp+0x10) %eax)
    22615     (write-buffered *(ebp+0x10) "' is too large to fit in a register\n")
    22616     (flush *(ebp+0x10))
    22617     (stop *(ebp+0x14) 1)
    22618     # never gets here
    22619
    22620 check-mu-copy-byte-to-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    22621     # . prologue
    22622     55/push-ebp
    22623     89/<- %ebp 4/r32/esp
    22624     # . save registers
    22625     50/push-eax
    22626     52/push-edx
    22627     53/push-ebx
    22628     56/push-esi
    22629     57/push-edi
    22630     # var type-parameters/edx: (addr table (handle array byte) (addr type-tree) 8)
    22631     81 5/subop/subtract %esp 0x60/imm32
    22632     68/push 0x60/imm32/size
    22633     68/push 0/imm32/read
    22634     68/push 0/imm32/write
    22635     89/<- %edx 4/r32/esp
    22636     # esi = stmt
    22637     8b/-> *(ebp+8) 6/r32/esi
    22638 $check-mu-copy-byte-to-stmt:check-for-output:
    22639     # if stmt->outputs abort
    22640     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    22641     3d/compare-eax-and 0/imm32
    22642     0f 85/jump-if-!= $check-mu-copy-byte-to-stmt:error-too-many-outputs/disp32
    22643 $check-mu-copy-byte-to-stmt:get-dest:
    22644     # var dest/edi: (addr stmt-var) = stmt->inouts
    22645     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    22646     89/<- %edi 0/r32/eax
    22647     # zero inouts
    22648     3d/compare-eax-and 0/imm32
    22649     0f 84/jump-if-= $check-mu-copy-byte-to-stmt:error-incorrect-inouts/disp32
    22650 $check-mu-copy-byte-to-stmt:get-src:
    22651     # var src/esi: (addr stmt-var) = dest->next
    22652     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
    22653     89/<- %esi 0/r32/eax
    22654     # 1 inout
    22655     3d/compare-eax-and 0/imm32
    22656     0f 84/jump-if-= $check-mu-copy-byte-to-stmt:error-incorrect-inouts/disp32
    22657     # > 2 inouts
    22658     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
    22659     3d/compare-eax-and 0/imm32
    22660     0f 85/jump-if-!= $check-mu-copy-byte-to-stmt:error-incorrect-inouts/disp32
    22661 $check-mu-copy-byte-to-stmt:types:
    22662     # if src is not a scalar, abort
    22663     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    22664     (size-of %eax)  # => eax
    22665     3d/compare-eax-and 4/imm32
    22666     0f 8f/jump-if-> $check-mu-copy-byte-to-stmt:error-src-too-large/disp32
    22667     # if src not in register, abort
    22668     {
    22669       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    22670       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    22671       3d/compare-eax-and 0/imm32
    22672       75/jump-if-!= break/disp8
    22673       e9/jump $check-mu-copy-byte-to-stmt:error-src-not-in-register/disp32
    22674     }
    22675     # var dest-type/ebx: (addr type-tree) = dest->value->type
    22676     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    22677     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    22678     89/<- %ebx 0/r32/eax
    22679     # if (dest->is-deref?) dest-type = dest-type->payload
    22680 $check-mu-copy-byte-to-stmt:check-dest-deref:
    22681     8b/-> *(edi+0x10) 0/r32/eax  # Stmt-var-is-deref
    22682     3d/compare-eax-and 0/imm32/false
    22683     {
    22684       74/jump-if-= break/disp8
    22685       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
    22686 $check-mu-copy-byte-to-stmt:dest-is-deref:
    22687       # if dest-type->right is null, dest-type = dest-type->left
    22688       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
    22689       {
    22690         75/jump-if-!= break/disp8
    22691 $check-mu-copy-byte-to-stmt:dest-is-deref2:
    22692         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    22693       }
    22694       89/<- %ebx 0/r32/eax
    22695     }
    22696     # if dest is not a byte, abort
    22697     (simple-mu-type? %ebx 8)  # byte => eax
    22698     3d/compare-eax-and 0/imm32/false
    22699     0f 84/jump-if-= $check-mu-copy-byte-to-stmt:error-invalid-dest-type/disp32
    22700 $check-mu-copy-byte-to-stmt:end:
    22701     # . reclaim locals
    22702     81 0/subop/add %esp 0x6c/imm32
    22703     # . restore registers
    22704     5f/pop-to-edi
    22705     5e/pop-to-esi
    22706     5b/pop-to-ebx
    22707     5a/pop-to-edx
    22708     58/pop-to-eax
    22709     # . epilogue
    22710     89/<- %esp 5/r32/ebp
    22711     5d/pop-to-ebp
    22712     c3/return
    22713
    22714 $check-mu-copy-byte-to-stmt:error-incorrect-inouts:
    22715     (write-buffered *(ebp+0x10) "fn ")
    22716     8b/-> *(ebp+0xc) 0/r32/eax
    22717     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22718     (write-buffered *(ebp+0x10) %eax)
    22719     (write-buffered *(ebp+0x10) ": stmt 'copy-byte-to' must have two inouts\n")
    22720     (flush *(ebp+0x10))
    22721     (stop *(ebp+0x14) 1)
    22722     # never gets here
    22723
    22724 $check-mu-copy-byte-to-stmt:error-too-many-outputs:
    22725     (write-buffered *(ebp+0x10) "fn ")
    22726     8b/-> *(ebp+0xc) 0/r32/eax
    22727     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22728     (write-buffered *(ebp+0x10) %eax)
    22729     (write-buffered *(ebp+0x10) ": stmt 'copy-byte-to' must not have any outputs\n")
    22730     (flush *(ebp+0x10))
    22731     (stop *(ebp+0x14) 1)
    22732     # never gets here
    22733
    22734 $check-mu-copy-byte-to-stmt:error-src-not-in-register:
    22735     (write-buffered *(ebp+0x10) "fn ")
    22736     8b/-> *(ebp+0xc) 0/r32/eax
    22737     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22738     (write-buffered *(ebp+0x10) %eax)
    22739     (write-buffered *(ebp+0x10) ": stmt copy-byte-to: source (second inout) must be in a register\n")
    22740     (flush *(ebp+0x10))
    22741     (stop *(ebp+0x14) 1)
    22742     # never gets here
    22743
    22744 $check-mu-copy-byte-to-stmt:error-invalid-dest-type:
    22745     (write-buffered *(ebp+0x10) "fn ")
    22746     8b/-> *(ebp+0xc) 0/r32/eax
    22747     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22748     (write-buffered *(ebp+0x10) %eax)
    22749     (write-buffered *(ebp+0x10) ": stmt copy-byte-to: '")
    22750     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    22751     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    22752     (write-buffered *(ebp+0x10) %eax)
    22753     (write-buffered *(ebp+0x10) "' must be a byte\n")
    22754     (flush *(ebp+0x10))
    22755     (stop *(ebp+0x14) 1)
    22756     # never gets here
    22757
    22758 $check-mu-copy-byte-to-stmt:error-src-too-large:
    22759     (write-buffered *(ebp+0x10) "fn ")
    22760     8b/-> *(ebp+0xc) 0/r32/eax
    22761     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22762     (write-buffered *(ebp+0x10) %eax)
    22763     (write-buffered *(ebp+0x10) ": stmt copy-byte-to: '")
    22764     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    22765     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    22766     (write-buffered *(ebp+0x10) %eax)
    22767     (write-buffered *(ebp+0x10) "' is too large to copy\n")
    22768     (flush *(ebp+0x10))
    22769     (stop *(ebp+0x14) 1)
    22770     # never gets here
    22771
    22772 check-mu-compare-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    22773     # . prologue
    22774     55/push-ebp
    22775     89/<- %ebp 4/r32/esp
    22776     # . save registers
    22777     50/push-eax
    22778     51/push-ecx
    22779     52/push-edx
    22780     53/push-ebx
    22781     56/push-esi
    22782     57/push-edi
    22783     # var type-parameters/edx: (addr table (handle array byte) (addr type-tree) 8)
    22784     81 5/subop/subtract %esp 0x60/imm32
    22785     68/push 0x60/imm32/size
    22786     68/push 0/imm32/read
    22787     68/push 0/imm32/write
    22788     89/<- %edx 4/r32/esp
    22789     # esi = stmt
    22790     8b/-> *(ebp+8) 6/r32/esi
    22791 $check-mu-compare-stmt:check-for-output:
    22792     # if stmt->outputs abort
    22793     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    22794     3d/compare-eax-and 0/imm32
    22795     0f 85/jump-if-!= $check-mu-compare-stmt:error-too-many-outputs/disp32
    22796 $check-mu-compare-stmt:get-left:
    22797     # var left/edi: (addr stmt-var) = stmt->inouts
    22798     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    22799     89/<- %edi 0/r32/eax
    22800     # zero inouts
    22801     3d/compare-eax-and 0/imm32
    22802     0f 84/jump-if-= $check-mu-compare-stmt:error-incorrect-inouts/disp32
    22803 $check-mu-compare-stmt:get-right:
    22804     # var right/esi: (addr stmt-var) = left->next
    22805     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
    22806     89/<- %esi 0/r32/eax
    22807     # 1 inout
    22808     3d/compare-eax-and 0/imm32
    22809     0f 84/jump-if-= $check-mu-compare-stmt:error-incorrect-inouts/disp32
    22810     # > 2 inouts
    22811     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
    22812     3d/compare-eax-and 0/imm32
    22813     0f 85/jump-if-!= $check-mu-compare-stmt:error-incorrect-inouts/disp32
    22814     # if both inouts are in memory, abort
    22815     {
    22816 $check-mu-compare-stmt:both-in-mem:
    22817       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    22818       (lookup *(eax+0x8) *(eax+0xc))  # Var-type Var-type => eax
    22819       (simple-mu-type? %eax 0)  # => eax
    22820       3d/compare-eax-and 0/imm32
    22821       0f 85/jump-if-!= break/disp32
    22822       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    22823       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    22824       3d/compare-eax-and 0/imm32
    22825       75/jump-if-!= break/disp8
    22826       (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    22827       (lookup *(eax+0x8) *(eax+0xc))  # Var-type Var-type => eax
    22828       (simple-mu-type? %eax 0)  # => eax
    22829       3d/compare-eax-and 0/imm32
    22830       75/jump-if-!= break/disp8
    22831       (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    22832       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    22833       3d/compare-eax-and 0/imm32
    22834       75/jump-if-!= break/disp8
    22835       e9/jump $check-mu-compare-stmt:error-both-in-memory/disp32
    22836     }
    22837 $check-mu-compare-stmt:types:
    22838     # var right-type/ecx: (addr type-tree) = right->value->type
    22839     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    22840     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    22841     89/<- %ecx 0/r32/eax
    22842     # if (right->is-deref?) right-type = right-type->payload
    22843     8b/-> *(esi+0x10) 0/r32/eax  # Stmt-var-is-deref
    22844     3d/compare-eax-and 0/imm32/false
    22845     {
    22846       74/jump-if-= break/disp8
    22847       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
    22848       # if right-type->right is null, right-type = right-type->left
    22849       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
    22850       {
    22851         75/jump-if-!= break/disp8
    22852         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    22853       }
    22854       89/<- %ecx 0/r32/eax
    22855     }
    22856     # if right-type is a literal string, abort
    22857     (simple-mu-type? %ecx 0x10)  # string-literal => eax
    22858     3d/compare-eax-and 0/imm32/false
    22859     0f 85/jump-if-!= $check-mu-compare-stmt:error-right-string-literal/disp32
    22860     # if right is not a scalar, abort
    22861     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    22862     (size-of %eax)  # => eax
    22863     3d/compare-eax-and 4/imm32
    22864     0f 8f/jump-if-> $check-mu-compare-stmt:error-right-too-large/disp32
    22865     # if left is not a scalar, abort
    22866     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    22867     (size-of %eax)  # => eax
    22868     3d/compare-eax-and 4/imm32
    22869     0f 8f/jump-if-> $check-mu-compare-stmt:error-left-too-large/disp32
    22870     # var left-type/ebx: (addr type-tree) = left->value->type
    22871     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    22872     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    22873     89/<- %ebx 0/r32/eax
    22874     # if (left->is-deref?) left-type = left-type->payload
    22875     8b/-> *(edi+0x10) 0/r32/eax  # Stmt-var-is-deref
    22876     3d/compare-eax-and 0/imm32/false
    22877     {
    22878       74/jump-if-= break/disp8
    22879       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
    22880       # if left-type->right is null, left-type = left-type->left
    22881       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
    22882       {
    22883         75/jump-if-!= break/disp8
    22884         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    22885       }
    22886       89/<- %ebx 0/r32/eax
    22887     }
    22888     # if (left-type == right-type) return
    22889     (type-match? %ebx %ecx %edx)  # => eax
    22890     3d/compare-eax-and 0/imm32
    22891     0f 85/jump-if-!= $check-mu-compare-stmt:end/disp32
    22892     # if left is an addr and right is 0, return
    22893     {
    22894       (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    22895       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    22896       (mu-addr-type? %eax)  # => eax
    22897       3d/compare-eax-and 0/imm32/false
    22898       74/jump-if-= break/disp8
    22899       (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    22900       (lookup *eax *(eax+4))  # Var-name Var-name => eax
    22901       (string-equal? %eax "0")  # => eax
    22902       3d/compare-eax-and 0/imm32/false
    22903       74/jump-if-= break/disp8
    22904       eb/jump $check-mu-compare-stmt:end/disp8
    22905     }
    22906     # if left is not number-like, abort
    22907     (check-mu-numberlike-arg %edi *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    22908 $check-mu-compare-stmt:end:
    22909     # . reclaim locals
    22910     81 0/subop/add %esp 0x6c/imm32
    22911     # . restore registers
    22912     5f/pop-to-edi
    22913     5e/pop-to-esi
    22914     5b/pop-to-ebx
    22915     5a/pop-to-edx
    22916     59/pop-to-ecx
    22917     58/pop-to-eax
    22918     # . epilogue
    22919     89/<- %esp 5/r32/ebp
    22920     5d/pop-to-ebp
    22921     c3/return
    22922
    22923 $check-mu-compare-stmt:error-incorrect-inouts:
    22924     (write-buffered *(ebp+0x10) "fn ")
    22925     8b/-> *(ebp+0xc) 0/r32/eax
    22926     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22927     (write-buffered *(ebp+0x10) %eax)
    22928     (write-buffered *(ebp+0x10) ": stmt 'compare' must have two inouts\n")
    22929     (flush *(ebp+0x10))
    22930     (stop *(ebp+0x14) 1)
    22931     # never gets here
    22932
    22933 $check-mu-compare-stmt:error-too-many-outputs:
    22934     (write-buffered *(ebp+0x10) "fn ")
    22935     8b/-> *(ebp+0xc) 0/r32/eax
    22936     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22937     (write-buffered *(ebp+0x10) %eax)
    22938     (write-buffered *(ebp+0x10) ": stmt 'compare' must not have any outputs\n")
    22939     (flush *(ebp+0x10))
    22940     (stop *(ebp+0x14) 1)
    22941     # never gets here
    22942
    22943 $check-mu-compare-stmt:error-both-in-memory:
    22944     (write-buffered *(ebp+0x10) "fn ")
    22945     8b/-> *(ebp+0xc) 0/r32/eax
    22946     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22947     (write-buffered *(ebp+0x10) %eax)
    22948     (write-buffered *(ebp+0x10) ": stmt compare: both inouts are in memory\n")
    22949     (flush *(ebp+0x10))
    22950     (stop *(ebp+0x14) 1)
    22951     # never gets here
    22952
    22953 $check-mu-compare-stmt:error-left-too-large:
    22954     (write-buffered *(ebp+0x10) "fn ")
    22955     8b/-> *(ebp+0xc) 0/r32/eax
    22956     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22957     (write-buffered *(ebp+0x10) %eax)
    22958     (write-buffered *(ebp+0x10) ": stmt compare: '")
    22959     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    22960     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    22961     (write-buffered *(ebp+0x10) %eax)
    22962     (write-buffered *(ebp+0x10) "' is too large to compare\n")
    22963     (flush *(ebp+0x10))
    22964     (stop *(ebp+0x14) 1)
    22965     # never gets here
    22966
    22967 $check-mu-compare-stmt:error-right-too-large:
    22968     (write-buffered *(ebp+0x10) "fn ")
    22969     8b/-> *(ebp+0xc) 0/r32/eax
    22970     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22971     (write-buffered *(ebp+0x10) %eax)
    22972     (write-buffered *(ebp+0x10) ": stmt compare: '")
    22973     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    22974     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    22975     (write-buffered *(ebp+0x10) %eax)
    22976     (write-buffered *(ebp+0x10) "' is too large to compare\n")
    22977     (flush *(ebp+0x10))
    22978     (stop *(ebp+0x14) 1)
    22979     # never gets here
    22980
    22981 $check-mu-compare-stmt:error-right-string-literal:
    22982     (write-buffered *(ebp+0x10) "fn ")
    22983     8b/-> *(ebp+0xc) 0/r32/eax
    22984     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    22985     (write-buffered *(ebp+0x10) %eax)
    22986     (write-buffered *(ebp+0x10) ": stmt compare: string literal ")
    22987     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    22988     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    22989     (write-buffered *(ebp+0x10) %eax)
    22990     (write-buffered *(ebp+0x10) " is not supported; use the string-equal? function\n")
    22991     (flush *(ebp+0x10))
    22992     (stop *(ebp+0x14) 1)
    22993     # never gets here
    22994
    22995 check-mu-address-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    22996     # . prologue
    22997     55/push-ebp
    22998     89/<- %ebp 4/r32/esp
    22999     # . save registers
    23000     50/push-eax
    23001     51/push-ecx
    23002     52/push-edx
    23003     56/push-esi
    23004     57/push-edi
    23005 $check-mu-address-stmt:get-output:
    23006     # esi = stmt
    23007     8b/-> *(ebp+8) 6/r32/esi
    23008     # var output/edi: (addr stmt-var) = stmt->outputs
    23009     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    23010     89/<- %edi 0/r32/eax
    23011     # zero outputs
    23012     3d/compare-eax-and 0/imm32
    23013     0f 84/jump-if-= $check-mu-address-stmt:error-no-output/disp32
    23014     # > 1 output
    23015     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
    23016     3d/compare-eax-and 0/imm32
    23017     0f 85/jump-if-!= $check-mu-address-stmt:error-too-many-outputs/disp32
    23018 $check-mu-address-stmt:get-inout:
    23019     # var inout/esi: (addr stmt-var) = stmt->inouts
    23020     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    23021     89/<- %esi 0/r32/eax
    23022     # zero inouts
    23023     3d/compare-eax-and 0/imm32
    23024     0f 84/jump-if-= $check-mu-address-stmt:error-no-inout/disp32
    23025     # > 1 inout
    23026     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
    23027     3d/compare-eax-and 0/imm32
    23028     0f 85/jump-if-!= $check-mu-address-stmt:error-too-many-inouts/disp32
    23029 $check-mu-address-stmt:types:
    23030     # if output not in register, abort
    23031     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    23032     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    23033     3d/compare-eax-and 0/imm32
    23034     0f 84/jump-if-= $check-mu-address-stmt:error-output-not-in-register/disp32
    23035     # var output-type/edx: (addr type-tree) = output->value->type
    23036     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    23037     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    23038     89/<- %edx 0/r32/eax
    23039     # if output-type not an addr, abort
    23040     (mu-addr-type? %edx)  # => eax
    23041     3d/compare-eax-and 0/imm32/false
    23042     0f 84/jump-if-= $check-mu-address-stmt:error-output-not-address/disp32
    23043     # output-type = output-type->right
    23044     (lookup *(edx+0xc) *(edx+0x10))  # Type-tree-right Type-tree-right => eax
    23045     # if output-type->right is null, output-type = output-type->left
    23046     81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
    23047     {
    23048       75/jump-if-!= break/disp8
    23049       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    23050     }
    23051     89/<- %edx 0/r32/eax
    23052     # var inout-type/ecx: (addr type-tree) = inout->value->type
    23053     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    23054     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    23055     89/<- %ecx 0/r32/eax
    23056     # if (inout->is-deref?) inout-type = inout-type->payload
    23057     8b/-> *(esi+0x10) 0/r32/eax  # Stmt-var-is-deref
    23058     3d/compare-eax-and 0/imm32/false
    23059     {
    23060       74/jump-if-= break/disp8
    23061       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
    23062       # if inout-type->right is null, t = inout-type->left
    23063       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
    23064       {
    23065         75/jump-if-!= break/disp8
    23066         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    23067       }
    23068       89/<- %ecx 0/r32/eax
    23069     }
    23070     # if (inout-type != output-type) abort
    23071     (type-equal-ignoring-capacity? %edx %ecx)  # => eax
    23072     3d/compare-eax-and 0/imm32
    23073     0f 84/jump-if-= $check-mu-address-stmt:error-type-mismatch/disp32
    23074 $check-mu-address-stmt:end:
    23075     # . restore registers
    23076     5f/pop-to-edi
    23077     5e/pop-to-esi
    23078     5a/pop-to-edx
    23079     59/pop-to-ecx
    23080     58/pop-to-eax
    23081     # . epilogue
    23082     89/<- %esp 5/r32/ebp
    23083     5d/pop-to-ebp
    23084     c3/return
    23085
    23086 $check-mu-address-stmt:error-no-inout:
    23087     (write-buffered *(ebp+0x10) "fn ")
    23088     8b/-> *(ebp+0xc) 0/r32/eax
    23089     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    23090     (write-buffered *(ebp+0x10) %eax)
    23091     (write-buffered *(ebp+0x10) ": stmt 'address' expects an inout\n")
    23092     (flush *(ebp+0x10))
    23093     (stop *(ebp+0x14) 1)
    23094     # never gets here
    23095
    23096 $check-mu-address-stmt:error-too-many-inouts:
    23097     (write-buffered *(ebp+0x10) "fn ")
    23098     8b/-> *(ebp+0xc) 0/r32/eax
    23099     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    23100     (write-buffered *(ebp+0x10) %eax)
    23101     (write-buffered *(ebp+0x10) ": stmt 'address' must have just one inout\n")
    23102     (flush *(ebp+0x10))
    23103     (stop *(ebp+0x14) 1)
    23104     # never gets here
    23105
    23106 $check-mu-address-stmt:error-no-output:
    23107     (write-buffered *(ebp+0x10) "fn ")
    23108     8b/-> *(ebp+0xc) 0/r32/eax
    23109     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    23110     (write-buffered *(ebp+0x10) %eax)
    23111     (write-buffered *(ebp+0x10) ": stmt 'address' expects an output\n")
    23112     (flush *(ebp+0x10))
    23113     (stop *(ebp+0x14) 1)
    23114     # never gets here
    23115
    23116 $check-mu-address-stmt:error-output-not-in-register:
    23117     (write-buffered *(ebp+0x10) "fn ")
    23118     8b/-> *(ebp+0xc) 0/r32/eax
    23119     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    23120     (write-buffered *(ebp+0x10) %eax)
    23121     (write-buffered *(ebp+0x10) ": stmt address: output '")
    23122     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    23123     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    23124     (write-buffered *(ebp+0x10) %eax)
    23125     (write-buffered *(ebp+0x10) "' not in a register\n")
    23126     (flush *(ebp+0x10))
    23127     (stop *(ebp+0x14) 1)
    23128     # never gets here
    23129
    23130 $check-mu-address-stmt:error-too-many-outputs:
    23131     (write-buffered *(ebp+0x10) "fn ")
    23132     8b/-> *(ebp+0xc) 0/r32/eax
    23133     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    23134     (write-buffered *(ebp+0x10) %eax)
    23135     (write-buffered *(ebp+0x10) ": stmt 'address' must have just one output\n")
    23136     (flush *(ebp+0x10))
    23137     (stop *(ebp+0x14) 1)
    23138     # never gets here
    23139
    23140 $check-mu-address-stmt:error-output-not-address:
    23141     (write-buffered *(ebp+0x10) "fn ")
    23142     8b/-> *(ebp+0xc) 0/r32/eax
    23143     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    23144     (write-buffered *(ebp+0x10) %eax)
    23145     (write-buffered *(ebp+0x10) ": stmt address: output '")
    23146     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    23147     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    23148     (write-buffered *(ebp+0x10) %eax)
    23149     (write-buffered *(ebp+0x10) "' is not an addr\n")
    23150     (flush *(ebp+0x10))
    23151     (stop *(ebp+0x14) 1)
    23152     # never gets here
    23153
    23154 $check-mu-address-stmt:error-type-mismatch:
    23155     (write-buffered *(ebp+0x10) "fn ")
    23156     8b/-> *(ebp+0xc) 0/r32/eax
    23157     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    23158     (write-buffered *(ebp+0x10) %eax)
    23159     (write-buffered *(ebp+0x10) ": stmt address: output '")
    23160     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    23161     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    23162     (write-buffered *(ebp+0x10) %eax)
    23163     (write-buffered *(ebp+0x10) "' cannot hold address of '")
    23164     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    23165     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    23166     (write-buffered *(ebp+0x10) %eax)
    23167     (write-buffered *(ebp+0x10) "'\n")
    23168     (flush *(ebp+0x10))
    23169     (stop *(ebp+0x14) 1)
    23170     # never gets here
    23171
    23172 type-equal-ignoring-capacity?:  # a: (addr type-tree), b: (addr type-tree) -> result/eax: boolean
    23173     # . prologue
    23174     55/push-ebp
    23175     89/<- %ebp 4/r32/esp
    23176     # . save registers
    23177     51/push-ecx
    23178     52/push-edx
    23179     53/push-ebx
    23180     # var curr-a/ecx: (addr type-tree) = a
    23181     8b/-> *(ebp+8) 1/r32/ecx
    23182     # var curr-b/ebx: (addr type-tree) = b
    23183     8b/-> *(ebp+0xc) 3/r32/ebx
    23184     # if (curr-a->is-atom?) fall back to regular equality
    23185     81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
    23186     0f 85/jump-if-!= $type-equal-ignoring-capacity?:base-case/disp32
    23187     # if (curr-a->left != curr-b->left) return false
    23188     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
    23189     89/<- %edx 0/r32/eax
    23190     (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
    23191     (type-equal? %edx %eax)  # => eax
    23192     3d/compare-eax-and 0/imm32/false
    23193     0f 84/jump-if-= $type-equal-ignoring-capacity?:end/disp32  # eax switches meaning
    23194     # if (curr-a->left == "array") curr-a = curr-a->element-type
    23195     {
    23196       (mu-array? %edx)  # => eax
    23197       3d/compare-eax-and 0/imm32/false
    23198       75/jump-if-!= break/disp8
    23199 $type-equal-ignoring-capacity?:array:
    23200       # curr-a = curr-a->right->left
    23201       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
    23202       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    23203       89/<- %ecx 0/r32/eax
    23204       # curr-b = curr-b->right->left
    23205       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
    23206       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    23207       89/<- %ebx 0/r32/eax
    23208       eb/jump $type-equal-ignoring-capacity?:base-case/disp8
    23209     }
    23210     # if (curr-a->left == "stream") curr-a = curr-a->element-type
    23211     {
    23212       (mu-stream? %edx)  # => eax
    23213       3d/compare-eax-and 0/imm32/false
    23214       75/jump-if-!= break/disp8
    23215 $type-equal-ignoring-capacity?:stream:
    23216       # curr-a = curr-a->right->left
    23217       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
    23218       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    23219       89/<- %ecx 0/r32/eax
    23220       # curr-b = curr-b->right->left
    23221       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
    23222       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    23223       89/<- %ebx 0/r32/eax
    23224       eb/jump $type-equal-ignoring-capacity?:base-case/disp8
    23225     }
    23226 $type-equal-ignoring-capacity?:base-case:
    23227     # return type-equal?(curr-a, curr-b)
    23228     (type-equal? %ecx %ebx)  # => eax
    23229 $type-equal-ignoring-capacity?:end:
    23230     # . restore registers
    23231     5b/pop-to-ebx
    23232     5a/pop-to-edx
    23233     59/pop-to-ecx
    23234     # . epilogue
    23235     89/<- %esp 5/r32/ebp
    23236     5d/pop-to-ebp
    23237     c3/return
    23238
    23239 check-mu-return-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    23240     # . prologue
    23241     55/push-ebp
    23242     89/<- %ebp 4/r32/esp
    23243     # . save registers
    23244     50/push-eax
    23245     51/push-ecx
    23246     52/push-edx
    23247     53/push-ebx
    23248     56/push-esi
    23249     57/push-edi
    23250     # var type-parameters/edx: (addr table (handle array byte) (addr type-tree) 8)
    23251     81 5/subop/subtract %esp 0x60/imm32
    23252     68/push 0x60/imm32/size
    23253     68/push 0/imm32/read
    23254     68/push 0/imm32/write
    23255     89/<- %edx 4/r32/esp
    23256     # var template/esi: (addr list var) = fn->outputs
    23257     8b/-> *(ebp+0xc) 0/r32/eax
    23258     (lookup *(eax+0x10) *(eax+0x14))  # Function-outputs Function-outputs => eax
    23259     89/<- %esi 0/r32/eax
    23260     # var curr-template/ebx: (addr list var) = fn->outputs
    23261     89/<- %ebx 0/r32/eax
    23262     # var curr/edi: (addr stmt-var) = stmt->inouts
    23263     8b/-> *(ebp+8) 0/r32/eax
    23264     (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    23265     89/<- %edi 0/r32/eax
    23266     {
    23267       # if template is null, break
    23268       81 7/subop/compare %ebx 0/imm32
    23269       0f 84/jump-if-= break/disp32
    23270       # if curr is null, abort
    23271       81 7/subop/compare %edi 0/imm32
    23272       0f 84/jump-if-= $check-mu-return-stmt:error-too-few-inouts/disp32
    23273       # var template-type/ecx: (addr type-tree) = template->value->type
    23274       (lookup *ebx *(ebx+4))  # List-value List-value => eax
    23275       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    23276       89/<- %ecx 0/r32/eax
    23277       # var curr-type/eax: (addr type-tree) = curr->value->type
    23278       (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    23279       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    23280       # if (curr->is-deref?) curr-type = payload of curr-type
    23281       81 7/subop/compare *(edi+0x10) 0/imm32/false  # Stmt-var-is-deref
    23282       {
    23283         74/jump-if-= break/disp8
    23284         (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
    23285         # if t->right is null, t = t->left
    23286         81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
    23287         75/jump-if-!= break/disp8
    23288         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    23289       }
    23290       # if curr-type is literal and template-type is float, abort
    23291       50/push-eax
    23292       {
    23293         (simple-mu-type? %eax 0)  # literal => eax
    23294         3d/compare-eax-and 0/imm32/false
    23295         74/jump-if-= break/disp8
    23296         (simple-mu-type? %ecx 0xf)  # float => eax
    23297         3d/compare-eax-and 0/imm32/false
    23298         0f 85/jump-if-!= $check-mu-return-stmt:error-literal-to-float/disp32
    23299       }
    23300       58/pop-to-eax
    23301       # if (curr-type != template-type) abort
    23302       (type-match? %ecx %eax %edx)  # => eax
    23303       3d/compare-eax-and 0/imm32/false
    23304       0f 84/jump-if-= $check-mu-return-stmt:error1/disp32
    23305       # if register-within-list-with-conflict?(curr, original template, curr-template, stmt) abort
    23306       (register-within-list-with-conflict? %edi %esi %ebx *(ebp+8))  # => eax
    23307       3d/compare-eax-and 0/imm32/false
    23308       0f 85/jump-if-!= $check-mu-return-stmt:error2/disp32
    23309       # template = template->next
    23310       (lookup *(ebx+8) *(ebx+0xc))  # List-next List-next => eax
    23311       89/<- %ebx 0/r32/eax
    23312       # curr = curr->next
    23313       (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
    23314       89/<- %edi 0/r32/eax
    23315       #
    23316       e9/jump loop/disp32
    23317     }
    23318     # if curr is not null, abort
    23319     81 7/subop/compare %edi 0/imm32
    23320     0f 85/jump-if-!= $check-mu-return-stmt:error-too-many-inouts/disp32
    23321 $check-mu-return-stmt:end:
    23322     # . reclaim locals
    23323     81 0/subop/add %esp 0x6c/imm32
    23324     # . restore registers
    23325     5f/pop-to-edi
    23326     5e/pop-to-esi
    23327     5b/pop-to-ebx
    23328     5a/pop-to-edx
    23329     59/pop-to-ecx
    23330     58/pop-to-eax
    23331     # . epilogue
    23332     89/<- %esp 5/r32/ebp
    23333     5d/pop-to-ebp
    23334     c3/return
    23335
    23336 $check-mu-return-stmt:error1:
    23337     (write-buffered *(ebp+0x10) "fn ")
    23338     8b/-> *(ebp+0xc) 0/r32/eax
    23339     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    23340     (write-buffered *(ebp+0x10) %eax)
    23341     (write-buffered *(ebp+0x10) ": return: '")
    23342     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    23343     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    23344     (write-buffered *(ebp+0x10) %eax)
    23345     (write-buffered *(ebp+0x10) "' has the wrong type\n")
    23346     (flush *(ebp+0x10))
    23347     (stop *(ebp+0x14) 1)
    23348     # never gets here
    23349
    23350 $check-mu-return-stmt:error2:
    23351     (write-buffered *(ebp+0x10) "fn ")
    23352     8b/-> *(ebp+0xc) 0/r32/eax
    23353     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    23354     (write-buffered *(ebp+0x10) %eax)
    23355     (write-buffered *(ebp+0x10) ": return: '")
    23356     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    23357     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    23358     (write-buffered *(ebp+0x10) %eax)
    23359     (write-buffered *(ebp+0x10) "' is no longer available\n")
    23360     (flush *(ebp+0x10))
    23361     (stop *(ebp+0x14) 1)
    23362     # never gets here
    23363
    23364 $check-mu-return-stmt:error-literal-to-float:
    23365     (write-buffered *(ebp+0x10) "fn ")
    23366     8b/-> *(ebp+0xc) 0/r32/eax
    23367     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    23368     (write-buffered *(ebp+0x10) %eax)
    23369     (write-buffered *(ebp+0x10) ": return: cannot copy literal '")
    23370     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    23371     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    23372     (write-buffered *(ebp+0x10) %eax)
    23373     (write-buffered *(ebp+0x10) "' to float\n")
    23374     (flush *(ebp+0x10))
    23375     (stop *(ebp+0x14) 1)
    23376     # never gets here
    23377
    23378 $check-mu-return-stmt:error-too-few-inouts:
    23379     (write-buffered *(ebp+0x10) "fn ")
    23380     8b/-> *(ebp+0xc) 0/r32/eax
    23381     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    23382     (write-buffered *(ebp+0x10) %eax)
    23383     (write-buffered *(ebp+0x10) ": return: too few inouts\n")
    23384     (flush *(ebp+0x10))
    23385     (stop *(ebp+0x14) 1)
    23386     # never gets here
    23387
    23388 $check-mu-return-stmt:error-too-many-inouts:
    23389     (write-buffered *(ebp+0x10) "fn ")
    23390     8b/-> *(ebp+0xc) 0/r32/eax
    23391     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    23392     (write-buffered *(ebp+0x10) %eax)
    23393     (write-buffered *(ebp+0x10) ": return: too many inouts\n")
    23394     (flush *(ebp+0x10))
    23395     (stop *(ebp+0x14) 1)
    23396     # never gets here
    23397
    23398 check-all-unique-registers:  # outputs: (addr list var), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    23399     # . prologue
    23400     55/push-ebp
    23401     89/<- %ebp 4/r32/esp
    23402     # . save registers
    23403     50/push-eax
    23404     51/push-ecx
    23405     56/push-esi
    23406     # var table/esi: (addr table (handle array byte) int 8)
    23407     81 5/subop/subtract %esp 0x60/imm32
    23408     68/push 0x60/imm32/size
    23409     68/push 0/imm32/read
    23410     68/push 0/imm32/write
    23411     89/<- %esi 4/r32/esp
    23412     # var curr/ecx: (addr list var) = outputs
    23413     8b/-> *(ebp+8) 1/r32/ecx
    23414     {
    23415       # if (curr == 0) break
    23416       81 7/subop/compare %ecx 0/imm32
    23417       0f 84/jump-if-= break/disp32
    23418       # var reg/eax: (addr array byte) = curr->value->register  # guaranteed to exist
    23419       (lookup *ecx *(ecx+4))  # List-value List-value => eax
    23420       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    23421       # if reg exists in table, abort
    23422       (maybe-get %esi %eax 0xc)  # => eax
    23423       3d/compare-eax-and 0/imm32
    23424       0f 85/jump-if-!= $check-all-unique-registers:abort/disp32
    23425       # insert reg in table
    23426       (lookup *ecx *(ecx+4))  # List-value List-value => eax
    23427       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    23428       (get-or-insert %esi %eax 0xc Heap)
    23429       # curr = curr->next
    23430       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
    23431       89/<- %ecx 0/r32/eax
    23432       e9/jump loop/disp32
    23433     }
    23434 $check-all-unique-registers:end:
    23435     # . reclaim locals
    23436     81 0/subop/add %esp 0x6c/imm32
    23437     # . restore registers
    23438     5e/pop-to-esi
    23439     59/pop-to-ecx
    23440     58/pop-to-eax
    23441     # . epilogue
    23442     89/<- %esp 5/r32/ebp
    23443     5d/pop-to-ebp
    23444     c3/return
    23445
    23446 $check-all-unique-registers:abort:
    23447     (write-buffered *(ebp+0x10) "fn ")
    23448     8b/-> *(ebp+0xc) 0/r32/eax
    23449     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    23450     (write-buffered *(ebp+0x10) %eax)
    23451     (write-buffered *(ebp+0x10) ": outputs must be in unique registers\n")
    23452     (flush *(ebp+0x10))
    23453     (stop *(ebp+0x14) 1)
    23454     # never gets here
    23455
    23456 # return false if s's register is not between start (inclusive) and end (exclusive)
    23457 # return false if the positionally corresponding register in stmt->inouts (where s comes from) is also s's register
    23458 # otherwise return true
    23459 register-within-list-with-conflict?:  # s: (addr stmt-var), start: (addr list var), end: (addr list var), stmt: (addr stmt) -> result/eax: boolean
    23460     # . prologue
    23461     55/push-ebp
    23462     89/<- %ebp 4/r32/esp
    23463     # . save registers
    23464     51/push-ecx
    23465     52/push-edx
    23466     53/push-ebx
    23467     56/push-esi
    23468     57/push-edi
    23469     # var target/ebx: (addr array byte) = s->value->register
    23470     8b/-> *(ebp+8) 0/r32/eax
    23471     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    23472     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    23473 #?     (write-buffered Stderr "AA: ")
    23474 #?     (write-buffered Stderr %eax)
    23475 #?     (write-buffered Stderr Newline)
    23476 #?     (flush Stderr)
    23477     # if (var->register == 0) return false
    23478     3d/compare-eax-and 0/imm32
    23479     0f 84/jump-if-= $register-within-list-with-conflict?:end/disp32  # eax turns into result
    23480     89/<- %ebx 0/r32/eax
    23481     # var curr/ecx: (addr list var) = start
    23482     8b/-> *(ebp+0xc) 1/r32/ecx
    23483     # edx = end
    23484     8b/-> *(ebp+0x10) 2/r32/edx
    23485     {
    23486       # if (curr == 0) break
    23487       81 7/subop/compare %edi 0/imm32
    23488       0f 84/jump-if-= break/disp32
    23489       # if (curr == end) break
    23490       39/compare %ecx 2/r32/edx
    23491       0f 84/jump-if-= break/disp32
    23492       # var curr-reg/eax: (addr array byte) = curr->value->register
    23493       (lookup *ecx *(ecx+4))  # List-value List-value => eax
    23494       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    23495       # if (curr-reg == 0) continue
    23496       3d/compare-eax-and 0/imm32
    23497       74/jump-if-= $register-within-list-with-conflict?:continue/disp8
    23498       # if (curr-reg == target) check for conflict
    23499       (string-equal? %eax %ebx)  # => eax
    23500       3d/compare-eax-and 0/imm32/false
    23501       {
    23502         74/jump-if-= break/disp8
    23503 #?         (write-buffered Stderr "conflict?\n")
    23504 #?         (flush Stderr)
    23505         # var return-inouts/eax: (addr stmt-var) = stmt->inouts
    23506         8b/-> *(ebp+0x14) 0/r32/eax
    23507         (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    23508         (register-conflict? %ebx %eax *(ebp+0xc))  # => eax
    23509         eb/jump $register-within-list-with-conflict?:end/disp8
    23510       }
    23511 $register-within-list-with-conflict?:continue:
    23512       # curr = curr->next
    23513       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
    23514       89/<- %ecx 0/r32/eax
    23515       e9/jump loop/disp32
    23516     }
    23517     # return false
    23518     b8/copy-to-eax 0/imm32/false
    23519 $register-within-list-with-conflict?:end:
    23520     # . restore registers
    23521     5f/pop-to-edi
    23522     5e/pop-to-esi
    23523     5b/pop-to-ebx
    23524     5a/pop-to-edx
    23525     59/pop-to-ecx
    23526     # . epilogue
    23527     89/<- %esp 5/r32/ebp
    23528     5d/pop-to-ebp
    23529     c3/return
    23530
    23531 # At the first occurrence of register 'reg' in fn-outputs,
    23532 # check if the corresponding element of return-inouts has a different register.
    23533 # This hacky helper is intended to be called in one specific place. Don't
    23534 # reuse it as is.
    23535 register-conflict?:  # reg: (addr array byte), return-inouts: (addr stmt-var), fn-outputs: (addr list var) => result/eax: boolean
    23536     # . prologue
    23537     55/push-ebp
    23538     89/<- %ebp 4/r32/esp
    23539     # . save registers
    23540     51/push-ecx
    23541     52/push-edx
    23542     53/push-ebx
    23543     56/push-esi
    23544     57/push-edi
    23545 #?     (write-buffered Stderr "BB: ")
    23546 #?     (write-buffered Stderr *(ebp+8))
    23547 #?     (write-buffered Stderr Newline)
    23548 #?     (flush Stderr)
    23549     # var curr-output/edi: (addr list var) = fn-outputs
    23550     8b/-> *(ebp+0x10) 7/r32/edi
    23551     # var curr-inout/esi: (addr stmt-var) = return-inouts
    23552     8b/-> *(ebp+0xc) 6/r32/esi
    23553     {
    23554       # if (curr-output == 0) abort
    23555       81 7/subop/compare %edi 0/imm32
    23556       0f 84/jump-if-= break/disp32
    23557       # if (curr-output->value->register != reg) continue
    23558       (lookup *edi *(edi+4))  # List-value List-value => eax
    23559       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    23560       (string-equal? %eax *(ebp+8))  # => eax
    23561       3d/compare-eax-and 0/imm32/false
    23562       0f 84/jump-if= $register-conflict?:continue/disp32
    23563 #?       (write-buffered Stderr "rescan\n")
    23564 #?       (flush Stderr)
    23565       # var curr-reg/eax: (addr array byte) = curr-inout->value->register
    23566       (lookup *esi *(esi+4))  # List-value List-value => eax
    23567       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    23568       # if (curr-reg == 0) return true
    23569       3d/compare-eax-and 0/imm32
    23570       {
    23571         75/jump-if-!= break/disp8
    23572 #?         (write-buffered Stderr "no register\n")
    23573 #?         (flush Stderr)
    23574         b8/copy-to-eax 1/imm32/true
    23575         e9/jump $register-conflict?:end/disp32
    23576       }
    23577       # return (curr-reg != reg)
    23578       (string-equal? %eax *(ebp+8))  # => eax
    23579       3d/compare-eax-and 0/imm32/false
    23580       0f 94/set-if-= %al
    23581 #?       (write-buffered Stderr "final: ")
    23582 #?       (write-int32-hex-buffered Stderr %eax)
    23583 #?       (write-buffered Stderr Newline)
    23584 #?       (flush Stderr)
    23585       eb/jump $register-conflict?:end/disp8
    23586 $register-conflict?:continue:
    23587       # curr-output = curr-output->next
    23588       (lookup *(edi+8) *(edi+0xc))  # List-next List-next => eax
    23589       89/<- %edi 0/r32/eax
    23590       # curr-inout = curr-inout->next
    23591       (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
    23592       89/<- %esi 0/r32/eax
    23593       e9/jump loop/disp32
    23594     }
    23595     # should never get here
    23596     (write-buffered Stderr "register-conflict? misused\n")
    23597     (flush Stderr)
    23598     e8/call syscall_exit/disp32
    23599 $register-conflict?:end:
    23600     # . restore registers
    23601     5f/pop-to-edi
    23602     5e/pop-to-esi
    23603     5b/pop-to-ebx
    23604     5a/pop-to-edx
    23605     59/pop-to-ecx
    23606     # . epilogue
    23607     89/<- %esp 5/r32/ebp
    23608     5d/pop-to-ebp
    23609     c3/return
    23610
    23611 check-final-stmt-is-return:  # block: (addr block), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    23612     # . prologue
    23613     55/push-ebp
    23614     89/<- %ebp 4/r32/esp
    23615     # . save registers
    23616     50/push-eax
    23617     51/push-ecx
    23618     # var curr/ecx: (addr list stmt) = block->stmts
    23619     8b/-> *(ebp+8) 0/r32/eax
    23620     (lookup *(eax+4) *(eax+8))  # Block-stmts Block-stmts => eax
    23621     3d/compare-eax-and 0/imm32
    23622     74/jump-if-= $check-final-stmt-is-return:error/disp8
    23623     89/<- %ecx 0/r32/eax
    23624     {
    23625       # if curr->next == 0, break
    23626       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
    23627       3d/compare-eax-and 0/imm32
    23628       74/jump-if-= break/disp8
    23629       # curr = curr->next
    23630       89/<- %ecx 0/r32/eax
    23631       e9/jump loop/disp32
    23632     }
    23633 $check-final-stmt-is-return:check-tag:
    23634     # if curr->value->tag != Stmt1, abort
    23635     (lookup *ecx *(ecx+4))  # List-value List-value => eax
    23636     81 7/subop/compare *eax 1/imm32/stmt1  # Stmt-tag
    23637     75/jump-if-!= $check-final-stmt-is-return:error/disp8
    23638 $check-final-stmt-is-return:check-operation:
    23639     # if curr->operation != "return", abort
    23640     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
    23641     (string-equal? %eax "return")
    23642     3d/compare-eax-and 0/imm32/false
    23643     74/jump-if-= $check-final-stmt-is-return:error/disp8
    23644 $check-final-stmt-is-return:end:
    23645     # . restore registers
    23646     59/pop-to-ecx
    23647     58/pop-to-eax
    23648     # . epilogue
    23649     89/<- %esp 5/r32/ebp
    23650     5d/pop-to-ebp
    23651     c3/return
    23652
    23653 $check-final-stmt-is-return:error:
    23654     (write-buffered *(ebp+0x10) "fn ")
    23655     8b/-> *(ebp+0xc) 0/r32/eax
    23656     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    23657     (write-buffered *(ebp+0x10) %eax)
    23658     (write-buffered *(ebp+0x10) ": final statement should be a 'return'\n")
    23659     (flush *(ebp+0x10))
    23660     (stop *(ebp+0x14) 1)
    23661     # never gets here
    23662
    23663 check-no-breaks:  # block: (addr block), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    23664     # . prologue
    23665     55/push-ebp
    23666     89/<- %ebp 4/r32/esp
    23667     # . save registers
    23668     50/push-eax
    23669     51/push-ecx
    23670     # var curr/ecx: (addr list stmt) = block->stmts
    23671     8b/-> *(ebp+8) 0/r32/eax
    23672     (lookup *(eax+4) *(eax+8))  # Block-stmts Block-stmts => eax
    23673     3d/compare-eax-and 0/imm32
    23674     0f 84/jump-if-= $check-no-breaks:end/disp32
    23675     89/<- %ecx 0/r32/eax
    23676     {
    23677       # if curr->next == 0, break
    23678       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
    23679       3d/compare-eax-and 0/imm32
    23680       74/jump-if-= break/disp8
    23681       # if curr->value->tag != Stmt1, continue
    23682       (lookup *ecx *(ecx+4))  # List-value List-value => eax
    23683       81 7/subop/compare *eax 1/imm32/stmt1  # Stmt-tag
    23684       75/jump-if-!= $check-no-breaks:continue/disp8
    23685       # if curr->value->operation starts with "break", abort
    23686       (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
    23687       (string-starts-with? %eax "break")  # => eax
    23688       3d/compare-eax-and 0/imm32/false
    23689       75/jump-if-!= $check-no-breaks:error/disp8
    23690 $check-no-breaks:continue:
    23691       # curr = curr->next
    23692       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
    23693       89/<- %ecx 0/r32/eax
    23694       e9/jump loop/disp32
    23695     }
    23696 $check-no-breaks:end:
    23697     # . restore registers
    23698     59/pop-to-ecx
    23699     58/pop-to-eax
    23700     # . epilogue
    23701     89/<- %esp 5/r32/ebp
    23702     5d/pop-to-ebp
    23703     c3/return
    23704
    23705 $check-no-breaks:error:
    23706     (write-buffered *(ebp+0x10) "fn ")
    23707     8b/-> *(ebp+0xc) 0/r32/eax
    23708     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    23709     (write-buffered *(ebp+0x10) %eax)
    23710     (write-buffered *(ebp+0x10) " has outputs, so you cannot 'break' out of the outermost block. Use 'return'.\n")
    23711     (flush *(ebp+0x10))
    23712     (stop *(ebp+0x14) 1)
    23713     # never gets here
    23714
    23715 check-mu-get-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    23716     # . prologue
    23717     55/push-ebp
    23718     89/<- %ebp 4/r32/esp
    23719     # . save registers
    23720     50/push-eax
    23721     51/push-ecx
    23722     52/push-edx
    23723     53/push-ebx
    23724     56/push-esi
    23725     57/push-edi
    23726     # esi = stmt
    23727     8b/-> *(ebp+8) 6/r32/esi
    23728     # - check for 0 inouts
    23729     # var base/ecx: (addr var) = stmt->inouts->value
    23730     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    23731     3d/compare-eax-and 0/imm32/false
    23732     0f 84/jump-if-= $check-mu-get-stmt:error-too-few-inouts/disp32
    23733     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    23734     89/<- %ecx 0/r32/eax
    23735 $check-mu-get-stmt:check-base:
    23736     # - check base type
    23737     # if it's an 'addr', check that it's in a register
    23738     # var base-type/ebx: (addr type-tree) = lookup(base->type)
    23739     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
    23740     89/<- %ebx 0/r32/eax
    23741     {
    23742       81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
    23743       0f 85/jump-if-!= break/disp32
    23744 $check-mu-get-stmt:base-is-compound:
    23745       # if (type->left != addr) break
    23746       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
    23747       (simple-mu-type? %eax 2)  # addr => eax
    23748       3d/compare-eax-and 0/imm32/false
    23749       74/jump-if-= break/disp8
    23750 $check-mu-get-stmt:base-is-addr:
    23751       # now check for register
    23752       81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
    23753       0f 84/jump-if-= $check-mu-get-stmt:error-base-type-addr-but-not-register/disp32
    23754 $check-mu-get-stmt:base-is-addr-in-register:
    23755       # type->left is now an addr; skip it
    23756       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
    23757       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
    23758       0f 85/jump-if-!= $check-mu-get-stmt:error-bad-base/disp32
    23759 $check-mu-get-stmt:base-is-addr-to-atom-in-register:
    23760       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    23761       89/<- %ebx 0/r32/eax
    23762     }
    23763 $check-mu-get-stmt:check-base-typeinfo:
    23764     # ensure type is a container
    23765     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
    23766     {
    23767       75/jump-if-!= break/disp8
    23768       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
    23769       89/<- %ebx 0/r32/eax
    23770     }
    23771     # var base-type-id/ebx: type-id = base-type->value
    23772     8b/-> *(ebx+4) 3/r32/ebx  # Type-tree-value
    23773     (container? %ebx)  # => eax
    23774     3d/compare-eax-and 0/imm32/false
    23775     0f 84/jump-if-= $check-mu-get-stmt:error-bad-base/disp32
    23776     # var base-typeinfo/edx: (addr typeinfo) = find-typeinfo(base-type-id)
    23777     # . var container/ecx: (handle typeinfo)
    23778     68/push 0/imm32
    23779     68/push 0/imm32
    23780     89/<- %ecx 4/r32/esp
    23781     # .
    23782     (find-typeinfo %ebx %ecx)
    23783     (lookup *ecx *(ecx+4))  # => eax
    23784     # . reclaim container
    23785     81 0/subop/add %esp 8/imm32
    23786     # .
    23787     89/<- %edx 0/r32/eax
    23788     # var offset/ecx: (addr stmt-var) = stmt->inouts->next
    23789     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    23790     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    23791     89/<- %ecx 0/r32/eax
    23792     # - check for 1 inout
    23793     3d/compare-eax-and 0/imm32/false
    23794     0f 84/jump-if-= $check-mu-get-stmt:error-too-few-inouts/disp32
    23795     # var offset/ecx: (addr var) = lookup(offset->value)
    23796     (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
    23797     89/<- %ecx 0/r32/eax
    23798     # - check for valid field
    23799     81 7/subop/compare *(ecx+0x14) -1/imm32/uninitialized  # Var-offset
    23800     0f 84/jump-if-= $check-mu-get-stmt:error-bad-field/disp32
    23801     # - check for too many inouts
    23802     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    23803     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    23804     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    23805     3d/compare-eax-and 0/imm32/false
    23806     0f 85/jump-if-!= $check-mu-get-stmt:error-too-many-inouts/disp32
    23807     # var output/edi: (addr var) = stmt->outputs->value
    23808     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    23809     # - check for 0 outputs
    23810     3d/compare-eax-and 0/imm32/false
    23811     0f 84/jump-if-= $check-mu-get-stmt:error-too-few-outputs/disp32
    23812     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    23813     89/<- %edi 0/r32/eax
    23814 $check-mu-get-stmt:check-output-type:
    23815     # - check output type
    23816     # must be in register
    23817     (lookup *(edi+0x18) *(edi+0x1c))  # Var-register Var-register => eax
    23818     3d/compare-eax-and 0/imm32
    23819     0f 84/jump-if-= $check-mu-get-stmt:error-output-not-in-register/disp32
    23820     # must have a non-atomic type
    23821     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
    23822     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
    23823     0f 85/jump-if-!= $check-mu-get-stmt:error-output-type-not-address/disp32
    23824     # type must start with (addr ...)
    23825     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    23826     (simple-mu-type? %eax 2)  # => eax
    23827     3d/compare-eax-and 0/imm32/false
    23828     0f 84/jump-if-= $check-mu-get-stmt:error-output-type-not-address/disp32
    23829 $check-mu-get-stmt:check-output-type-match:
    23830     # payload of addr type must match 'type' definition
    23831     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
    23832     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
    23833     # if (payload->right == null) payload = payload->left
    23834     81 7/subop/compare *(eax+0xc) 0/imm32/null  # Type-tree-right
    23835     {
    23836       75/jump-if-!= break/disp8
    23837       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    23838     }
    23839     89/<- %edi 0/r32/eax
    23840     # . var output-name/ecx: (addr array byte)
    23841     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    23842     89/<- %ecx 0/r32/eax
    23843     # . var base-typeinfo-entry/eax: (addr handle typeinfo-entry)
    23844     (lookup *(edx+4) *(edx+8))  # Typeinfo-fields Typeinfo-fields => eax
    23845     (get %eax %ecx 0x10)  # => eax
    23846     # .
    23847     (lookup *eax *(eax+4))  # => eax
    23848     (lookup *eax *(eax+4))  # Typeinfo-entry-input-var Typeinfo-entry-input-var => eax
    23849     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    23850     # .
    23851     (type-equal? %edi %eax)  # => eax
    23852     3d/compare-eax-and 0/imm32/false
    23853     0f 84/jump-if-= $check-mu-get-stmt:error-bad-output-type/disp32
    23854     # - check for too many outputs
    23855     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    23856     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    23857     3d/compare-eax-and 0/imm32/false
    23858     0f 85/jump-if-!= $check-mu-get-stmt:error-too-many-outputs/disp32
    23859 $check-mu-get-stmt:end:
    23860     # . restore registers
    23861     5f/pop-to-edi
    23862     5e/pop-to-esi
    23863     5b/pop-to-ebx
    23864     5a/pop-to-edx
    23865     59/pop-to-ecx
    23866     58/pop-to-eax
    23867     # . epilogue
    23868     89/<- %esp 5/r32/ebp
    23869     5d/pop-to-ebp
    23870     c3/return
    23871
    23872 $check-mu-get-stmt:error-too-few-inouts:
    23873     (write-buffered *(ebp+0x10) "fn ")
    23874     8b/-> *(ebp+0xc) 0/r32/eax
    23875     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    23876     (write-buffered *(ebp+0x10) %eax)
    23877     (write-buffered *(ebp+0x10) ": stmt get: too few inouts (2 required)\n")
    23878     (flush *(ebp+0x10))
    23879     (stop *(ebp+0x14) 1)
    23880     # never gets here
    23881
    23882 $check-mu-get-stmt:error-too-many-inouts:
    23883     (write-buffered *(ebp+0x10) "fn ")
    23884     8b/-> *(ebp+0xc) 0/r32/eax
    23885     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    23886     (write-buffered *(ebp+0x10) %eax)
    23887     (write-buffered *(ebp+0x10) ": stmt get: too many inouts (2 required)\n")
    23888     (flush *(ebp+0x10))
    23889     (stop *(ebp+0x14) 1)
    23890     # never gets here
    23891
    23892 $check-mu-get-stmt:error-too-few-outputs:
    23893     (write-buffered *(ebp+0x10) "fn ")
    23894     8b/-> *(ebp+0xc) 0/r32/eax
    23895     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    23896     (write-buffered *(ebp+0x10) %eax)
    23897     (write-buffered *(ebp+0x10) ": stmt get: must have an output\n")
    23898     (flush *(ebp+0x10))
    23899     (stop *(ebp+0x14) 1)
    23900     # never gets here
    23901
    23902 $check-mu-get-stmt:error-too-many-outputs:
    23903     (write-buffered *(ebp+0x10) "fn ")
    23904     8b/-> *(ebp+0xc) 0/r32/eax
    23905     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    23906     (write-buffered *(ebp+0x10) %eax)
    23907     (write-buffered *(ebp+0x10) ": stmt get: too many outputs (1 required)\n")
    23908     (flush *(ebp+0x10))
    23909     (stop *(ebp+0x14) 1)
    23910     # never gets here
    23911
    23912 $check-mu-get-stmt:error-bad-base:
    23913     # error("fn " fn ": stmt get: var '" base->name "' must have a 'type' definition\n")
    23914     (write-buffered *(ebp+0x10) "fn ")
    23915     8b/-> *(ebp+0xc) 0/r32/eax
    23916     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    23917     (write-buffered *(ebp+0x10) %eax)
    23918     (write-buffered *(ebp+0x10) ": stmt get: var '")
    23919     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    23920     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    23921     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    23922     (write-buffered *(ebp+0x10) %eax)
    23923     (write-buffered *(ebp+0x10) "' must have a 'type' definition\n")
    23924     (flush *(ebp+0x10))
    23925     (stop *(ebp+0x14) 1)
    23926     # never gets here
    23927
    23928 $check-mu-get-stmt:error-base-type-addr-but-not-register:
    23929     (write-buffered *(ebp+0x10) "fn ")
    23930     8b/-> *(ebp+0xc) 0/r32/eax
    23931     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    23932     (write-buffered *(ebp+0x10) %eax)
    23933     (write-buffered *(ebp+0x10) ": stmt get: var '")
    23934     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    23935     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    23936     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    23937     (write-buffered *(ebp+0x10) %eax)
    23938     (write-buffered *(ebp+0x10) "' is an 'addr' type, and so must live in a register\n")
    23939     (flush *(ebp+0x10))
    23940     (stop *(ebp+0x14) 1)
    23941     # never gets here
    23942
    23943 $check-mu-get-stmt:error-bad-field:
    23944     # error("fn " fn ": stmt get: type " type " has no member called '" curr->name "'\n")
    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: type '")
    23950     # . write(Type-id->data[tmp])
    23951     bf/copy-to-edi Type-id/imm32
    23952     8b/-> *(edi+ebx<<2+0xc) 6/r32/esi
    23953     {
    23954       81 7/subop/compare %esi 0/imm32
    23955       74/jump-if-= break/disp8
    23956       (write-buffered *(ebp+0x10) %esi)
    23957     }
    23958     # .
    23959     (write-buffered *(ebp+0x10) "' has no member called '")
    23960     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    23961     (write-buffered *(ebp+0x10) %eax)
    23962     (write-buffered *(ebp+0x10) "'\n")
    23963     (flush *(ebp+0x10))
    23964     (stop *(ebp+0x14) 1)
    23965     # never gets here
    23966
    23967 $check-mu-get-stmt:error-output-not-in-register:
    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: output '")
    23973     (lookup *edi *(edi+4))  # Var-name Var-name => eax
    23974     (write-buffered *(ebp+0x10) %eax)
    23975     (write-buffered *(ebp+0x10) "' is not in a register\n")
    23976     (flush *(ebp+0x10))
    23977     (stop *(ebp+0x14) 1)
    23978     # never gets here
    23979
    23980 $check-mu-get-stmt:error-output-type-not-address:
    23981     (write-buffered *(ebp+0x10) "fn ")
    23982     8b/-> *(ebp+0xc) 0/r32/eax
    23983     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    23984     (write-buffered *(ebp+0x10) %eax)
    23985     (write-buffered *(ebp+0x10) ": stmt get: output must be an addr\n")
    23986     (flush *(ebp+0x10))
    23987     (stop *(ebp+0x14) 1)
    23988     # never gets here
    23989
    23990 $check-mu-get-stmt:error-bad-output-type:
    23991     (write-buffered *(ebp+0x10) "fn ")
    23992     8b/-> *(ebp+0xc) 0/r32/eax
    23993     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    23994     (write-buffered *(ebp+0x10) %eax)
    23995     (write-buffered *(ebp+0x10) ": stmt get: wrong output type for member '")
    23996     (write-buffered *(ebp+0x10) %ecx)
    23997     (write-buffered *(ebp+0x10) "' of type '")
    23998     bf/copy-to-edi Type-id/imm32
    23999     8b/-> *(edi+ebx<<2+0xc) 6/r32/esi
    24000     {
    24001       81 7/subop/compare %esi 0/imm32
    24002       74/jump-if-= break/disp8
    24003       (write-buffered *(ebp+0x10) %esi)
    24004     }
    24005     (write-buffered *(ebp+0x10) "'\n")
    24006     (flush *(ebp+0x10))
    24007     (stop *(ebp+0x14) 1)
    24008     # never gets here
    24009
    24010 check-mu-index-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    24011     # . prologue
    24012     55/push-ebp
    24013     89/<- %ebp 4/r32/esp
    24014     # . save registers
    24015     50/push-eax
    24016     51/push-ecx
    24017     52/push-edx
    24018     53/push-ebx
    24019     56/push-esi
    24020     57/push-edi
    24021     # esi = stmt
    24022     8b/-> *(ebp+8) 6/r32/esi
    24023     # - check for 0 inouts
    24024     # var base/ecx: (addr var) = stmt->inouts->value
    24025     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    24026 $check-mu-index-stmt:check-no-inouts:
    24027     3d/compare-eax-and 0/imm32
    24028     0f 84/jump-if-= $check-mu-index-stmt:error-too-few-inouts/disp32
    24029     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    24030     89/<- %ecx 0/r32/eax
    24031     # - check base type is either (addr array ...) in register or (array ...) on stack
    24032     # var base-type/ebx: (addr type-tree) = lookup(base->type)
    24033     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
    24034     89/<- %ebx 0/r32/eax
    24035     # if base-type is an atom, abort with a precise error
    24036     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
    24037     {
    24038       74/jump-if-= break/disp8
    24039       (simple-mu-type? %ebx 3)  # array => eax
    24040       3d/compare-eax-and 0/imm32/false
    24041       0f 85/jump-if-!= $check-mu-index-stmt:error-base-array-atom-type/disp32
    24042       0f 84/jump-if-= $check-mu-index-stmt:error-base-non-array-type/disp32
    24043     }
    24044 $check-mu-index-stmt:base-is-compound:
    24045     # if type->left not addr or array, abort
    24046     {
    24047       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
    24048       (simple-mu-type? %eax 2)  # addr => eax
    24049       3d/compare-eax-and 0/imm32/false
    24050       75/jump-if-!= break/disp8
    24051       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
    24052       (simple-mu-type? %eax 3)  # array => eax
    24053       3d/compare-eax-and 0/imm32/false
    24054       75/jump-if-!= break/disp8
    24055       e9/jump $check-mu-index-stmt:error-base-non-array-type/disp32
    24056     }
    24057     # if (type->left == addr) ensure type->right->left == array and type->register exists
    24058     {
    24059       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
    24060       (simple-mu-type? %eax 2)  # addr => eax
    24061       3d/compare-eax-and 0/imm32/false
    24062       74/jump-if-= break/disp8
    24063 $check-mu-index-stmt:base-is-addr:
    24064       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
    24065       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    24066       (simple-mu-type? %eax 3)  # array => eax
    24067       3d/compare-eax-and 0/imm32/false
    24068       0f 84/jump-if-= $check-mu-index-stmt:error-base-non-array-type/disp32
    24069 $check-mu-index-stmt:check-base-addr-is-register:
    24070       81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
    24071       0f 84/jump-if-= $check-mu-index-stmt:error-base-address-array-type-on-stack/disp32
    24072     }
    24073     # if (type->left == array) ensure type->register doesn't exist
    24074     {
    24075       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
    24076       (simple-mu-type? %eax 3)  # array => eax
    24077       3d/compare-eax-and 0/imm32/false
    24078       74/jump-if-= break/disp8
    24079 $check-mu-index-stmt:base-is-array:
    24080       81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
    24081       0f 85/jump-if-!= $check-mu-index-stmt:error-base-array-type-in-register/disp32
    24082     }
    24083     # if (base-type->left == addr) base-type = base-type->right
    24084     {
    24085       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
    24086       (simple-mu-type? %eax 2)  # addr => eax
    24087       3d/compare-eax-and 0/imm32/false
    24088       74/jump-if-= break/disp8
    24089       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
    24090       89/<- %ebx 0/r32/eax
    24091     }
    24092     # - check for 1 inout
    24093     # var index/ecx: (addr stmt-var) = stmt->inouts->next->value
    24094     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    24095     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    24096 $check-mu-index-stmt:check-single-inout:
    24097     3d/compare-eax-and 0/imm32
    24098     0f 84/jump-if-= $check-mu-index-stmt:error-too-few-inouts/disp32
    24099     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    24100     89/<- %ecx 0/r32/eax
    24101     # - check index is either a literal or register
    24102     # var index-type/edx: (addr type-tree)
    24103     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
    24104     89/<- %edx 0/r32/eax
    24105     # if index type is an atom, it must be a literal or int
    24106     81 7/subop/compare *edx 0/imm32/false  # Type-tree-is-atom
    24107     {
    24108       74/jump-if-= break/disp8
    24109 $check-mu-index-stmt:index-type-is-atom:
    24110       (simple-mu-type? %edx 0)  # literal => eax
    24111       3d/compare-eax-and 0/imm32/false
    24112       75/jump-if-!= $check-mu-index-stmt:index-type-done/disp8
    24113       (simple-mu-type? %edx 1)  # int => eax
    24114       3d/compare-eax-and 0/imm32/false
    24115       75/jump-if-!= $check-mu-index-stmt:index-type-done/disp8
    24116       (simple-mu-type? %edx 7)  # offset => eax
    24117       3d/compare-eax-and 0/imm32/false
    24118       0f 85/jump-if-!= $check-mu-index-stmt:error-index-offset-atom-type/disp32
    24119       e9/jump $check-mu-index-stmt:error-invalid-index-type/disp32
    24120     }
    24121     # if index type is a non-atom: it must be an offset
    24122     {
    24123       75/jump-if-!= break/disp8
    24124 $check-mu-index-stmt:index-type-is-non-atom:
    24125       (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
    24126       (simple-mu-type? %eax 7)  # offset => eax
    24127       3d/compare-eax-and 0/imm32/false
    24128       0f 84/jump-if-= $check-mu-index-stmt:error-invalid-index-type/disp32
    24129     }
    24130 $check-mu-index-stmt:index-type-done:
    24131     # check index is either a literal or in a register
    24132     {
    24133       (simple-mu-type? %edx 0)  # literal => eax
    24134       3d/compare-eax-and 0/imm32/false
    24135       75/jump-if-!= break/disp8
    24136 $check-mu-index-stmt:check-index-in-register:
    24137       81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
    24138       0f 84/jump-if-= $check-mu-index-stmt:error-index-on-stack/disp32
    24139     }
    24140     # - if index is an 'int', check that element type of base has size 1, 2, 4 or 8 bytes.
    24141     {
    24142       (simple-mu-type? %edx 1)  # int => eax
    24143       3d/compare-eax-and 0/imm32/false
    24144       74/jump-if-= break/disp8
    24145 $check-mu-index-stmt:check-index-can-be-int:
    24146       (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    24147       (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    24148       (array-element-size %eax)  # => eax
    24149       3d/compare-eax-and 1/imm32
    24150       74/jump-if-= break/disp8
    24151       3d/compare-eax-and 2/imm32
    24152       74/jump-if-= break/disp8
    24153       3d/compare-eax-and 4/imm32
    24154       74/jump-if-= break/disp8
    24155       3d/compare-eax-and 8/imm32
    24156       74/jump-if-= break/disp8
    24157       e9/jump $check-mu-index-stmt:error-index-needs-offset/disp32
    24158     }
    24159     # - check for too many inouts
    24160     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    24161     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    24162     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    24163     3d/compare-eax-and 0/imm32/false
    24164     0f 85/jump-if-!= $check-mu-index-stmt:error-too-many-inouts/disp32
    24165     # - check for 0 outputs
    24166     # var output/edi: (addr var) = stmt->outputs->value
    24167     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    24168     3d/compare-eax-and 0/imm32/false
    24169     0f 84/jump-if-= $check-mu-index-stmt:error-too-few-outputs/disp32
    24170     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    24171     89/<- %edi 0/r32/eax
    24172     # - check output type
    24173     # must have a non-atomic type
    24174     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
    24175     89/<- %edx 0/r32/eax
    24176     81 7/subop/compare *edx 0/imm32/false  # Type-tree-is-atom
    24177     0f 85/jump-if-!= $check-mu-index-stmt:error-output-type-not-address/disp32
    24178     # type must start with (addr ...)
    24179     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
    24180     (simple-mu-type? %eax 2)  # addr => eax
    24181     3d/compare-eax-and 0/imm32/false
    24182     0f 84/jump-if-= $check-mu-index-stmt:error-output-type-not-address/disp32
    24183     # if tail(base-type) != tail(output-type) abort
    24184     (type-tail %ebx)  # => eax
    24185     89/<- %ebx 0/r32/eax
    24186     (type-tail %edx)  # => eax
    24187     (type-equal? %ebx %eax)  # => eax
    24188     3d/compare-eax-and 0/imm32/false
    24189     0f 84/jump-if-= $check-mu-index-stmt:error-bad-output-type/disp32
    24190     # - check for too many outputs
    24191     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    24192     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    24193     3d/compare-eax-and 0/imm32/false
    24194     0f 85/jump-if-!= $check-mu-index-stmt:error-too-many-outputs/disp32
    24195 $check-mu-index-stmt:end:
    24196     # . restore registers
    24197     5f/pop-to-edi
    24198     5e/pop-to-esi
    24199     5b/pop-to-ebx
    24200     5a/pop-to-edx
    24201     59/pop-to-ecx
    24202     58/pop-to-eax
    24203     # . epilogue
    24204     89/<- %esp 5/r32/ebp
    24205     5d/pop-to-ebp
    24206     c3/return
    24207
    24208 $check-mu-index-stmt:error-base-non-array-type:
    24209     (write-buffered *(ebp+0x10) "fn ")
    24210     8b/-> *(ebp+0xc) 0/r32/eax
    24211     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24212     (write-buffered *(ebp+0x10) %eax)
    24213     (write-buffered *(ebp+0x10) ": stmt index: var '")
    24214     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    24215     (write-buffered *(ebp+0x10) %eax)
    24216     (write-buffered *(ebp+0x10) "' is not an array\n")
    24217     (flush *(ebp+0x10))
    24218     (stop *(ebp+0x14) 1)
    24219     # never gets here
    24220
    24221 $check-mu-index-stmt:error-base-array-atom-type:
    24222     (write-buffered *(ebp+0x10) "fn ")
    24223     8b/-> *(ebp+0xc) 0/r32/eax
    24224     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24225     (write-buffered *(ebp+0x10) %eax)
    24226     (write-buffered *(ebp+0x10) ": stmt index: array '")
    24227     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    24228     (write-buffered *(ebp+0x10) %eax)
    24229     (write-buffered *(ebp+0x10) "' must specify the type of its elements\n")
    24230     (flush *(ebp+0x10))
    24231     (stop *(ebp+0x14) 1)
    24232     # never gets here
    24233
    24234 $check-mu-index-stmt:error-base-address-array-type-on-stack:
    24235     (write-buffered *(ebp+0x10) "fn ")
    24236     8b/-> *(ebp+0xc) 0/r32/eax
    24237     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24238     (write-buffered *(ebp+0x10) %eax)
    24239     (write-buffered *(ebp+0x10) ": stmt index: var '")
    24240     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    24241     (write-buffered *(ebp+0x10) %eax)
    24242     (write-buffered *(ebp+0x10) "' is an addr to an array, and so must live in a register\n")
    24243     (flush *(ebp+0x10))
    24244     (stop *(ebp+0x14) 1)
    24245     # never gets here
    24246
    24247 $check-mu-index-stmt:error-base-array-type-in-register:
    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: var '")
    24253     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    24254     (write-buffered *(ebp+0x10) %eax)
    24255     (write-buffered *(ebp+0x10) "' is an array, and so must live on the stack\n")
    24256     (flush *(ebp+0x10))
    24257     (stop *(ebp+0x14) 1)
    24258     # never gets here
    24259
    24260 $check-mu-index-stmt:error-too-few-inouts:
    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: too few inouts (2 required)\n")
    24266     (flush *(ebp+0x10))
    24267     (stop *(ebp+0x14) 1)
    24268     # never gets here
    24269
    24270 $check-mu-index-stmt:error-invalid-index-type:
    24271     (write-buffered *(ebp+0x10) "fn ")
    24272     8b/-> *(ebp+0xc) 0/r32/eax
    24273     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24274     (write-buffered *(ebp+0x10) %eax)
    24275     (write-buffered *(ebp+0x10) ": stmt index: second argument '")
    24276     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    24277     (write-buffered *(ebp+0x10) %eax)
    24278     (write-buffered *(ebp+0x10) "' must be an int or offset\n")
    24279     (flush *(ebp+0x10))
    24280     (stop *(ebp+0x14) 1)
    24281     # never gets here
    24282
    24283 $check-mu-index-stmt:error-index-offset-atom-type:
    24284     (write-buffered *(ebp+0x10) "fn ")
    24285     8b/-> *(ebp+0xc) 0/r32/eax
    24286     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24287     (write-buffered *(ebp+0x10) %eax)
    24288     (write-buffered *(ebp+0x10) ": stmt index: offset '")
    24289     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    24290     (write-buffered *(ebp+0x10) %eax)
    24291     (write-buffered *(ebp+0x10) "' must specify the type of array elements\n")
    24292     (flush *(ebp+0x10))
    24293     (stop *(ebp+0x14) 1)
    24294     # never gets here
    24295
    24296 $check-mu-index-stmt:error-index-on-stack:
    24297     (write-buffered *(ebp+0x10) "fn ")
    24298     8b/-> *(ebp+0xc) 0/r32/eax
    24299     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24300     (write-buffered *(ebp+0x10) %eax)
    24301     (write-buffered *(ebp+0x10) ": stmt index: second argument '")
    24302     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    24303     (write-buffered *(ebp+0x10) %eax)
    24304     (write-buffered *(ebp+0x10) "' must be in a register\n")
    24305     (flush *(ebp+0x10))
    24306     (stop *(ebp+0x14) 1)
    24307     # never gets here
    24308
    24309 $check-mu-index-stmt:error-index-needs-offset:
    24310     (write-buffered *(ebp+0x10) "fn ")
    24311     8b/-> *(ebp+0xc) 0/r32/eax
    24312     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24313     (write-buffered *(ebp+0x10) %eax)
    24314     (write-buffered *(ebp+0x10) ": stmt index: cannot take an int for array '")
    24315     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    24316     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    24317     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    24318     (write-buffered *(ebp+0x10) %eax)
    24319     (write-buffered *(ebp+0x10) "'; create an offset instead. See mu.md for details.\n")
    24320     (flush *(ebp+0x10))
    24321     (stop *(ebp+0x14) 1)
    24322     # never gets here
    24323
    24324 $check-mu-index-stmt:error-too-many-inouts:
    24325     (write-buffered *(ebp+0x10) "fn ")
    24326     8b/-> *(ebp+0xc) 0/r32/eax
    24327     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24328     (write-buffered *(ebp+0x10) %eax)
    24329     (write-buffered *(ebp+0x10) ": stmt index: too many inouts (2 required)\n")
    24330     (flush *(ebp+0x10))
    24331     (stop *(ebp+0x14) 1)
    24332     # never gets here
    24333
    24334 $check-mu-index-stmt:error-too-few-outputs:
    24335     (write-buffered *(ebp+0x10) "fn ")
    24336     8b/-> *(ebp+0xc) 0/r32/eax
    24337     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24338     (write-buffered *(ebp+0x10) %eax)
    24339     (write-buffered *(ebp+0x10) ": stmt index: must have an output\n")
    24340     (flush *(ebp+0x10))
    24341     (stop *(ebp+0x14) 1)
    24342     # never gets here
    24343
    24344 $check-mu-index-stmt:error-too-many-outputs:
    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: too many outputs (1 required)\n")
    24350     (flush *(ebp+0x10))
    24351     (stop *(ebp+0x14) 1)
    24352     # never gets here
    24353
    24354 $check-mu-index-stmt:error-output-not-in-register:
    24355     (write-buffered *(ebp+0x10) "fn ")
    24356     8b/-> *(ebp+0xc) 0/r32/eax
    24357     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24358     (write-buffered *(ebp+0x10) %eax)
    24359     (write-buffered *(ebp+0x10) ": stmt index: output '")
    24360     (lookup *edi *(edi+4))  # Var-name Var-name => eax
    24361     (write-buffered *(ebp+0x10) %eax)
    24362     (write-buffered *(ebp+0x10) "' is not in a register\n")
    24363     (flush *(ebp+0x10))
    24364     (stop *(ebp+0x14) 1)
    24365     # never gets here
    24366
    24367 $check-mu-index-stmt:error-output-type-not-address:
    24368     (write-buffered *(ebp+0x10) "fn ")
    24369     8b/-> *(ebp+0xc) 0/r32/eax
    24370     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24371     (write-buffered *(ebp+0x10) %eax)
    24372     (write-buffered *(ebp+0x10) ": stmt index: output '")
    24373     (lookup *edi *(edi+4))  # Var-name Var-name => eax
    24374     (write-buffered *(ebp+0x10) %eax)
    24375     (write-buffered *(ebp+0x10) "' must be an addr\n")
    24376     (flush *(ebp+0x10))
    24377     (stop *(ebp+0x14) 1)
    24378     # never gets here
    24379
    24380 $check-mu-index-stmt:error-bad-output-type:
    24381     (write-buffered *(ebp+0x10) "fn ")
    24382     8b/-> *(ebp+0xc) 0/r32/eax
    24383     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24384     (write-buffered *(ebp+0x10) %eax)
    24385     (write-buffered *(ebp+0x10) ": stmt index: output '")
    24386     (lookup *edi *(edi+4))  # Var-name Var-name => eax
    24387     (write-buffered *(ebp+0x10) %eax)
    24388     (write-buffered *(ebp+0x10) "' does not have the right type\n")
    24389     (flush *(ebp+0x10))
    24390     (stop *(ebp+0x14) 1)
    24391     # never gets here
    24392
    24393 check-mu-length-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    24394     # . prologue
    24395     55/push-ebp
    24396     89/<- %ebp 4/r32/esp
    24397     # . save registers
    24398     50/push-eax
    24399     51/push-ecx
    24400     52/push-edx
    24401     53/push-ebx
    24402     56/push-esi
    24403     57/push-edi
    24404     # esi = stmt
    24405     8b/-> *(ebp+8) 6/r32/esi
    24406     # - check for 0 inouts
    24407     # var base/ecx: (addr var) = stmt->inouts->value
    24408     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    24409 $check-mu-length-stmt:check-no-inouts:
    24410     3d/compare-eax-and 0/imm32
    24411     0f 84/jump-if-= $check-mu-length-stmt:error-too-few-inouts/disp32
    24412     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    24413     89/<- %ecx 0/r32/eax
    24414     # - check base type is either (addr array ...) in register or (array ...) on stack
    24415     # var base-type/ebx: (addr type-tree) = lookup(base->type)
    24416     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
    24417     89/<- %ebx 0/r32/eax
    24418     # if base-type is an atom, abort with a precise error
    24419     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
    24420     {
    24421       74/jump-if-= break/disp8
    24422       (simple-mu-type? %ebx 3)  # array => eax
    24423       3d/compare-eax-and 0/imm32/false
    24424       0f 85/jump-if-!= $check-mu-length-stmt:error-base-array-atom-type/disp32
    24425       0f 84/jump-if-= $check-mu-length-stmt:error-base-non-array-type/disp32
    24426     }
    24427 $check-mu-length-stmt:base-is-compound:
    24428     # if type->left not addr or array, abort
    24429     {
    24430       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
    24431       (simple-mu-type? %eax 2)  # addr => eax
    24432       3d/compare-eax-and 0/imm32/false
    24433       75/jump-if-!= break/disp8
    24434       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
    24435       (simple-mu-type? %eax 3)  # array => eax
    24436       3d/compare-eax-and 0/imm32/false
    24437       75/jump-if-!= break/disp8
    24438       e9/jump $check-mu-length-stmt:error-base-non-array-type/disp32
    24439     }
    24440     # if (type->left == addr) ensure type->right->left == array and type->register exists
    24441     {
    24442       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
    24443       (simple-mu-type? %eax 2)  # addr => eax
    24444       3d/compare-eax-and 0/imm32/false
    24445       74/jump-if-= break/disp8
    24446 $check-mu-length-stmt:base-is-addr:
    24447       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
    24448       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    24449       (simple-mu-type? %eax 3)  # array => eax
    24450       3d/compare-eax-and 0/imm32/false
    24451       0f 84/jump-if-= $check-mu-length-stmt:error-base-non-array-type/disp32
    24452 $check-mu-length-stmt:check-base-addr-is-register:
    24453       81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
    24454       0f 84/jump-if-= $check-mu-length-stmt:error-base-address-array-type-on-stack/disp32
    24455     }
    24456     # if (type->left == array) ensure type->register doesn't exist
    24457     {
    24458       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
    24459       (simple-mu-type? %eax 3)  # array => eax
    24460       3d/compare-eax-and 0/imm32/false
    24461       74/jump-if-= break/disp8
    24462 $check-mu-length-stmt:base-is-array:
    24463       81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
    24464       0f 85/jump-if-!= $check-mu-length-stmt:error-base-array-type-in-register/disp32
    24465     }
    24466     # if (base-type->left == addr) base-type = base-type->right
    24467     {
    24468       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
    24469       (simple-mu-type? %eax 2)  # addr => eax
    24470       3d/compare-eax-and 0/imm32/false
    24471       74/jump-if-= break/disp8
    24472       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
    24473       89/<- %ebx 0/r32/eax
    24474     }
    24475     # - check for too many inouts
    24476     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    24477     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    24478     3d/compare-eax-and 0/imm32/false
    24479     0f 85/jump-if-!= $check-mu-length-stmt:error-too-many-inouts/disp32
    24480     # - check for 0 outputs
    24481     # var output/edi: (addr var) = stmt->outputs->value
    24482     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    24483     3d/compare-eax-and 0/imm32/false
    24484     0f 84/jump-if-= $check-mu-length-stmt:error-too-few-outputs/disp32
    24485     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    24486     89/<- %edi 0/r32/eax
    24487     # - check output type
    24488     # must have a non-atomic type
    24489     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
    24490     (simple-mu-type? %eax 1)  # int => eax
    24491     3d/compare-eax-and 0/imm32/false
    24492     0f 84/jump-if-= $check-mu-length-stmt:error-invalid-output-type/disp32
    24493     # - check for too many outputs
    24494     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    24495     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    24496     3d/compare-eax-and 0/imm32/false
    24497     0f 85/jump-if-!= $check-mu-length-stmt:error-too-many-outputs/disp32
    24498 $check-mu-length-stmt:end:
    24499     # . restore registers
    24500     5f/pop-to-edi
    24501     5e/pop-to-esi
    24502     5b/pop-to-ebx
    24503     5a/pop-to-edx
    24504     59/pop-to-ecx
    24505     58/pop-to-eax
    24506     # . epilogue
    24507     89/<- %esp 5/r32/ebp
    24508     5d/pop-to-ebp
    24509     c3/return
    24510
    24511 $check-mu-length-stmt:error-base-non-array-type:
    24512     (write-buffered *(ebp+0x10) "fn ")
    24513     8b/-> *(ebp+0xc) 0/r32/eax
    24514     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24515     (write-buffered *(ebp+0x10) %eax)
    24516     (write-buffered *(ebp+0x10) ": stmt length: var '")
    24517     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    24518     (write-buffered *(ebp+0x10) %eax)
    24519     (write-buffered *(ebp+0x10) "' is not an array\n")
    24520     (flush *(ebp+0x10))
    24521     (stop *(ebp+0x14) 1)
    24522     # never gets here
    24523
    24524 $check-mu-length-stmt:error-base-array-atom-type:
    24525     (write-buffered *(ebp+0x10) "fn ")
    24526     8b/-> *(ebp+0xc) 0/r32/eax
    24527     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24528     (write-buffered *(ebp+0x10) %eax)
    24529     (write-buffered *(ebp+0x10) ": stmt length: array '")
    24530     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    24531     (write-buffered *(ebp+0x10) %eax)
    24532     (write-buffered *(ebp+0x10) "' must specify the type of its elements\n")
    24533     (flush *(ebp+0x10))
    24534     (stop *(ebp+0x14) 1)
    24535     # never gets here
    24536
    24537 $check-mu-length-stmt:error-base-address-array-type-on-stack:
    24538     (write-buffered *(ebp+0x10) "fn ")
    24539     8b/-> *(ebp+0xc) 0/r32/eax
    24540     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24541     (write-buffered *(ebp+0x10) %eax)
    24542     (write-buffered *(ebp+0x10) ": stmt length: var '")
    24543     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    24544     (write-buffered *(ebp+0x10) %eax)
    24545     (write-buffered *(ebp+0x10) "' is an addr to an array, and so must live in a register\n")
    24546     (flush *(ebp+0x10))
    24547     (stop *(ebp+0x14) 1)
    24548     # never gets here
    24549
    24550 $check-mu-length-stmt:error-base-array-type-in-register:
    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: var '")
    24556     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    24557     (write-buffered *(ebp+0x10) %eax)
    24558     (write-buffered *(ebp+0x10) "' is an array, and so must live on the stack\n")
    24559     (flush *(ebp+0x10))
    24560     (stop *(ebp+0x14) 1)
    24561     # never gets here
    24562
    24563 $check-mu-length-stmt:error-too-few-inouts:
    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: too few inouts (1 required)\n")
    24569     (flush *(ebp+0x10))
    24570     (stop *(ebp+0x14) 1)
    24571     # never gets here
    24572
    24573 $check-mu-length-stmt:error-invalid-index-type:
    24574     (write-buffered *(ebp+0x10) "fn ")
    24575     8b/-> *(ebp+0xc) 0/r32/eax
    24576     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24577     (write-buffered *(ebp+0x10) %eax)
    24578     (write-buffered *(ebp+0x10) ": stmt length: second argument '")
    24579     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    24580     (write-buffered *(ebp+0x10) %eax)
    24581     (write-buffered *(ebp+0x10) "' must be an int or offset\n")
    24582     (flush *(ebp+0x10))
    24583     (stop *(ebp+0x14) 1)
    24584     # never gets here
    24585
    24586 $check-mu-length-stmt:error-index-offset-atom-type:
    24587     (write-buffered *(ebp+0x10) "fn ")
    24588     8b/-> *(ebp+0xc) 0/r32/eax
    24589     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24590     (write-buffered *(ebp+0x10) %eax)
    24591     (write-buffered *(ebp+0x10) ": stmt length: offset '")
    24592     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    24593     (write-buffered *(ebp+0x10) %eax)
    24594     (write-buffered *(ebp+0x10) "' must specify the type of array elements\n")
    24595     (flush *(ebp+0x10))
    24596     (stop *(ebp+0x14) 1)
    24597     # never gets here
    24598
    24599 $check-mu-length-stmt:error-index-on-stack:
    24600     (write-buffered *(ebp+0x10) "fn ")
    24601     8b/-> *(ebp+0xc) 0/r32/eax
    24602     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24603     (write-buffered *(ebp+0x10) %eax)
    24604     (write-buffered *(ebp+0x10) ": stmt length: second argument '")
    24605     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    24606     (write-buffered *(ebp+0x10) %eax)
    24607     (write-buffered *(ebp+0x10) "' must be in a register\n")
    24608     (flush *(ebp+0x10))
    24609     (stop *(ebp+0x14) 1)
    24610     # never gets here
    24611
    24612 $check-mu-length-stmt:error-index-needs-offset:
    24613     (write-buffered *(ebp+0x10) "fn ")
    24614     8b/-> *(ebp+0xc) 0/r32/eax
    24615     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24616     (write-buffered *(ebp+0x10) %eax)
    24617     (write-buffered *(ebp+0x10) ": stmt length: cannot take an int for array '")
    24618     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    24619     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    24620     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    24621     (write-buffered *(ebp+0x10) %eax)
    24622     (write-buffered *(ebp+0x10) "'; create an offset instead. See mu.md for details.\n")
    24623     (flush *(ebp+0x10))
    24624     (stop *(ebp+0x14) 1)
    24625     # never gets here
    24626
    24627 $check-mu-length-stmt:error-too-many-inouts:
    24628     (write-buffered *(ebp+0x10) "fn ")
    24629     8b/-> *(ebp+0xc) 0/r32/eax
    24630     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24631     (write-buffered *(ebp+0x10) %eax)
    24632     (write-buffered *(ebp+0x10) ": stmt length: too many inouts (1 required)\n")
    24633     (flush *(ebp+0x10))
    24634     (stop *(ebp+0x14) 1)
    24635     # never gets here
    24636
    24637 $check-mu-length-stmt:error-too-few-outputs:
    24638     (write-buffered *(ebp+0x10) "fn ")
    24639     8b/-> *(ebp+0xc) 0/r32/eax
    24640     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24641     (write-buffered *(ebp+0x10) %eax)
    24642     (write-buffered *(ebp+0x10) ": stmt length: must have an output\n")
    24643     (flush *(ebp+0x10))
    24644     (stop *(ebp+0x14) 1)
    24645     # never gets here
    24646
    24647 $check-mu-length-stmt:error-too-many-outputs:
    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: too many outputs (1 required)\n")
    24653     (flush *(ebp+0x10))
    24654     (stop *(ebp+0x14) 1)
    24655     # never gets here
    24656
    24657 $check-mu-length-stmt:error-output-not-in-register:
    24658     (write-buffered *(ebp+0x10) "fn ")
    24659     8b/-> *(ebp+0xc) 0/r32/eax
    24660     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24661     (write-buffered *(ebp+0x10) %eax)
    24662     (write-buffered *(ebp+0x10) ": stmt length: output '")
    24663     (lookup *edi *(edi+4))  # Var-name Var-name => eax
    24664     (write-buffered *(ebp+0x10) %eax)
    24665     (write-buffered *(ebp+0x10) "' is not in a register\n")
    24666     (flush *(ebp+0x10))
    24667     (stop *(ebp+0x14) 1)
    24668     # never gets here
    24669
    24670 $check-mu-length-stmt:error-invalid-output-type:
    24671     (write-buffered *(ebp+0x10) "fn ")
    24672     8b/-> *(ebp+0xc) 0/r32/eax
    24673     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24674     (write-buffered *(ebp+0x10) %eax)
    24675     (write-buffered *(ebp+0x10) ": stmt length: output '")
    24676     (lookup *edi *(edi+4))  # Var-name Var-name => eax
    24677     (write-buffered *(ebp+0x10) %eax)
    24678     (write-buffered *(ebp+0x10) "' does not have the right type\n")
    24679     (flush *(ebp+0x10))
    24680     (stop *(ebp+0x14) 1)
    24681     # never gets here
    24682
    24683 check-mu-compute-offset-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    24684     # . prologue
    24685     55/push-ebp
    24686     89/<- %ebp 4/r32/esp
    24687     # . save registers
    24688     50/push-eax
    24689     51/push-ecx
    24690     52/push-edx
    24691     53/push-ebx
    24692     56/push-esi
    24693     57/push-edi
    24694     # esi = stmt
    24695     8b/-> *(ebp+8) 6/r32/esi
    24696     # - check for 0 inouts
    24697     # var base/ecx: (addr var) = stmt->inouts->value
    24698     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    24699 $check-mu-compute-offset-stmt:check-no-inouts:
    24700     3d/compare-eax-and 0/imm32
    24701     0f 84/jump-if-= $check-mu-compute-offset-stmt:error-too-few-inouts/disp32
    24702     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    24703     89/<- %ecx 0/r32/eax
    24704     # - check base type is either (addr array ...) in register or (array ...) on stack
    24705     # var base-type/ebx: (addr type-tree) = lookup(base->type)
    24706     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
    24707     89/<- %ebx 0/r32/eax
    24708     # if base-type is an atom, abort with a precise error
    24709     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
    24710     {
    24711       74/jump-if-= break/disp8
    24712       (simple-mu-type? %ebx 3)  # array => eax
    24713       3d/compare-eax-and 0/imm32/false
    24714       0f 85/jump-if-!= $check-mu-compute-offset-stmt:error-base-array-atom-type/disp32
    24715       0f 84/jump-if-= $check-mu-compute-offset-stmt:error-base-non-array-type/disp32
    24716     }
    24717 $check-mu-compute-offset-stmt:base-is-compound:
    24718     # if type->left not addr or array, abort
    24719     {
    24720       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
    24721       (simple-mu-type? %eax 2)  # addr => eax
    24722       3d/compare-eax-and 0/imm32/false
    24723       75/jump-if-!= break/disp8
    24724       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
    24725       (simple-mu-type? %eax 3)  # array => eax
    24726       3d/compare-eax-and 0/imm32/false
    24727       75/jump-if-!= break/disp8
    24728       e9/jump $check-mu-compute-offset-stmt:error-base-non-array-type/disp32
    24729     }
    24730     # if (type->left == addr) ensure type->right->left == array and type->register exists
    24731     {
    24732       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
    24733       (simple-mu-type? %eax 2)  # addr => eax
    24734       3d/compare-eax-and 0/imm32/false
    24735       74/jump-if-= break/disp8
    24736 $check-mu-compute-offset-stmt:base-is-addr:
    24737       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
    24738       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    24739       (simple-mu-type? %eax 3)  # array => eax
    24740       3d/compare-eax-and 0/imm32/false
    24741       0f 84/jump-if-= $check-mu-compute-offset-stmt:error-base-non-array-type/disp32
    24742     }
    24743     # if (base-type->left == addr) base-type = base-type->right
    24744     {
    24745       (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
    24746       (simple-mu-type? %eax 2)  # addr => eax
    24747       3d/compare-eax-and 0/imm32/false
    24748       74/jump-if-= break/disp8
    24749       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
    24750       89/<- %ebx 0/r32/eax
    24751     }
    24752     # - check for 1 inout
    24753     # var index/ecx: (addr stmt-var) = stmt->inouts->next->value
    24754     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    24755     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    24756 $check-mu-compute-offset-stmt:check-single-inout:
    24757     3d/compare-eax-and 0/imm32
    24758     0f 84/jump-if-= $check-mu-compute-offset-stmt:error-too-few-inouts/disp32
    24759     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    24760     89/<- %ecx 0/r32/eax
    24761     # - check index is either a literal or register
    24762     # var index-type/edx: (addr type-tree)
    24763     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
    24764     89/<- %edx 0/r32/eax
    24765     # index type must be a literal or int
    24766     81 7/subop/compare *edx 0/imm32/false  # Type-tree-is-atom
    24767     0f 84/jump-if-= $check-mu-compute-offset-stmt:error-invalid-index-type/disp32
    24768     {
    24769 $check-mu-compute-offset-stmt:index-type-is-atom:
    24770       (simple-mu-type? %edx 0)  # literal => eax
    24771       3d/compare-eax-and 0/imm32/false
    24772       75/jump-if-!= break/disp8
    24773       (simple-mu-type? %edx 1)  # int => eax
    24774       3d/compare-eax-and 0/imm32/false
    24775       75/jump-if-!= break/disp8
    24776       e9/jump $check-mu-compute-offset-stmt:error-invalid-index-type/disp32
    24777     }
    24778     # - check for too many inouts
    24779     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    24780     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    24781     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    24782     3d/compare-eax-and 0/imm32/false
    24783     0f 85/jump-if-!= $check-mu-compute-offset-stmt:error-too-many-inouts/disp32
    24784     # - check for 0 outputs
    24785     # var output/edi: (addr var) = stmt->outputs->value
    24786     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    24787     3d/compare-eax-and 0/imm32/false
    24788     0f 84/jump-if-= $check-mu-compute-offset-stmt:error-too-few-outputs/disp32
    24789     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    24790     89/<- %edi 0/r32/eax
    24791     # - check output type
    24792     # must have a non-atomic type
    24793     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
    24794     89/<- %edx 0/r32/eax
    24795     81 7/subop/compare *edx 0/imm32/false  # Type-tree-is-atom
    24796     0f 85/jump-if-!= $check-mu-compute-offset-stmt:error-output-type-not-offset/disp32
    24797     # type must start with (offset ...)
    24798     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
    24799     (simple-mu-type? %eax 7)  # offset => eax
    24800     3d/compare-eax-and 0/imm32/false
    24801     0f 84/jump-if-= $check-mu-compute-offset-stmt:error-output-type-not-offset/disp32
    24802     # if tail(base-type) != tail(output-type) abort
    24803     (type-tail %ebx)  # => eax
    24804     89/<- %ebx 0/r32/eax
    24805     (type-tail %edx)  # => eax
    24806     (type-equal? %ebx %eax)  # => eax
    24807     3d/compare-eax-and 0/imm32/false
    24808     0f 84/jump-if-= $check-mu-compute-offset-stmt:error-bad-output-type/disp32
    24809     # - check for too many outputs
    24810     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    24811     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    24812     3d/compare-eax-and 0/imm32/false
    24813     0f 85/jump-if-!= $check-mu-compute-offset-stmt:error-too-many-outputs/disp32
    24814 $check-mu-compute-offset-stmt:end:
    24815     # . restore registers
    24816     5f/pop-to-edi
    24817     5e/pop-to-esi
    24818     5b/pop-to-ebx
    24819     5a/pop-to-edx
    24820     59/pop-to-ecx
    24821     58/pop-to-eax
    24822     # . epilogue
    24823     89/<- %esp 5/r32/ebp
    24824     5d/pop-to-ebp
    24825     c3/return
    24826
    24827 $check-mu-compute-offset-stmt:error-base-non-array-type:
    24828     (write-buffered *(ebp+0x10) "fn ")
    24829     8b/-> *(ebp+0xc) 0/r32/eax
    24830     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24831     (write-buffered *(ebp+0x10) %eax)
    24832     (write-buffered *(ebp+0x10) ": stmt compute-offset: var '")
    24833     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    24834     (write-buffered *(ebp+0x10) %eax)
    24835     (write-buffered *(ebp+0x10) "' is not an array\n")
    24836     (flush *(ebp+0x10))
    24837     (stop *(ebp+0x14) 1)
    24838     # never gets here
    24839
    24840 $check-mu-compute-offset-stmt:error-base-array-atom-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: array '")
    24846     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    24847     (write-buffered *(ebp+0x10) %eax)
    24848     (write-buffered *(ebp+0x10) "' must specify the type of its elements\n")
    24849     (flush *(ebp+0x10))
    24850     (stop *(ebp+0x14) 1)
    24851     # never gets here
    24852
    24853 $check-mu-compute-offset-stmt:error-too-few-inouts:
    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: too few inouts (2 required)\n")
    24859     (flush *(ebp+0x10))
    24860     (stop *(ebp+0x14) 1)
    24861     # never gets here
    24862
    24863 $check-mu-compute-offset-stmt:error-invalid-index-type:
    24864     (write-buffered *(ebp+0x10) "fn ")
    24865     8b/-> *(ebp+0xc) 0/r32/eax
    24866     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24867     (write-buffered *(ebp+0x10) %eax)
    24868     (write-buffered *(ebp+0x10) ": stmt compute-offset: second argument '")
    24869     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    24870     (write-buffered *(ebp+0x10) %eax)
    24871     (write-buffered *(ebp+0x10) "' must be an int\n")
    24872     (flush *(ebp+0x10))
    24873     (stop *(ebp+0x14) 1)
    24874     # never gets here
    24875
    24876 $check-mu-compute-offset-stmt:error-index-offset-atom-type:
    24877     (write-buffered *(ebp+0x10) "fn ")
    24878     8b/-> *(ebp+0xc) 0/r32/eax
    24879     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24880     (write-buffered *(ebp+0x10) %eax)
    24881     (write-buffered *(ebp+0x10) ": stmt compute-offset: offset '")
    24882     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    24883     (write-buffered *(ebp+0x10) %eax)
    24884     (write-buffered *(ebp+0x10) "' must specify the type of array elements\n")
    24885     (flush *(ebp+0x10))
    24886     (stop *(ebp+0x14) 1)
    24887     # never gets here
    24888
    24889 $check-mu-compute-offset-stmt:error-index-on-stack:
    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: second argument '")
    24895     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    24896     (write-buffered *(ebp+0x10) %eax)
    24897     (write-buffered *(ebp+0x10) "' must be in a register\n")
    24898     (flush *(ebp+0x10))
    24899     (stop *(ebp+0x14) 1)
    24900     # never gets here
    24901
    24902 $check-mu-compute-offset-stmt:error-too-many-inouts:
    24903     (write-buffered *(ebp+0x10) "fn ")
    24904     8b/-> *(ebp+0xc) 0/r32/eax
    24905     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24906     (write-buffered *(ebp+0x10) %eax)
    24907     (write-buffered *(ebp+0x10) ": stmt compute-offset: too many inouts (2 required)\n")
    24908     (flush *(ebp+0x10))
    24909     (stop *(ebp+0x14) 1)
    24910     # never gets here
    24911
    24912 $check-mu-compute-offset-stmt:error-too-few-outputs:
    24913     (write-buffered *(ebp+0x10) "fn ")
    24914     8b/-> *(ebp+0xc) 0/r32/eax
    24915     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24916     (write-buffered *(ebp+0x10) %eax)
    24917     (write-buffered *(ebp+0x10) ": stmt compute-offset: must have an output\n")
    24918     (flush *(ebp+0x10))
    24919     (stop *(ebp+0x14) 1)
    24920     # never gets here
    24921
    24922 $check-mu-compute-offset-stmt:error-too-many-outputs:
    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: too many outputs (1 required)\n")
    24928     (flush *(ebp+0x10))
    24929     (stop *(ebp+0x14) 1)
    24930     # never gets here
    24931
    24932 $check-mu-compute-offset-stmt:error-output-not-in-register:
    24933     (write-buffered *(ebp+0x10) "fn ")
    24934     8b/-> *(ebp+0xc) 0/r32/eax
    24935     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24936     (write-buffered *(ebp+0x10) %eax)
    24937     (write-buffered *(ebp+0x10) ": stmt compute-offset: output '")
    24938     (lookup *edi *(edi+4))  # Var-name Var-name => eax
    24939     (write-buffered *(ebp+0x10) %eax)
    24940     (write-buffered *(ebp+0x10) "' is not in a register\n")
    24941     (flush *(ebp+0x10))
    24942     (stop *(ebp+0x14) 1)
    24943     # never gets here
    24944
    24945 $check-mu-compute-offset-stmt:error-output-type-not-offset:
    24946     (write-buffered *(ebp+0x10) "fn ")
    24947     8b/-> *(ebp+0xc) 0/r32/eax
    24948     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24949     (write-buffered *(ebp+0x10) %eax)
    24950     (write-buffered *(ebp+0x10) ": stmt compute-offset: output '")
    24951     (lookup *edi *(edi+4))  # Var-name Var-name => eax
    24952     (write-buffered *(ebp+0x10) %eax)
    24953     (write-buffered *(ebp+0x10) "' must be an offset\n")
    24954     (flush *(ebp+0x10))
    24955     (stop *(ebp+0x14) 1)
    24956     # never gets here
    24957
    24958 $check-mu-compute-offset-stmt:error-bad-output-type:
    24959     (write-buffered *(ebp+0x10) "fn ")
    24960     8b/-> *(ebp+0xc) 0/r32/eax
    24961     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    24962     (write-buffered *(ebp+0x10) %eax)
    24963     (write-buffered *(ebp+0x10) ": stmt compute-offset: output '")
    24964     (lookup *edi *(edi+4))  # Var-name Var-name => eax
    24965     (write-buffered *(ebp+0x10) %eax)
    24966     (write-buffered *(ebp+0x10) "' does not have the right type\n")
    24967     (flush *(ebp+0x10))
    24968     (stop *(ebp+0x14) 1)
    24969     # never gets here
    24970
    24971 check-mu-copy-object-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    24972     # . prologue
    24973     55/push-ebp
    24974     89/<- %ebp 4/r32/esp
    24975     # . save registers
    24976     50/push-eax
    24977     51/push-ecx
    24978     53/push-ebx
    24979     56/push-esi
    24980     57/push-edi
    24981     # esi = stmt
    24982     8b/-> *(ebp+8) 6/r32/esi
    24983 $check-mu-copy-object-stmt:check-for-output:
    24984     # if stmt->outputs abort
    24985     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    24986     3d/compare-eax-and 0/imm32
    24987     0f 85/jump-if-!= $check-mu-copy-object-stmt:error-too-many-outputs/disp32
    24988 $check-mu-copy-object-stmt:get-left:
    24989     # var dest/edi: (addr stmt-var) = stmt->inouts
    24990     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    24991     89/<- %edi 0/r32/eax
    24992     # zero inouts
    24993     3d/compare-eax-and 0/imm32
    24994     0f 84/jump-if-= $check-mu-copy-object-stmt:error-incorrect-inouts/disp32
    24995 $check-mu-copy-object-stmt:get-src:
    24996     # var src/esi: (addr stmt-var) = dest->next
    24997     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
    24998     89/<- %esi 0/r32/eax
    24999     # 1 inout
    25000     3d/compare-eax-and 0/imm32
    25001     0f 84/jump-if-= $check-mu-copy-object-stmt:error-incorrect-inouts/disp32
    25002     # > 2 inouts
    25003     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
    25004     3d/compare-eax-and 0/imm32
    25005     0f 85/jump-if-!= $check-mu-copy-object-stmt:error-incorrect-inouts/disp32
    25006 $check-mu-copy-object-stmt:types:
    25007     # var src-type/ecx: (addr type-tree) = src->value->type
    25008     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    25009     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    25010     89/<- %ecx 0/r32/eax
    25011     # if (src->is-deref?) src-type = src-type->payload
    25012     8b/-> *(esi+0x10) 0/r32/eax  # Stmt-var-is-deref
    25013     3d/compare-eax-and 0/imm32/false
    25014     {
    25015       74/jump-if-= break/disp8
    25016       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
    25017       # if src-type->right is null, src-type = src-type->left
    25018       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
    25019       {
    25020         75/jump-if-!= break/disp8
    25021         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    25022       }
    25023       89/<- %ecx 0/r32/eax
    25024     }
    25025     # if src-type is not addr, abort
    25026     (mu-addr-type? %ecx)  # => eax
    25027     3d/compare-eax-and 0/imm32/false
    25028     0f 84/jump-if-= $check-mu-copy-object-stmt:error-invalid-types/disp32
    25029     # var dest-type/ebx: (addr type-tree) = dest->value->type
    25030     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    25031     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    25032     89/<- %ebx 0/r32/eax
    25033     # if (dest->is-deref?) dest-type = dest-type->payload
    25034     8b/-> *(edi+0x10) 0/r32/eax  # Stmt-var-is-deref
    25035     3d/compare-eax-and 0/imm32/false
    25036     {
    25037       74/jump-if-= break/disp8
    25038       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
    25039       # if dest-type->right is null, dest-type = dest-type->left
    25040       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
    25041       {
    25042         75/jump-if-!= break/disp8
    25043         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    25044       }
    25045       89/<- %ebx 0/r32/eax
    25046     }
    25047     # if (dest-type != src-type) abort
    25048     (type-equal? %ecx %ebx)  # => eax
    25049     3d/compare-eax-and 0/imm32
    25050     0f 84/jump-if-= $check-mu-copy-object-stmt:error-invalid-types/disp32
    25051 $check-mu-copy-object-stmt:end:
    25052     # . restore registers
    25053     5f/pop-to-edi
    25054     5e/pop-to-esi
    25055     5b/pop-to-ebx
    25056     59/pop-to-ecx
    25057     58/pop-to-eax
    25058     # . epilogue
    25059     89/<- %esp 5/r32/ebp
    25060     5d/pop-to-ebp
    25061     c3/return
    25062
    25063 $check-mu-copy-object-stmt:error-incorrect-inouts:
    25064     (write-buffered *(ebp+0x10) "fn ")
    25065     8b/-> *(ebp+0xc) 0/r32/eax
    25066     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25067     (write-buffered *(ebp+0x10) %eax)
    25068     (write-buffered *(ebp+0x10) ": stmt 'copy-object' must have two inouts\n")
    25069     (flush *(ebp+0x10))
    25070     (stop *(ebp+0x14) 1)
    25071     # never gets here
    25072
    25073 $check-mu-copy-object-stmt:error-too-many-outputs:
    25074     (write-buffered *(ebp+0x10) "fn ")
    25075     8b/-> *(ebp+0xc) 0/r32/eax
    25076     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25077     (write-buffered *(ebp+0x10) %eax)
    25078     (write-buffered *(ebp+0x10) ": stmt 'copy-object' must not have any outputs\n")
    25079     (flush *(ebp+0x10))
    25080     (stop *(ebp+0x14) 1)
    25081     # never gets here
    25082
    25083 $check-mu-copy-object-stmt:error-invalid-types:
    25084     (write-buffered *(ebp+0x10) "fn ")
    25085     8b/-> *(ebp+0xc) 0/r32/eax
    25086     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25087     (write-buffered *(ebp+0x10) %eax)
    25088     (write-buffered *(ebp+0x10) ": stmt copy-object: two inouts with identical addr types expected\n")
    25089     (flush *(ebp+0x10))
    25090     (stop *(ebp+0x14) 1)
    25091     # never gets here
    25092
    25093 check-mu-clear-object-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    25094     # . prologue
    25095     55/push-ebp
    25096     89/<- %ebp 4/r32/esp
    25097     # . save registers
    25098     50/push-eax
    25099     51/push-ecx
    25100     53/push-ebx
    25101     56/push-esi
    25102     57/push-edi
    25103     # esi = stmt
    25104     8b/-> *(ebp+8) 6/r32/esi
    25105 $check-mu-clear-object-stmt:check-for-output:
    25106     # if stmt->outputs abort
    25107     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    25108     3d/compare-eax-and 0/imm32
    25109     0f 85/jump-if-!= $check-mu-clear-object-stmt:error-too-many-outputs/disp32
    25110 $check-mu-clear-object-stmt:get-left:
    25111     # var dest/edi: (addr stmt-var) = stmt->inouts
    25112     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    25113     89/<- %edi 0/r32/eax
    25114     # zero inouts
    25115     3d/compare-eax-and 0/imm32
    25116     0f 84/jump-if-= $check-mu-clear-object-stmt:error-incorrect-inouts/disp32
    25117 $check-mu-clear-object-stmt:get-src:
    25118     # > 1 inout
    25119     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
    25120     3d/compare-eax-and 0/imm32
    25121     0f 85/jump-if-!= $check-mu-clear-object-stmt:error-incorrect-inouts/disp32
    25122 $check-mu-clear-object-stmt:types:
    25123     # var src-type/ecx: (addr type-tree) = src->value->type
    25124     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    25125     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    25126     89/<- %ecx 0/r32/eax
    25127     # if (src->is-deref?) src-type = src-type->payload
    25128     8b/-> *(edi+0x10) 0/r32/eax  # Stmt-var-is-deref
    25129     3d/compare-eax-and 0/imm32/false
    25130     {
    25131       74/jump-if-= break/disp8
    25132       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
    25133       # if src-type->right is null, src-type = src-type->left
    25134       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
    25135       {
    25136         75/jump-if-!= break/disp8
    25137         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    25138       }
    25139       89/<- %ecx 0/r32/eax
    25140     }
    25141     # if src-type is not addr, abort
    25142     (mu-addr-type? %ecx)  # => eax
    25143     3d/compare-eax-and 0/imm32/false
    25144     0f 84/jump-if-= $check-mu-clear-object-stmt:error-invalid-type/disp32
    25145 $check-mu-clear-object-stmt:end:
    25146     # . restore registers
    25147     5f/pop-to-edi
    25148     5e/pop-to-esi
    25149     5b/pop-to-ebx
    25150     59/pop-to-ecx
    25151     58/pop-to-eax
    25152     # . epilogue
    25153     89/<- %esp 5/r32/ebp
    25154     5d/pop-to-ebp
    25155     c3/return
    25156
    25157 $check-mu-clear-object-stmt:error-incorrect-inouts:
    25158     (write-buffered *(ebp+0x10) "fn ")
    25159     8b/-> *(ebp+0xc) 0/r32/eax
    25160     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25161     (write-buffered *(ebp+0x10) %eax)
    25162     (write-buffered *(ebp+0x10) ": stmt 'clear-object' must have a single inout\n")
    25163     (flush *(ebp+0x10))
    25164     (stop *(ebp+0x14) 1)
    25165     # never gets here
    25166
    25167 $check-mu-clear-object-stmt:error-too-many-outputs:
    25168     (write-buffered *(ebp+0x10) "fn ")
    25169     8b/-> *(ebp+0xc) 0/r32/eax
    25170     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25171     (write-buffered *(ebp+0x10) %eax)
    25172     (write-buffered *(ebp+0x10) ": stmt 'clear-object' must not have any outputs\n")
    25173     (flush *(ebp+0x10))
    25174     (stop *(ebp+0x14) 1)
    25175     # never gets here
    25176
    25177 $check-mu-clear-object-stmt:error-invalid-type:
    25178     (write-buffered *(ebp+0x10) "fn ")
    25179     8b/-> *(ebp+0xc) 0/r32/eax
    25180     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25181     (write-buffered *(ebp+0x10) %eax)
    25182     (write-buffered *(ebp+0x10) ": stmt clear-object: inout must have an addr type\n")
    25183     (flush *(ebp+0x10))
    25184     (stop *(ebp+0x14) 1)
    25185     # never gets here
    25186
    25187 check-mu-allocate-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    25188     # . prologue
    25189     55/push-ebp
    25190     89/<- %ebp 4/r32/esp
    25191     # . save registers
    25192     50/push-eax
    25193     53/push-ebx
    25194     56/push-esi
    25195     57/push-edi
    25196     # esi = stmt
    25197     8b/-> *(ebp+8) 6/r32/esi
    25198 $check-mu-allocate-stmt:check-for-output:
    25199     # if stmt->outputs abort
    25200     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    25201     3d/compare-eax-and 0/imm32
    25202     0f 85/jump-if-!= $check-mu-allocate-stmt:error-too-many-outputs/disp32
    25203 $check-mu-allocate-stmt:get-target:
    25204     # var target/edi: (addr stmt-var) = stmt->inouts
    25205     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    25206     89/<- %edi 0/r32/eax
    25207     # zero inouts
    25208     3d/compare-eax-and 0/imm32
    25209     0f 84/jump-if-= $check-mu-allocate-stmt:error-incorrect-inouts/disp32
    25210     # > 1 inouts
    25211     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
    25212     3d/compare-eax-and 0/imm32
    25213     0f 85/jump-if-!= $check-mu-allocate-stmt:error-incorrect-inouts/disp32
    25214 $check-mu-allocate-stmt:check-type:
    25215     # var target-type/ebx: (addr type-tree) = target->value->type
    25216     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    25217     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    25218     89/<- %ebx 0/r32/eax
    25219     # if (target->is-deref?) target-type = target-type->payload
    25220     8b/-> *(edi+0x10) 0/r32/eax  # Stmt-var-is-deref
    25221     3d/compare-eax-and 0/imm32/false
    25222     {
    25223       74/jump-if-= break/disp8
    25224       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
    25225       # if target-type->right is null, target-type = target-type->left
    25226       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
    25227       {
    25228         75/jump-if-!= break/disp8
    25229         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    25230       }
    25231       89/<- %ebx 0/r32/eax
    25232     }
    25233     # if target-type is not addr, abort
    25234     (mu-addr-type? %ebx)  # => eax
    25235     3d/compare-eax-and 0/imm32/false
    25236     0f 84/jump-if-= $check-mu-allocate-stmt:error-invalid-type/disp32
    25237     # if target-type->right is an atom, abort
    25238     (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
    25239     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
    25240     0f 85/jump-if-!= $check-mu-allocate-stmt:error-invalid-type/disp32
    25241     # if target-type->right->left is not handle, abort
    25242     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    25243     (simple-mu-type? %eax 4)  # handle => eax
    25244     3d/compare-eax-and 0/imm32/false
    25245     0f 84/jump-if-= $check-mu-allocate-stmt:error-invalid-type/disp32
    25246 $check-mu-allocate-stmt:end:
    25247     # . restore registers
    25248     5f/pop-to-edi
    25249     5e/pop-to-esi
    25250     5b/pop-to-ebx
    25251     58/pop-to-eax
    25252     # . epilogue
    25253     89/<- %esp 5/r32/ebp
    25254     5d/pop-to-ebp
    25255     c3/return
    25256
    25257 $check-mu-allocate-stmt:error-incorrect-inouts:
    25258     (write-buffered *(ebp+0x10) "fn ")
    25259     8b/-> *(ebp+0xc) 0/r32/eax
    25260     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25261     (write-buffered *(ebp+0x10) %eax)
    25262     (write-buffered *(ebp+0x10) ": stmt 'allocate' must have a single inout\n")
    25263     (flush *(ebp+0x10))
    25264     (stop *(ebp+0x14) 1)
    25265     # never gets here
    25266
    25267 $check-mu-allocate-stmt:error-too-many-outputs:
    25268     (write-buffered *(ebp+0x10) "fn ")
    25269     8b/-> *(ebp+0xc) 0/r32/eax
    25270     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25271     (write-buffered *(ebp+0x10) %eax)
    25272     (write-buffered *(ebp+0x10) ": stmt 'allocate' must not have any outputs\n")
    25273     (flush *(ebp+0x10))
    25274     (stop *(ebp+0x14) 1)
    25275     # never gets here
    25276
    25277 $check-mu-allocate-stmt:error-invalid-type:
    25278     (write-buffered *(ebp+0x10) "fn ")
    25279     8b/-> *(ebp+0xc) 0/r32/eax
    25280     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25281     (write-buffered *(ebp+0x10) %eax)
    25282     (write-buffered *(ebp+0x10) ": stmt allocate: inout '")
    25283     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    25284     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    25285     (write-buffered *(ebp+0x10) %eax)
    25286     (write-buffered *(ebp+0x10) "' must have type (addr handle ...)\n")
    25287     (flush *(ebp+0x10))
    25288     (stop *(ebp+0x14) 1)
    25289     # never gets here
    25290
    25291 check-mu-populate-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    25292     # . prologue
    25293     55/push-ebp
    25294     89/<- %ebp 4/r32/esp
    25295     # . save registers
    25296     50/push-eax
    25297     53/push-ebx
    25298     56/push-esi
    25299     57/push-edi
    25300     # esi = stmt
    25301     8b/-> *(ebp+8) 6/r32/esi
    25302 $check-mu-populate-stmt:check-for-output:
    25303     # if stmt->outputs abort
    25304     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    25305     3d/compare-eax-and 0/imm32
    25306     0f 85/jump-if-!= $check-mu-populate-stmt:error-too-many-outputs/disp32
    25307 $check-mu-populate-stmt:get-target:
    25308     # var target/edi: (addr stmt-var) = stmt->inouts
    25309     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    25310     89/<- %edi 0/r32/eax
    25311     # zero inouts
    25312     3d/compare-eax-and 0/imm32
    25313     0f 84/jump-if-= $check-mu-populate-stmt:error-incorrect-inouts/disp32
    25314 $check-mu-populate-stmt:get-length:
    25315     # var length/esi: (addr stmt-var) = dest->next
    25316     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
    25317     89/<- %esi 0/r32/eax
    25318     # 1 inout
    25319     3d/compare-eax-and 0/imm32
    25320     0f 84/jump-if-= $check-mu-populate-stmt:error-incorrect-inouts/disp32
    25321     # > 2 inouts
    25322     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
    25323     3d/compare-eax-and 0/imm32
    25324     0f 85/jump-if-!= $check-mu-populate-stmt:error-incorrect-inouts/disp32
    25325 $check-mu-populate-stmt:check-target-type:
    25326     # var target-type/ebx: (addr type-tree) = target->value->type
    25327     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    25328     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    25329     89/<- %ebx 0/r32/eax
    25330 $check-mu-populate-stmt:check-target-type-deref:
    25331     # if (target->is-deref?) target-type = target-type->payload
    25332     8b/-> *(edi+0x10) 0/r32/eax  # Stmt-var-is-deref
    25333     3d/compare-eax-and 0/imm32/false
    25334     {
    25335       74/jump-if-= break/disp8
    25336       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
    25337       # if target-type->right is null, target-type = target-type->left
    25338       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
    25339       {
    25340         75/jump-if-!= break/disp8
    25341         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    25342       }
    25343       89/<- %ebx 0/r32/eax
    25344     }
    25345 $check-mu-populate-stmt:check-target-type-addr:
    25346     # if target-type is not addr, abort
    25347     (mu-addr-type? %ebx)  # => eax
    25348     3d/compare-eax-and 0/imm32/false
    25349     0f 84/jump-if-= $check-mu-populate-stmt:error-invalid-target-type/disp32
    25350     # if target-type->right is an atom, abort
    25351     (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
    25352     89/<- %ebx 0/r32/eax
    25353     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
    25354     0f 85/jump-if-!= $check-mu-populate-stmt:error-invalid-target-type/disp32
    25355 $check-mu-populate-stmt:check-target-type-handle:
    25356     # if target-type->right->left is not handle, abort
    25357     (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
    25358     (simple-mu-type? %eax 4)  # handle => eax
    25359     3d/compare-eax-and 0/imm32/false
    25360     0f 84/jump-if-= $check-mu-populate-stmt:error-invalid-target-type/disp32
    25361     # if target-type->right->right is an atom, abort
    25362     (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
    25363     89/<- %ebx 0/r32/eax
    25364     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
    25365     0f 85/jump-if-!= $check-mu-populate-stmt:error-invalid-target-type/disp32
    25366 $check-mu-populate-stmt:check-target-type-array:
    25367     # if target-type->right->right->left is not array, abort
    25368     (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
    25369     (simple-mu-type? %eax 3)  # array => eax
    25370     3d/compare-eax-and 0/imm32/false
    25371     0f 84/jump-if-= $check-mu-populate-stmt:error-invalid-target-type/disp32
    25372 $check-mu-populate-stmt:check-length-type:
    25373     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    25374     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    25375     89/<- %ebx 0/r32/eax
    25376     (simple-mu-type? %ebx 0)  # literal => eax
    25377     3d/compare-eax-and 0/imm32/false
    25378     75/jump-if-!= $check-mu-populate-stmt:end/disp8
    25379     (simple-mu-type? %ebx 1)  # int => eax
    25380     3d/compare-eax-and 0/imm32/false
    25381     0f 84/jump-if-= $check-mu-populate-stmt:error-invalid-length-type/disp32
    25382 $check-mu-populate-stmt:end:
    25383     # . restore registers
    25384     5f/pop-to-edi
    25385     5e/pop-to-esi
    25386     5b/pop-to-ebx
    25387     58/pop-to-eax
    25388     # . epilogue
    25389     89/<- %esp 5/r32/ebp
    25390     5d/pop-to-ebp
    25391     c3/return
    25392
    25393 $check-mu-populate-stmt:error-incorrect-inouts:
    25394     (write-buffered *(ebp+0x10) "fn ")
    25395     8b/-> *(ebp+0xc) 0/r32/eax
    25396     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25397     (write-buffered *(ebp+0x10) %eax)
    25398     (write-buffered *(ebp+0x10) ": stmt 'populate' must have two inouts\n")
    25399     (flush *(ebp+0x10))
    25400     (stop *(ebp+0x14) 1)
    25401     # never gets here
    25402
    25403 $check-mu-populate-stmt:error-too-many-outputs:
    25404     (write-buffered *(ebp+0x10) "fn ")
    25405     8b/-> *(ebp+0xc) 0/r32/eax
    25406     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25407     (write-buffered *(ebp+0x10) %eax)
    25408     (write-buffered *(ebp+0x10) ": stmt 'populate' must not have any outputs\n")
    25409     (flush *(ebp+0x10))
    25410     (stop *(ebp+0x14) 1)
    25411     # never gets here
    25412
    25413 $check-mu-populate-stmt:error-invalid-target-type:
    25414     (write-buffered *(ebp+0x10) "fn ")
    25415     8b/-> *(ebp+0xc) 0/r32/eax
    25416     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25417     (write-buffered *(ebp+0x10) %eax)
    25418     (write-buffered *(ebp+0x10) ": stmt populate: first inout '")
    25419     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    25420     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    25421     (write-buffered *(ebp+0x10) %eax)
    25422     (write-buffered *(ebp+0x10) "' must have type (addr handle array ...)\n")
    25423     (flush *(ebp+0x10))
    25424     (stop *(ebp+0x14) 1)
    25425     # never gets here
    25426
    25427 $check-mu-populate-stmt:error-invalid-length-type:
    25428     (write-buffered *(ebp+0x10) "fn ")
    25429     8b/-> *(ebp+0xc) 0/r32/eax
    25430     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25431     (write-buffered *(ebp+0x10) %eax)
    25432     (write-buffered *(ebp+0x10) ": stmt populate: second inout '")
    25433     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    25434     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    25435     (write-buffered *(ebp+0x10) %eax)
    25436     (write-buffered *(ebp+0x10) "' must be an int\n")
    25437     (flush *(ebp+0x10))
    25438     (stop *(ebp+0x14) 1)
    25439     # never gets here
    25440
    25441 check-mu-populate-stream-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    25442     # . prologue
    25443     55/push-ebp
    25444     89/<- %ebp 4/r32/esp
    25445     # . save registers
    25446     50/push-eax
    25447     53/push-ebx
    25448     56/push-esi
    25449     57/push-edi
    25450     # esi = stmt
    25451     8b/-> *(ebp+8) 6/r32/esi
    25452 $check-mu-populate-stream-stmt:check-for-output:
    25453     # if stmt->outputs abort
    25454     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    25455     3d/compare-eax-and 0/imm32
    25456     0f 85/jump-if-!= $check-mu-populate-stream-stmt:error-too-many-outputs/disp32
    25457 $check-mu-populate-stream-stmt:get-target:
    25458     # var target/edi: (addr stmt-var) = stmt->inouts
    25459     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    25460     89/<- %edi 0/r32/eax
    25461     # zero inouts
    25462     3d/compare-eax-and 0/imm32
    25463     0f 84/jump-if-= $check-mu-populate-stream-stmt:error-incorrect-inouts/disp32
    25464 $check-mu-populate-stream-stmt:get-length:
    25465     # var length/esi: (addr stmt-var) = dest->next
    25466     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
    25467     89/<- %esi 0/r32/eax
    25468     # 1 inout
    25469     3d/compare-eax-and 0/imm32
    25470     0f 84/jump-if-= $check-mu-populate-stream-stmt:error-incorrect-inouts/disp32
    25471     # > 2 inouts
    25472     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
    25473     3d/compare-eax-and 0/imm32
    25474     0f 85/jump-if-!= $check-mu-populate-stream-stmt:error-incorrect-inouts/disp32
    25475 $check-mu-populate-stream-stmt:check-target-type:
    25476     # var target-type/ebx: (addr type-tree) = target->value->type
    25477     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    25478     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    25479     89/<- %ebx 0/r32/eax
    25480 $check-mu-populate-stream-stmt:check-target-type-deref:
    25481     # if (target->is-deref?) target-type = target-type->payload
    25482     8b/-> *(edi+0x10) 0/r32/eax  # Stmt-var-is-deref
    25483     3d/compare-eax-and 0/imm32/false
    25484     {
    25485       74/jump-if-= break/disp8
    25486       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
    25487       # if target-type->right is null, target-type = target-type->left
    25488       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
    25489       {
    25490         75/jump-if-!= break/disp8
    25491         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    25492       }
    25493       89/<- %ebx 0/r32/eax
    25494     }
    25495 $check-mu-populate-stream-stmt:check-target-type-addr:
    25496     # if target-type is not addr, abort
    25497     (mu-addr-type? %ebx)  # => eax
    25498     3d/compare-eax-and 0/imm32/false
    25499     0f 84/jump-if-= $check-mu-populate-stream-stmt:error-invalid-target-type/disp32
    25500     # if target-type->right is an atom, abort
    25501     (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
    25502     89/<- %ebx 0/r32/eax
    25503     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
    25504     0f 85/jump-if-!= $check-mu-populate-stream-stmt:error-invalid-target-type/disp32
    25505 $check-mu-populate-stream-stmt:check-target-type-handle:
    25506     # if target-type->right->left is not handle, abort
    25507     (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
    25508     (simple-mu-type? %eax 4)  # handle => eax
    25509     3d/compare-eax-and 0/imm32/false
    25510     0f 84/jump-if-= $check-mu-populate-stream-stmt:error-invalid-target-type/disp32
    25511     # if target-type->right->right is an atom, abort
    25512     (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
    25513     89/<- %ebx 0/r32/eax
    25514     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
    25515     0f 85/jump-if-!= $check-mu-populate-stream-stmt:error-invalid-target-type/disp32
    25516 $check-mu-populate-stream-stmt:check-target-type-stream:
    25517     # if target-type->right->right->left is not stream, abort
    25518     (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
    25519     (simple-mu-type? %eax 0xb)  # stream => eax
    25520     3d/compare-eax-and 0/imm32/false
    25521     0f 84/jump-if-= $check-mu-populate-stream-stmt:error-invalid-target-type/disp32
    25522 $check-mu-populate-stream-stmt:check-length-type:
    25523     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    25524     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    25525     89/<- %ebx 0/r32/eax
    25526     (simple-mu-type? %ebx 0)  # literal => eax
    25527     3d/compare-eax-and 0/imm32/false
    25528     75/jump-if-!= $check-mu-populate-stream-stmt:end/disp8
    25529     (simple-mu-type? %ebx 1)  # int => eax
    25530     3d/compare-eax-and 0/imm32/false
    25531     0f 84/jump-if-= $check-mu-populate-stream-stmt:error-invalid-length-type/disp32
    25532 $check-mu-populate-stream-stmt:end:
    25533     # . restore registers
    25534     5f/pop-to-edi
    25535     5e/pop-to-esi
    25536     5b/pop-to-ebx
    25537     58/pop-to-eax
    25538     # . epilogue
    25539     89/<- %esp 5/r32/ebp
    25540     5d/pop-to-ebp
    25541     c3/return
    25542
    25543 $check-mu-populate-stream-stmt:error-incorrect-inouts:
    25544     (write-buffered *(ebp+0x10) "fn ")
    25545     8b/-> *(ebp+0xc) 0/r32/eax
    25546     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25547     (write-buffered *(ebp+0x10) %eax)
    25548     (write-buffered *(ebp+0x10) ": stmt 'populate-stream' must have two inouts\n")
    25549     (flush *(ebp+0x10))
    25550     (stop *(ebp+0x14) 1)
    25551     # never gets here
    25552
    25553 $check-mu-populate-stream-stmt:error-too-many-outputs:
    25554     (write-buffered *(ebp+0x10) "fn ")
    25555     8b/-> *(ebp+0xc) 0/r32/eax
    25556     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25557     (write-buffered *(ebp+0x10) %eax)
    25558     (write-buffered *(ebp+0x10) ": stmt 'populate-stream' must not have any outputs\n")
    25559     (flush *(ebp+0x10))
    25560     (stop *(ebp+0x14) 1)
    25561     # never gets here
    25562
    25563 $check-mu-populate-stream-stmt:error-invalid-target-type:
    25564     (write-buffered *(ebp+0x10) "fn ")
    25565     8b/-> *(ebp+0xc) 0/r32/eax
    25566     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25567     (write-buffered *(ebp+0x10) %eax)
    25568     (write-buffered *(ebp+0x10) ": stmt populate-stream: first inout '")
    25569     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    25570     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    25571     (write-buffered *(ebp+0x10) %eax)
    25572     (write-buffered *(ebp+0x10) "' must have type (addr handle stream ...)\n")
    25573     (flush *(ebp+0x10))
    25574     (stop *(ebp+0x14) 1)
    25575     # never gets here
    25576
    25577 $check-mu-populate-stream-stmt:error-invalid-length-type:
    25578     (write-buffered *(ebp+0x10) "fn ")
    25579     8b/-> *(ebp+0xc) 0/r32/eax
    25580     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25581     (write-buffered *(ebp+0x10) %eax)
    25582     (write-buffered *(ebp+0x10) ": stmt populate-stream: second inout '")
    25583     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    25584     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    25585     (write-buffered *(ebp+0x10) %eax)
    25586     (write-buffered *(ebp+0x10) "' must be an int\n")
    25587     (flush *(ebp+0x10))
    25588     (stop *(ebp+0x14) 1)
    25589     # never gets here
    25590
    25591 check-mu-read-from-stream-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    25592     # . prologue
    25593     55/push-ebp
    25594     89/<- %ebp 4/r32/esp
    25595     # . save registers
    25596     50/push-eax
    25597     51/push-ecx
    25598     52/push-edx
    25599     53/push-ebx
    25600     56/push-esi
    25601     57/push-edi
    25602     # esi = stmt
    25603     8b/-> *(ebp+8) 6/r32/esi
    25604     # - check for 0 inouts
    25605     # var base/ecx: (addr var) = stmt->inouts->value
    25606     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    25607 $check-mu-read-from-stream-stmt:check-no-inouts:
    25608     3d/compare-eax-and 0/imm32
    25609     0f 84/jump-if-= $check-mu-read-from-stream-stmt:error-too-few-inouts/disp32
    25610     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    25611     89/<- %ecx 0/r32/eax
    25612     # - check base type is (addr stream T)
    25613     # var base-type/ebx: (addr type-tree) = lookup(base->type)
    25614     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
    25615     89/<- %ebx 0/r32/eax
    25616 $check-mu-read-from-stream-stmt:check-base-is-compound:
    25617     # if base-type is an atom, abort
    25618     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
    25619     0f 85/jump-if-!= $check-mu-read-from-stream-stmt:error-invalid-base-type/disp32
    25620 $check-mu-read-from-stream-stmt:check-base-is-addr:
    25621     # if type->left not addr, abort
    25622     (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
    25623     (simple-mu-type? %eax 2)  # addr => eax
    25624     3d/compare-eax-and 0/imm32/false
    25625     0f 84/jump-if-= $check-mu-read-from-stream-stmt:error-invalid-base-type/disp32
    25626 $check-mu-read-from-stream-stmt:check-base-is-addr-to-stream:
    25627     # base-type = base-type->right
    25628     (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
    25629     89/<- %ebx 0/r32/eax
    25630     # ensure base-type->left == stream
    25631     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    25632     (simple-mu-type? %eax 0xb)  # stream => eax
    25633     3d/compare-eax-and 0/imm32/false
    25634     0f 84/jump-if-= $check-mu-read-from-stream-stmt:error-invalid-base-type/disp32
    25635     # - check target type is (addr T)
    25636     # var target/ecx: (addr stmt-var) = stmt->inouts->next->value
    25637     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    25638     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    25639 $check-mu-read-from-stream-stmt:check-single-inout:
    25640     3d/compare-eax-and 0/imm32
    25641     0f 84/jump-if-= $check-mu-read-from-stream-stmt:error-too-few-inouts/disp32
    25642     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    25643     89/<- %ecx 0/r32/eax
    25644     # var target-type/edx: (addr type-tree)
    25645     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
    25646     89/<- %edx 0/r32/eax
    25647     # if target-type is an atom, it must be a literal or int
    25648 $check-mu-read-from-stream-stmt:check-target-is-compound:
    25649     81 7/subop/compare *edx 0/imm32/false  # Type-tree-is-atom
    25650     0f 85/jump-if-!= $check-mu-read-from-stream-stmt:error-target-type-not-address/disp32
    25651 $check-mu-read-from-stream-stmt:check-target-type:
    25652     # target type must start with (addr ...)
    25653     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
    25654     (simple-mu-type? %eax 2)  # addr => eax
    25655     3d/compare-eax-and 0/imm32/false
    25656     0f 84/jump-if-= $check-mu-read-from-stream-stmt:error-target-type-not-address/disp32
    25657     # if tail(base-type) != tail(target-type) abort
    25658     (type-tail %ebx)  # => eax
    25659     89/<- %ebx 0/r32/eax
    25660     (type-tail %edx)  # => eax
    25661     (type-equal? %ebx %eax)  # => eax
    25662     3d/compare-eax-and 0/imm32/false
    25663     0f 84/jump-if-= $check-mu-read-from-stream-stmt:error-invalid-target-type/disp32
    25664 $check-mu-read-from-stream-stmt:check-too-many-inouts:
    25665     # - check for too many inouts
    25666     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    25667     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    25668     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    25669     3d/compare-eax-and 0/imm32/false
    25670     0f 85/jump-if-!= $check-mu-read-from-stream-stmt:error-too-many-inouts/disp32
    25671 $check-mu-read-from-stream-stmt:check-unexpected-output:
    25672     # - check for any output
    25673     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    25674     3d/compare-eax-and 0/imm32/false
    25675     0f 85/jump-if-!= $check-mu-read-from-stream-stmt:error-unexpected-output/disp32
    25676 $check-mu-read-from-stream-stmt:end:
    25677     # . restore registers
    25678     5f/pop-to-edi
    25679     5e/pop-to-esi
    25680     5b/pop-to-ebx
    25681     5a/pop-to-edx
    25682     59/pop-to-ecx
    25683     58/pop-to-eax
    25684     # . epilogue
    25685     89/<- %esp 5/r32/ebp
    25686     5d/pop-to-ebp
    25687     c3/return
    25688
    25689 $check-mu-read-from-stream-stmt:error-invalid-base-type:
    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: var '")
    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 to a stream\n")
    25698     (flush *(ebp+0x10))
    25699     (stop *(ebp+0x14) 1)
    25700     # never gets here
    25701
    25702 $check-mu-read-from-stream-stmt:error-too-few-inouts:
    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: too few inouts (2 required)\n")
    25708     (flush *(ebp+0x10))
    25709     (stop *(ebp+0x14) 1)
    25710     # never gets here
    25711
    25712 $check-mu-read-from-stream-stmt:error-target-type-not-address:
    25713     (write-buffered *(ebp+0x10) "fn ")
    25714     8b/-> *(ebp+0xc) 0/r32/eax
    25715     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25716     (write-buffered *(ebp+0x10) %eax)
    25717     (write-buffered *(ebp+0x10) ": stmt read-from-stream: target '")
    25718     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    25719     (write-buffered *(ebp+0x10) %eax)
    25720     (write-buffered *(ebp+0x10) "' must be an addr\n")
    25721     (flush *(ebp+0x10))
    25722     (stop *(ebp+0x14) 1)
    25723     # never gets here
    25724
    25725 $check-mu-read-from-stream-stmt:error-invalid-target-type:
    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: second inout '")
    25731     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    25732     (write-buffered *(ebp+0x10) %eax)
    25733     (write-buffered *(ebp+0x10) "' does not have the right type\n")
    25734     (flush *(ebp+0x10))
    25735     (stop *(ebp+0x14) 1)
    25736     # never gets here
    25737
    25738 $check-mu-read-from-stream-stmt:error-too-many-inouts:
    25739     (write-buffered *(ebp+0x10) "fn ")
    25740     8b/-> *(ebp+0xc) 0/r32/eax
    25741     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25742     (write-buffered *(ebp+0x10) %eax)
    25743     (write-buffered *(ebp+0x10) ": stmt read-from-stream: too many inouts (2 required)\n")
    25744     (flush *(ebp+0x10))
    25745     (stop *(ebp+0x14) 1)
    25746     # never gets here
    25747
    25748 $check-mu-read-from-stream-stmt:error-unexpected-output:
    25749     (write-buffered *(ebp+0x10) "fn ")
    25750     8b/-> *(ebp+0xc) 0/r32/eax
    25751     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25752     (write-buffered *(ebp+0x10) %eax)
    25753     (write-buffered *(ebp+0x10) ": stmt read-from-stream: unexpected output\n")
    25754     (flush *(ebp+0x10))
    25755     (stop *(ebp+0x14) 1)
    25756     # never gets here
    25757
    25758 check-mu-write-to-stream-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    25759     # . prologue
    25760     55/push-ebp
    25761     89/<- %ebp 4/r32/esp
    25762     # . save registers
    25763     50/push-eax
    25764     51/push-ecx
    25765     52/push-edx
    25766     53/push-ebx
    25767     56/push-esi
    25768     57/push-edi
    25769     # esi = stmt
    25770     8b/-> *(ebp+8) 6/r32/esi
    25771     # - check for 0 inouts
    25772     # var base/ecx: (addr var) = stmt->inouts->value
    25773     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    25774 $check-mu-write-to-stream-stmt:check-no-inouts:
    25775     3d/compare-eax-and 0/imm32
    25776     0f 84/jump-if-= $check-mu-write-to-stream-stmt:error-too-few-inouts/disp32
    25777     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    25778     89/<- %ecx 0/r32/eax
    25779     # - check base type is (addr stream T)
    25780     # var base-type/ebx: (addr type-tree) = lookup(base->type)
    25781     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
    25782     89/<- %ebx 0/r32/eax
    25783 $check-mu-write-to-stream-stmt:check-base-is-compound:
    25784     # if base-type is an atom, abort
    25785     81 7/subop/compare *ebx 0/imm32/false  # Type-tree-is-atom
    25786     0f 85/jump-if-!= $check-mu-write-to-stream-stmt:error-invalid-base-type/disp32
    25787 $check-mu-write-to-stream-stmt:check-base-is-addr:
    25788     # if type->left not addr, abort
    25789     (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
    25790     (simple-mu-type? %eax 2)  # addr => eax
    25791     3d/compare-eax-and 0/imm32/false
    25792     0f 84/jump-if-= $check-mu-write-to-stream-stmt:error-invalid-base-type/disp32
    25793 $check-mu-write-to-stream-stmt:check-base-is-addr-to-stream:
    25794     # base-type = base-type->right
    25795     (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
    25796     89/<- %ebx 0/r32/eax
    25797     # ensure base-type->left == stream
    25798     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    25799     (simple-mu-type? %eax 0xb)  # stream => eax
    25800     3d/compare-eax-and 0/imm32/false
    25801     0f 84/jump-if-= $check-mu-write-to-stream-stmt:error-invalid-base-type/disp32
    25802     # - check target type is (addr T)
    25803     # var target/ecx: (addr stmt-var) = stmt->inouts->next->value
    25804     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    25805     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    25806 $check-mu-write-to-stream-stmt:check-single-inout:
    25807     3d/compare-eax-and 0/imm32
    25808     0f 84/jump-if-= $check-mu-write-to-stream-stmt:error-too-few-inouts/disp32
    25809     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    25810     89/<- %ecx 0/r32/eax
    25811     # var target-type/edx: (addr type-tree)
    25812     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
    25813     89/<- %edx 0/r32/eax
    25814     # if target-type is an atom, it must be a literal or int
    25815 $check-mu-write-to-stream-stmt:check-target-is-compound:
    25816     81 7/subop/compare *edx 0/imm32/false  # Type-tree-is-atom
    25817     0f 85/jump-if-!= $check-mu-write-to-stream-stmt:error-target-type-not-address/disp32
    25818 $check-mu-write-to-stream-stmt:check-target-type:
    25819     # target type must start with (addr ...)
    25820     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
    25821     (simple-mu-type? %eax 2)  # addr => eax
    25822     3d/compare-eax-and 0/imm32/false
    25823     0f 84/jump-if-= $check-mu-write-to-stream-stmt:error-target-type-not-address/disp32
    25824     # if tail(base-type) != tail(target-type) abort
    25825     (type-tail %ebx)  # => eax
    25826     89/<- %ebx 0/r32/eax
    25827     (type-tail %edx)  # => eax
    25828     (type-equal? %ebx %eax)  # => eax
    25829     3d/compare-eax-and 0/imm32/false
    25830     0f 84/jump-if-= $check-mu-write-to-stream-stmt:error-invalid-target-type/disp32
    25831 $check-mu-write-to-stream-stmt:check-too-many-inouts:
    25832     # - check for too many inouts
    25833     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    25834     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    25835     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    25836     3d/compare-eax-and 0/imm32/false
    25837     0f 85/jump-if-!= $check-mu-write-to-stream-stmt:error-too-many-inouts/disp32
    25838 $check-mu-write-to-stream-stmt:check-unexpected-output:
    25839     # - check for any output
    25840     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    25841     3d/compare-eax-and 0/imm32/false
    25842     0f 85/jump-if-!= $check-mu-write-to-stream-stmt:error-unexpected-output/disp32
    25843 $check-mu-write-to-stream-stmt:end:
    25844     # . restore registers
    25845     5f/pop-to-edi
    25846     5e/pop-to-esi
    25847     5b/pop-to-ebx
    25848     5a/pop-to-edx
    25849     59/pop-to-ecx
    25850     58/pop-to-eax
    25851     # . epilogue
    25852     89/<- %esp 5/r32/ebp
    25853     5d/pop-to-ebp
    25854     c3/return
    25855
    25856 $check-mu-write-to-stream-stmt:error-invalid-base-type:
    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: var '")
    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 to a stream\n")
    25865     (flush *(ebp+0x10))
    25866     (stop *(ebp+0x14) 1)
    25867     # never gets here
    25868
    25869 $check-mu-write-to-stream-stmt:error-too-few-inouts:
    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: too few inouts (2 required)\n")
    25875     (flush *(ebp+0x10))
    25876     (stop *(ebp+0x14) 1)
    25877     # never gets here
    25878
    25879 $check-mu-write-to-stream-stmt:error-target-type-not-address:
    25880     (write-buffered *(ebp+0x10) "fn ")
    25881     8b/-> *(ebp+0xc) 0/r32/eax
    25882     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25883     (write-buffered *(ebp+0x10) %eax)
    25884     (write-buffered *(ebp+0x10) ": stmt write-to-stream: target '")
    25885     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    25886     (write-buffered *(ebp+0x10) %eax)
    25887     (write-buffered *(ebp+0x10) "' must be an addr\n")
    25888     (flush *(ebp+0x10))
    25889     (stop *(ebp+0x14) 1)
    25890     # never gets here
    25891
    25892 $check-mu-write-to-stream-stmt:error-invalid-target-type:
    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: second inout '")
    25898     (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    25899     (write-buffered *(ebp+0x10) %eax)
    25900     (write-buffered *(ebp+0x10) "' does not have the right type\n")
    25901     (flush *(ebp+0x10))
    25902     (stop *(ebp+0x14) 1)
    25903     # never gets here
    25904
    25905 $check-mu-write-to-stream-stmt:error-too-many-inouts:
    25906     (write-buffered *(ebp+0x10) "fn ")
    25907     8b/-> *(ebp+0xc) 0/r32/eax
    25908     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25909     (write-buffered *(ebp+0x10) %eax)
    25910     (write-buffered *(ebp+0x10) ": stmt write-to-stream: too many inouts (2 required)\n")
    25911     (flush *(ebp+0x10))
    25912     (stop *(ebp+0x14) 1)
    25913     # never gets here
    25914
    25915 $check-mu-write-to-stream-stmt:error-unexpected-output:
    25916     (write-buffered *(ebp+0x10) "fn ")
    25917     8b/-> *(ebp+0xc) 0/r32/eax
    25918     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    25919     (write-buffered *(ebp+0x10) %eax)
    25920     (write-buffered *(ebp+0x10) ": stmt write-to-stream: unexpected output\n")
    25921     (flush *(ebp+0x10))
    25922     (stop *(ebp+0x14) 1)
    25923     # never gets here
    25924
    25925 check-mu-convert-stmt:  # stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    25926     # . prologue
    25927     55/push-ebp
    25928     89/<- %ebp 4/r32/esp
    25929     # . save registers
    25930     50/push-eax
    25931     51/push-ecx
    25932     52/push-edx
    25933     56/push-esi
    25934     57/push-edi
    25935 $check-mu-convert-stmt:get-output:
    25936     # esi = stmt
    25937     8b/-> *(ebp+8) 6/r32/esi
    25938     # var output/edi: (addr stmt-var) = stmt->outputs
    25939     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    25940     89/<- %edi 0/r32/eax
    25941     # zero outputs
    25942     3d/compare-eax-and 0/imm32
    25943     0f 84/jump-if-= $check-mu-convert-stmt:error-no-output/disp32
    25944     # > 1 output
    25945     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
    25946     3d/compare-eax-and 0/imm32
    25947     0f 85/jump-if-!= $check-mu-convert-stmt:error-too-many-outputs/disp32
    25948 $check-mu-convert-stmt:get-inout:
    25949     # var inout/esi: (addr stmt-var) = stmt->inouts
    25950     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    25951     89/<- %esi 0/r32/eax
    25952     # zero inouts
    25953     3d/compare-eax-and 0/imm32
    25954     0f 84/jump-if-= $check-mu-convert-stmt:error-no-inout/disp32
    25955     # > 1 inout
    25956     (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
    25957     3d/compare-eax-and 0/imm32
    25958     0f 85/jump-if-!= $check-mu-convert-stmt:error-too-many-inouts/disp32
    25959 $check-mu-convert-stmt:types:
    25960     # var inout-type/ecx: (addr type-tree) = inout->value->type
    25961     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    25962     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    25963     89/<- %ecx 0/r32/eax
    25964     # if (inout->is-deref?) inout-type = inout-type->payload
    25965     8b/-> *(esi+0x10) 0/r32/eax  # Stmt-var-is-deref
    25966     3d/compare-eax-and 0/imm32/false
    25967     {
    25968       74/jump-if-= break/disp8
    25969       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
    25970       # if inout-type->right is null, t = inout-type->left
    25971       81 7/subop/compare *(eax+0xc) 0/imm32  # Type-tree-right
    25972       {
    25973         75/jump-if-!= break/disp8
    25974         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    25975       }
    25976       89/<- %ecx 0/r32/eax
    25977     }
    25978     # if input is not int or float, abort
    25979     {
    25980       (simple-mu-type? %ecx 1)  # int => eax
    25981       3d/compare-eax-and 0/imm32/false
    25982       75/jump-if-!= break/disp8
    25983       (simple-mu-type? %ecx 0xf)  # float => eax
    25984       3d/compare-eax-and 0/imm32/false
    25985       75/jump-if-!= break/disp8
    25986       e9/jump $check-mu-convert-stmt:error-invalid-inout-type/disp32
    25987     }
    25988     # if output not in register, abort
    25989     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    25990     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    25991     3d/compare-eax-and 0/imm32
    25992     0f 84/jump-if-= $check-mu-convert-stmt:error-output-not-in-register/disp32
    25993     # var output-type/edx: (addr type-tree) = output->value->type
    25994     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    25995     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    25996     89/<- %edx 0/r32/eax
    25997     # if output is not int or float, abort
    25998     {
    25999       (simple-mu-type? %edx 1)  # int => eax
    26000       3d/compare-eax-and 0/imm32/false
    26001       75/jump-if-!= break/disp8
    26002       (simple-mu-type? %edx 0xf)  # float => eax
    26003       3d/compare-eax-and 0/imm32/false
    26004       75/jump-if-!= break/disp8
    26005       e9/jump $check-mu-convert-stmt:error-invalid-output-type/disp32
    26006     }
    26007     # if both are ints, abort
    26008     {
    26009       (simple-mu-type? %edx 1)  # int => eax
    26010       3d/compare-eax-and 0/imm32/false
    26011       74/jump-if-= break/disp8
    26012       (simple-mu-type? %ecx 1)  # int => eax
    26013       3d/compare-eax-and 0/imm32/false
    26014       74/jump-if-= break/disp8
    26015       e9/jump $check-mu-convert-stmt:error-int-to-int/disp32
    26016     }
    26017     # if both are floats, abort
    26018     {
    26019       (simple-mu-type? %edx 0xf)  # float => eax
    26020       3d/compare-eax-and 0/imm32/false
    26021       74/jump-if-= break/disp8
    26022       (simple-mu-type? %ecx 0xf)  # float => eax
    26023       3d/compare-eax-and 0/imm32/false
    26024       74/jump-if-= break/disp8
    26025       e9/jump $check-mu-convert-stmt:error-float-to-float/disp32
    26026     }
    26027 $check-mu-convert-stmt:end:
    26028     # . restore registers
    26029     5f/pop-to-edi
    26030     5e/pop-to-esi
    26031     5a/pop-to-edx
    26032     59/pop-to-ecx
    26033     58/pop-to-eax
    26034     # . epilogue
    26035     89/<- %esp 5/r32/ebp
    26036     5d/pop-to-ebp
    26037     c3/return
    26038
    26039 $check-mu-convert-stmt:error-no-inout:
    26040     (write-buffered *(ebp+0x10) "fn ")
    26041     8b/-> *(ebp+0xc) 0/r32/eax
    26042     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    26043     (write-buffered *(ebp+0x10) %eax)
    26044     (write-buffered *(ebp+0x10) ": stmt 'convert' expects an inout\n")
    26045     (flush *(ebp+0x10))
    26046     (stop *(ebp+0x14) 1)
    26047     # never gets here
    26048
    26049 $check-mu-convert-stmt:error-too-many-inouts:
    26050     (write-buffered *(ebp+0x10) "fn ")
    26051     8b/-> *(ebp+0xc) 0/r32/eax
    26052     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    26053     (write-buffered *(ebp+0x10) %eax)
    26054     (write-buffered *(ebp+0x10) ": stmt 'convert' must have just one inout\n")
    26055     (flush *(ebp+0x10))
    26056     (stop *(ebp+0x14) 1)
    26057     # never gets here
    26058
    26059 $check-mu-convert-stmt:error-no-output:
    26060     (write-buffered *(ebp+0x10) "fn ")
    26061     8b/-> *(ebp+0xc) 0/r32/eax
    26062     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    26063     (write-buffered *(ebp+0x10) %eax)
    26064     (write-buffered *(ebp+0x10) ": stmt 'convert' expects an output\n")
    26065     (flush *(ebp+0x10))
    26066     (stop *(ebp+0x14) 1)
    26067     # never gets here
    26068
    26069 $check-mu-convert-stmt:error-output-not-in-register:
    26070     (write-buffered *(ebp+0x10) "fn ")
    26071     8b/-> *(ebp+0xc) 0/r32/eax
    26072     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    26073     (write-buffered *(ebp+0x10) %eax)
    26074     (write-buffered *(ebp+0x10) ": stmt convert: output '")
    26075     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    26076     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    26077     (write-buffered *(ebp+0x10) %eax)
    26078     (write-buffered *(ebp+0x10) "' not in a register\n")
    26079     (flush *(ebp+0x10))
    26080     (stop *(ebp+0x14) 1)
    26081     # never gets here
    26082
    26083 $check-mu-convert-stmt:error-too-many-outputs:
    26084     (write-buffered *(ebp+0x10) "fn ")
    26085     8b/-> *(ebp+0xc) 0/r32/eax
    26086     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    26087     (write-buffered *(ebp+0x10) %eax)
    26088     (write-buffered *(ebp+0x10) ": stmt 'convert' must have just one output\n")
    26089     (flush *(ebp+0x10))
    26090     (stop *(ebp+0x14) 1)
    26091     # never gets here
    26092
    26093 $check-mu-convert-stmt:error-invalid-inout-type:
    26094     (write-buffered *(ebp+0x10) "fn ")
    26095     8b/-> *(ebp+0xc) 0/r32/eax
    26096     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    26097     (write-buffered *(ebp+0x10) %eax)
    26098     (write-buffered *(ebp+0x10) ": stmt convert: inout '")
    26099     (lookup *esi *(esi+4))  # Stmt-var-value Stmt-var-value => eax
    26100     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    26101     (write-buffered *(ebp+0x10) %eax)
    26102     (write-buffered *(ebp+0x10) "' must be an int or float\n")
    26103     (flush *(ebp+0x10))
    26104     (stop *(ebp+0x14) 1)
    26105     # never gets here
    26106
    26107 $check-mu-convert-stmt:error-invalid-output-type:
    26108     (write-buffered *(ebp+0x10) "fn ")
    26109     8b/-> *(ebp+0xc) 0/r32/eax
    26110     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    26111     (write-buffered *(ebp+0x10) %eax)
    26112     (write-buffered *(ebp+0x10) ": stmt convert: output '")
    26113     (lookup *edi *(edi+4))  # Stmt-var-value Stmt-var-value => eax
    26114     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    26115     (write-buffered *(ebp+0x10) %eax)
    26116     (write-buffered *(ebp+0x10) "' must be an int or float\n")
    26117     (flush *(ebp+0x10))
    26118     (stop *(ebp+0x14) 1)
    26119     # never gets here
    26120
    26121 $check-mu-convert-stmt:error-int-to-int:
    26122     (write-buffered *(ebp+0x10) "fn ")
    26123     8b/-> *(ebp+0xc) 0/r32/eax
    26124     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    26125     (write-buffered *(ebp+0x10) %eax)
    26126     (write-buffered *(ebp+0x10) ": stmt convert: no need to convert int to int\n")
    26127     (flush *(ebp+0x10))
    26128     (stop *(ebp+0x14) 1)
    26129     # never gets here
    26130
    26131 $check-mu-convert-stmt:error-float-to-float:
    26132     (write-buffered *(ebp+0x10) "fn ")
    26133     8b/-> *(ebp+0xc) 0/r32/eax
    26134     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    26135     (write-buffered *(ebp+0x10) %eax)
    26136     (write-buffered *(ebp+0x10) ": stmt convert: no need to convert float to float\n")
    26137     (flush *(ebp+0x10))
    26138     (stop *(ebp+0x14) 1)
    26139     # never gets here
    26140
    26141 check-mu-call:  # stmt: (addr stmt), callee: (addr function), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    26142     # . prologue
    26143     55/push-ebp
    26144     89/<- %ebp 4/r32/esp
    26145     # var type-parameters: (addr table (handle array byte) (addr type-tree) 8)
    26146     68/push 0/imm32
    26147     # var type-parameters-storage: (table (handle array byte) (addr type-tree) 8)
    26148     81 5/subop/subtract %esp 0x60/imm32
    26149     68/push 0x60/imm32/size
    26150     68/push 0/imm32/read
    26151     68/push 0/imm32/write
    26152     # save a pointer to type-parameters-storage at type-parameters
    26153     89/<- *(ebp-4) 4/r32/esp
    26154     (clear-stream *(ebp-4))
    26155     # . save registers
    26156     50/push-eax
    26157     51/push-ecx
    26158     52/push-edx
    26159     53/push-ebx
    26160     56/push-esi
    26161     57/push-edi
    26162     # esi = stmt
    26163     8b/-> *(ebp+8) 6/r32/esi
    26164     # edi = callee
    26165     8b/-> *(ebp+0xc) 7/r32/edi
    26166     # var inouts/ecx: (addr stmt-var) = lookup(stmt->inouts)
    26167     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    26168     89/<- %ecx 0/r32/eax
    26169     # var expected/edx: (addr list var) = lookup(f->inouts)
    26170     (lookup *(edi+8) *(edi+0xc))  # Function-inouts Function-inouts => eax
    26171     89/<- %edx 0/r32/eax
    26172     {
    26173 $check-mu-call:check-for-inouts:
    26174       # if (inouts == 0) break
    26175       81 7/subop/compare %ecx 0/imm32
    26176       0f 84/jump-if-= break/disp32
    26177       # if (expected == 0) error
    26178       81 7/subop/compare %edx 0/imm32
    26179       0f 84/jump-if-= break/disp32
    26180 $check-mu-call:check-null-addr:
    26181       # if (inouts->value->name == "0") continue
    26182       (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
    26183       (lookup *eax *(eax+4))  # Var-name Var-name => eax
    26184       (string-equal? %eax "0")  # => eax
    26185       3d/compare-eax-and 0/imm32/false
    26186       0f 85/jump-if-!= $check-mu-call:continue-to-next-inout/disp32
    26187 $check-mu-call:check-inout-type:
    26188       # var t/ebx: (addr type-tree) = inouts->value->type
    26189       (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
    26190       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    26191       89/<- %ebx 0/r32/eax
    26192       # if (inouts->is-deref?) t = t->right
    26193       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
    26194       {
    26195         74/jump-if-= break/disp8
    26196         (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
    26197         89/<- %ebx 0/r32/eax
    26198         # if t->right is null, t = t->left
    26199         81 7/subop/compare *(ebx+0xc) 0/imm32  # Type-tree-right
    26200         75/jump-if-!= break/disp8
    26201         (lookup *(ebx+4) *(ebx+8))  # Type-tree-left Type-tree-left => eax
    26202         89/<- %ebx 0/r32/eax
    26203       }
    26204       # var v2/eax: (addr v) = lookup(expected->value)
    26205       (lookup *edx *(edx+4))  # List-value List-value => eax
    26206       # var t2/eax: (addr type-tree) = lookup(v2->type)
    26207       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    26208       # if (t != t2) error
    26209       (type-match? %eax %ebx *(ebp-4))  # => eax
    26210       3d/compare-eax-and 0/imm32/false
    26211       {
    26212         0f 85/jump-if-!= break/disp32
    26213         (write-buffered *(ebp+0x14) "fn ")
    26214         8b/-> *(ebp+0x10) 0/r32/eax
    26215         (lookup *eax *(eax+4))  # Function-name Function-name => eax
    26216         (write-buffered *(ebp+0x14) %eax)
    26217         (write-buffered *(ebp+0x14) ": call ")
    26218         (lookup *edi *(edi+4))  # Function-name Function-name => eax
    26219         (write-buffered *(ebp+0x14) %eax)
    26220         (write-buffered *(ebp+0x14) ": type for inout '")
    26221         (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
    26222         (lookup *eax *(eax+4))  # Var-name Var-name => eax
    26223         (write-buffered *(ebp+0x14) %eax)
    26224         (write-buffered *(ebp+0x14) "' is not right\n")
    26225         (flush *(ebp+0x14))
    26226         (stop *(ebp+0x18) 1)
    26227       }
    26228 $check-mu-call:continue-to-next-inout:
    26229       # inouts = lookup(inouts->next)
    26230       (lookup *(ecx+8) *(ecx+0xc))  # Stmt-var-next Stmt-var-next => eax
    26231       89/<- %ecx 0/r32/eax
    26232       # expected = lookup(expected->next)
    26233       (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
    26234       89/<- %edx 0/r32/eax
    26235       #
    26236       e9/jump loop/disp32
    26237     }
    26238 $check-mu-call:check-inout-count:
    26239     # if (inouts == expected) proceed
    26240     39/compare %ecx 2/r32/edx
    26241     {
    26242       0f 84/jump-if-= break/disp32
    26243       # exactly one of the two is null
    26244       # if (inouts == 0) error("too many inouts")
    26245       {
    26246         81 7/subop/compare %ecx 0/imm32
    26247         0f 84/jump-if-= break/disp32
    26248         (write-buffered *(ebp+0x14) "fn ")
    26249         8b/-> *(ebp+0x10) 0/r32/eax
    26250         (lookup *eax *(eax+4))  # Function-name Function-name => eax
    26251         (write-buffered *(ebp+0x14) %eax)
    26252         (write-buffered *(ebp+0x14) ": call ")
    26253         (lookup *edi *(edi+4))  # Function-name Function-name => eax
    26254         (write-buffered *(ebp+0x14) %eax)
    26255         (write-buffered *(ebp+0x14) ": too many inouts\n")
    26256         (flush *(ebp+0x14))
    26257         (stop *(ebp+0x18) 1)
    26258       }
    26259       # if (expected == 0) error("too few inouts")
    26260       {
    26261         81 7/subop/compare %edx 0/imm32
    26262         0f 84/jump-if-= break/disp32
    26263         (write-buffered *(ebp+0x14) "fn ")
    26264         8b/-> *(ebp+0x10) 0/r32/eax
    26265         (lookup *eax *(eax+4))  # Function-name Function-name => eax
    26266         (write-buffered *(ebp+0x14) %eax)
    26267         (write-buffered *(ebp+0x14) ": call ")
    26268         (lookup *edi *(edi+4))  # Function-name Function-name => eax
    26269         (write-buffered *(ebp+0x14) %eax)
    26270         (write-buffered *(ebp+0x14) ": too few inouts\n")
    26271         (flush *(ebp+0x14))
    26272         (stop *(ebp+0x18) 1)
    26273       }
    26274     }
    26275 $check-mu-call:check-outputs:
    26276     # var outputs/ecx: (addr stmt-var) = lookup(stmt->outputs)
    26277     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    26278     89/<- %ecx 0/r32/eax
    26279     # var expected/edx: (addr list var) = lookup(f->outputs)
    26280     (lookup *(edi+0x10) *(edi+0x14))  # Function-outputs Function-outputs => eax
    26281     89/<- %edx 0/r32/eax
    26282     {
    26283 $check-mu-call:check-for-outputs:
    26284       # if (outputs == 0) break
    26285       81 7/subop/compare %ecx 0/imm32
    26286       0f 84/jump-if-= break/disp32
    26287       # if (expected == 0) error
    26288       81 7/subop/compare %edx 0/imm32
    26289       0f 84/jump-if-= break/disp32
    26290 $check-mu-call:check-output-type:
    26291       # var v/eax: (addr v) = lookup(outputs->value)
    26292       (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
    26293       # var t/ebx: (addr type-tree) = lookup(v->type)
    26294       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    26295       89/<- %ebx 0/r32/eax
    26296       # if (outputs->is-deref?) t = t->right  # TODO: check that t->left is an addr
    26297       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
    26298       {
    26299         74/jump-if-= break/disp8
    26300         (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
    26301         89/<- %ebx 0/r32/eax
    26302       }
    26303       # var v2/eax: (addr v) = lookup(expected->value)
    26304       (lookup *edx *(edx+4))  # List-value List-value => eax
    26305       # var t2/eax: (addr type-tree) = lookup(v2->type)
    26306       (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    26307       # if (t != t2) error
    26308       (type-match? %eax %ebx *(ebp-4))  # => eax
    26309       3d/compare-eax-and 0/imm32/false
    26310       {
    26311         0f 85/jump-if-!= break/disp32
    26312         (write-buffered *(ebp+0x14) "fn ")
    26313         8b/-> *(ebp+0x10) 0/r32/eax
    26314         (lookup *eax *(eax+4))  # Function-name Function-name => eax
    26315         (write-buffered *(ebp+0x14) %eax)
    26316         (write-buffered *(ebp+0x14) ": call ")
    26317         (lookup *edi *(edi+4))  # Function-name Function-name => eax
    26318         (write-buffered *(ebp+0x14) %eax)
    26319         (write-buffered *(ebp+0x14) ": type for output '")
    26320         (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
    26321         (lookup *eax *(eax+4))  # Var-name Var-name => eax
    26322         (write-buffered *(ebp+0x14) %eax)
    26323         (write-buffered *(ebp+0x14) "' is not right\n")
    26324         (flush *(ebp+0x14))
    26325         (stop *(ebp+0x18) 1)
    26326       }
    26327 $check-mu-call:check-output-register:
    26328       # var v/eax: (addr v) = lookup(outputs->value)
    26329       (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
    26330       # var r/ebx: (addr array byte) = lookup(v->register)
    26331       (lookup *(eax+18) *(eax+0x1c))  # Var-register Var-register => eax
    26332       89/<- %ebx 0/r32/eax
    26333       # if (r == 0) error
    26334       3d/compare-eax-and 0/imm32
    26335       {
    26336         0f 85/jump-if-!= break/disp32
    26337         (write-buffered *(ebp+0x14) "fn ")
    26338         8b/-> *(ebp+0x10) 0/r32/eax
    26339         (lookup *eax *(eax+4))  # Function-name Function-name => eax
    26340         (write-buffered *(ebp+0x14) %eax)
    26341         (write-buffered *(ebp+0x14) ": call ")
    26342         (lookup *edi *(edi+4))  # Function-name Function-name => eax
    26343         (write-buffered *(ebp+0x14) %eax)
    26344         (write-buffered *(ebp+0x14) ": output '")
    26345         (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
    26346         (lookup *eax *(eax+4))  # Var-name Var-name => eax
    26347         (write-buffered *(ebp+0x14) %eax)
    26348         (write-buffered *(ebp+0x14) "' is not in a register\n")
    26349         (flush *(ebp+0x14))
    26350         (stop *(ebp+0x18) 1)
    26351       }
    26352       # var v2/eax: (addr v) = lookup(expected->value)
    26353       (lookup *edx *(edx+4))  # Stmt-var-value Stmt-var-value => eax
    26354       # var r2/eax: (addr array byte) = lookup(v2->register)
    26355       (lookup *(eax+18) *(eax+0x1c))  # Var-register Var-register => eax
    26356       # if (r != r2) error
    26357       (string-equal? %eax %ebx)  # => eax
    26358       3d/compare-eax-and 0/imm32/false
    26359       {
    26360         0f 85/jump-if-!= break/disp32
    26361         (write-buffered *(ebp+0x14) "fn ")
    26362         8b/-> *(ebp+0x10) 0/r32/eax
    26363         (lookup *eax *(eax+4))  # Function-name Function-name => eax
    26364         (write-buffered *(ebp+0x14) %eax)
    26365         (write-buffered *(ebp+0x14) ": call ")
    26366         (lookup *edi *(edi+4))  # Function-name Function-name => eax
    26367         (write-buffered *(ebp+0x14) %eax)
    26368         (write-buffered *(ebp+0x14) ": register for output '")
    26369         (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
    26370         (lookup *eax *(eax+4))  # Var-name Var-name => eax
    26371         (write-buffered *(ebp+0x14) %eax)
    26372         (write-buffered *(ebp+0x14) "' is not right\n")
    26373         (flush *(ebp+0x14))
    26374         (stop *(ebp+0x18) 1)
    26375       }
    26376 $check-mu-call:continue-to-next-output:
    26377       # outputs = lookup(outputs->next)
    26378       (lookup *(ecx+8) *(ecx+0xc))  # Stmt-var-next Stmt-var-next => eax
    26379       89/<- %ecx 0/r32/eax
    26380       # expected = lookup(expected->next)
    26381       (lookup *(edx+8) *(edx+0xc))  # List-next List-next => eax
    26382       89/<- %edx 0/r32/eax
    26383       #
    26384       e9/jump loop/disp32
    26385     }
    26386 $check-mu-call:check-output-count:
    26387     # if (outputs == expected) proceed
    26388     39/compare %ecx 2/r32/edx
    26389     {
    26390       0f 84/jump-if-= break/disp32
    26391       # exactly one of the two is null
    26392       # if (outputs == 0) error("too many outputs")
    26393       {
    26394         81 7/subop/compare %ecx 0/imm32
    26395         0f 84/jump-if-= break/disp32
    26396         (write-buffered *(ebp+0x14) "fn ")
    26397         8b/-> *(ebp+0x10) 0/r32/eax
    26398         (lookup *eax *(eax+4))  # Function-name Function-name => eax
    26399         (write-buffered *(ebp+0x14) %eax)
    26400         (write-buffered *(ebp+0x14) ": call ")
    26401         (lookup *edi *(edi+4))  # Function-name Function-name => eax
    26402         (write-buffered *(ebp+0x14) %eax)
    26403         (write-buffered *(ebp+0x14) ": too many outputs\n")
    26404         (flush *(ebp+0x14))
    26405         (stop *(ebp+0x18) 1)
    26406       }
    26407       # if (expected == 0) error("too few outputs")
    26408       {
    26409         81 7/subop/compare %edx 0/imm32
    26410         0f 84/jump-if-= break/disp32
    26411         (write-buffered *(ebp+0x14) "fn ")
    26412         8b/-> *(ebp+0x10) 0/r32/eax
    26413         (lookup *eax *(eax+4))  # Function-name Function-name => eax
    26414         (write-buffered *(ebp+0x14) %eax)
    26415         (write-buffered *(ebp+0x14) ": call ")
    26416         (lookup *edi *(edi+4))  # Function-name Function-name => eax
    26417         (write-buffered *(ebp+0x14) %eax)
    26418         (write-buffered *(ebp+0x14) ": too few outputs\n")
    26419         (flush *(ebp+0x14))
    26420         (stop *(ebp+0x18) 1)
    26421       }
    26422     }
    26423 $check-mu-call:end:
    26424     # . restore registers
    26425     5f/pop-to-edi
    26426     5e/pop-to-esi
    26427     5b/pop-to-ebx
    26428     5a/pop-to-edx
    26429     59/pop-to-ecx
    26430     58/pop-to-eax
    26431     # . reclaim locals exclusively on the stack
    26432     81 0/subop/add %esp 0x70/imm32
    26433     # . epilogue
    26434     89/<- %esp 5/r32/ebp
    26435     5d/pop-to-ebp
    26436     c3/return
    26437
    26438 # like type-equal? but takes literals type parameters into account
    26439 type-match?:  # def: (addr type-tree), call: (addr type-tree), type-parameters: (addr table (handle array byte) (addr type-tree)) -> result/eax: boolean
    26440     # . prologue
    26441     55/push-ebp
    26442     89/<- %ebp 4/r32/esp
    26443     # if call is literal and def is numberlike, return true
    26444     {
    26445 $type-match?:check-literal-int:
    26446       (simple-mu-type? *(ebp+0xc) 0)  # literal => eax
    26447       3d/compare-eax-and 0/imm32/false
    26448       74/jump-if-= break/disp8
    26449       (mu-numberlike-output? *(ebp+8))  # => eax
    26450       3d/compare-eax-and 0/imm32/false
    26451       74/jump-if-= break/disp8
    26452       b8/copy-to-eax 1/imm32/true
    26453       e9/jump $type-match?:end/disp32
    26454     }
    26455     # if call is literal-string, match against (addr array byte)
    26456     {
    26457 $type-match?:check-literal-string:
    26458       (simple-mu-type? *(ebp+0xc) 0x10)  # literal-string => eax
    26459       3d/compare-eax-and 0/imm32/false
    26460       74/jump-if-= break/disp8
    26461       (type-component-match? *(ebp+8) Addr-type-string *(ebp+0x10))  # => eax
    26462       e9/jump $type-match?:end/disp32
    26463     }
    26464 $type-match?:baseline:
    26465     # otherwise fall back
    26466     (type-component-match? *(ebp+8) *(ebp+0xc) *(ebp+0x10))  # => eax
    26467 $type-match?:end:
    26468     # . epilogue
    26469     89/<- %esp 5/r32/ebp
    26470     5d/pop-to-ebp
    26471     c3/return
    26472
    26473 type-component-match?:  # def: (addr type-tree), call: (addr type-tree), type-parameters: (addr table (handle array byte) (addr type-tree)) -> result/eax: boolean
    26474     # . prologue
    26475     55/push-ebp
    26476     89/<- %ebp 4/r32/esp
    26477     # . save registers
    26478     51/push-ecx
    26479     52/push-edx
    26480     53/push-ebx
    26481     # ecx = def
    26482     8b/-> *(ebp+8) 1/r32/ecx
    26483     # edx = call
    26484     8b/-> *(ebp+0xc) 2/r32/edx
    26485 $type-component-match?:compare-addr:
    26486     # if (def == call) return true
    26487     8b/-> %ecx 0/r32/eax  # Var-type
    26488     39/compare %edx 0/r32/eax  # Var-type
    26489     b8/copy-to-eax 1/imm32/true
    26490     0f 84/jump-if-= $type-component-match?:end/disp32
    26491     # if (def == 0) return false
    26492     b8/copy-to-eax 0/imm32/false
    26493     81 7/subop/compare %ecx 0/imm32  # Type-tree-is-atom
    26494     0f 84/jump-if-= $type-component-match?:end/disp32
    26495     # if (call == 0) return false
    26496     81 7/subop/compare %edx 0/imm32  # Type-tree-is-atom
    26497     0f 84/jump-if-= $type-component-match?:end/disp32
    26498     # if def is a type parameter, just check in type-parameters
    26499     {
    26500 $type-component-match?:check-type-parameter:
    26501       81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
    26502       74/jump-if-= break/disp8
    26503       81 7/subop/compare *(ecx+4) 0xa/imm32/type-parameter  # Type-tree-value
    26504       75/jump-if-!= break/disp8
    26505 $type-component-match?:type-parameter:
    26506       (type-parameter-match? *(ecx+8) *(ecx+0xc)  %edx  *(ebp+0x10))  # => eax
    26507       e9/jump $type-component-match?:end/disp32
    26508     }
    26509     # if def is a list containing just a type parameter, just check in type-parameters
    26510     {
    26511 $type-component-match?:check-list-type-parameter:
    26512       # if def is a list..
    26513       81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
    26514       75/jump-if-!= break/disp8
    26515       #   ..that's a singleton
    26516       81 7/subop/compare *(ecx+0xc) 0/imm32  # Type-tree-left
    26517       75/jump-if-!= break/disp8
    26518       #   ..and whose head is a type parameter
    26519       (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
    26520       81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
    26521       74/jump-if-= break/disp8
    26522       81 7/subop/compare *(eax+4) 0xa/imm32/type-parameter  # Type-tree-value
    26523       75/jump-if-!= break/disp8
    26524 $type-component-match?:list-type-parameter:
    26525       (type-parameter-match? *(eax+8) *(eax+0xc)  %edx  *(ebp+0x10))  # => eax
    26526       e9/jump $type-component-match?:end/disp32
    26527     }
    26528 $type-component-match?:compare-atom-state:
    26529     # if (def->is-atom? != call->is-atom?) return false
    26530     8b/-> *ecx 3/r32/ebx  # Type-tree-is-atom
    26531     39/compare *edx 3/r32/ebx  # Type-tree-is-atom
    26532     b8/copy-to-eax 0/imm32/false
    26533     0f 85/jump-if-!= $type-component-match?:end/disp32
    26534     # if def->is-atom? return (def->value == call->value)
    26535     {
    26536 $type-component-match?:check-atom:
    26537       81 7/subop/compare %ebx 0/imm32/false
    26538       74/jump-if-= break/disp8
    26539 $type-component-match?:is-atom:
    26540       8b/-> *(ecx+4) 0/r32/eax  # Type-tree-value
    26541       39/compare *(edx+4) 0/r32/eax  # Type-tree-value
    26542       0f 94/set-if-= %al
    26543       25/and-eax-with 0xff/imm32
    26544       e9/jump $type-component-match?:end/disp32
    26545     }
    26546 $type-component-match?:check-left:
    26547     # if (!type-component-match?(def->left, call->left)) return false
    26548     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
    26549     89/<- %ebx 0/r32/eax
    26550     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
    26551     (type-component-match? %ebx %eax *(ebp+0x10))  # => eax
    26552     3d/compare-eax-and 0/imm32/false
    26553     74/jump-if-= $type-component-match?:end/disp8
    26554 $type-component-match?:check-right:
    26555     # return type-component-match?(def->right, call->right)
    26556     (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
    26557     89/<- %ebx 0/r32/eax
    26558     (lookup *(edx+0xc) *(edx+0x10))  # Type-tree-right Type-tree-right => eax
    26559     (type-component-match? %ebx %eax *(ebp+0x10))  # => eax
    26560 $type-component-match?:end:
    26561     # . restore registers
    26562     5b/pop-to-ebx
    26563     5a/pop-to-edx
    26564     59/pop-to-ecx
    26565     # . epilogue
    26566     89/<- %esp 5/r32/ebp
    26567     5d/pop-to-ebp
    26568     c3/return
    26569
    26570 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
    26571     # . prologue
    26572     55/push-ebp
    26573     89/<- %ebp 4/r32/esp
    26574     # . save registers
    26575     51/push-ecx
    26576     #
    26577     (get-or-insert-handle *(ebp+0x14)  *(ebp+8) *(ebp+0xc)  0xc)  # => eax
    26578     # if parameter wasn't saved, save it
    26579     {
    26580       81 7/subop/compare *eax 0/imm32
    26581       75/jump-if-!= break/disp8
    26582       8b/-> *(ebp+0x10) 1/r32/ecx
    26583       89/<- *eax 1/r32/ecx
    26584     }
    26585     #
    26586     (type-equal? *(ebp+0x10) *eax)  # => eax
    26587 $type-parameter-match?:end:
    26588     # . restore registers
    26589     59/pop-to-ecx
    26590     # . epilogue
    26591     89/<- %esp 5/r32/ebp
    26592     5d/pop-to-ebp
    26593     c3/return
    26594
    26595 size-of:  # v: (addr var) -> result/eax: int
    26596     # . prologue
    26597     55/push-ebp
    26598     89/<- %ebp 4/r32/esp
    26599     # . save registers
    26600     51/push-ecx
    26601     # var t/ecx: (addr type-tree) = lookup(v->type)
    26602     8b/-> *(ebp+8) 1/r32/ecx
    26603 #?     (write-buffered Stderr "size-of ")
    26604 #?     (write-int32-hex-buffered Stderr %ecx)
    26605 #?     (write-buffered Stderr Newline)
    26606 #?     (write-buffered Stderr "type allocid: ")
    26607 #?     (write-int32-hex-buffered Stderr *(ecx+8))
    26608 #?     (write-buffered Stderr Newline)
    26609 #?     (flush Stderr)
    26610     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
    26611     89/<- %ecx 0/r32/eax
    26612     # if mu-array?(t) return size-of-array(t)
    26613     {
    26614       (mu-array? %ecx)  # => eax
    26615       3d/compare-eax-and 0/imm32/false
    26616       74/jump-if-= break/disp8
    26617       (size-of-array %ecx)  # => eax
    26618       eb/jump $size-of:end/disp8
    26619     }
    26620     # if mu-stream?(t) return size-of-stream(t)
    26621     {
    26622       (mu-stream? %ecx)  # => eax
    26623       3d/compare-eax-and 0/imm32/false
    26624       74/jump-if-= break/disp8
    26625       (size-of-stream %ecx)  # => eax
    26626       eb/jump $size-of:end/disp8
    26627     }
    26628     # if (!t->is-atom?) t = lookup(t->left)
    26629     {
    26630       81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
    26631       75/jump-if-!= break/disp8
    26632       (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
    26633       89/<- %ecx 0/r32/eax
    26634     }
    26635     # TODO: assert t->is-atom?
    26636     (size-of-type-id *(ecx+4))  # Type-tree-value => eax
    26637 $size-of:end:
    26638     # . restore registers
    26639     59/pop-to-ecx
    26640     # . epilogue
    26641     89/<- %esp 5/r32/ebp
    26642     5d/pop-to-ebp
    26643     c3/return
    26644
    26645 size-of-deref:  # v: (addr var) -> result/eax: int
    26646     # . prologue
    26647     55/push-ebp
    26648     89/<- %ebp 4/r32/esp
    26649     # . save registers
    26650     51/push-ecx
    26651     # var t/ecx: (addr type-tree) = lookup(v->type)
    26652     8b/-> *(ebp+8) 1/r32/ecx
    26653     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
    26654     89/<- %ecx 0/r32/eax
    26655     # TODO: assert(t is an addr)
    26656     # t = lookup(t->right)
    26657     (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
    26658     89/<- %ecx 0/r32/eax
    26659     # if mu-array?(t) return size-of-array(t)
    26660     {
    26661       (mu-array? %ecx)  # => eax
    26662       3d/compare-eax-and 0/imm32/false
    26663       74/jump-if-= break/disp8
    26664       (size-of-array %ecx)  # => eax
    26665       eb/jump $size-of-deref:end/disp8
    26666     }
    26667     # if mu-stream?(t) return size-of-stream(t)
    26668     {
    26669       (mu-stream? %ecx)  # => eax
    26670       3d/compare-eax-and 0/imm32/false
    26671       74/jump-if-= break/disp8
    26672       (size-of-stream %ecx)  # => eax
    26673       eb/jump $size-of-deref:end/disp8
    26674     }
    26675     # if (!t->is-atom?) t = lookup(t->left)
    26676     {
    26677       81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
    26678       75/jump-if-!= break/disp8
    26679       (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
    26680       89/<- %ecx 0/r32/eax
    26681     }
    26682     # TODO: assert t->is-atom?
    26683     (size-of-type-id *(ecx+4))  # Type-tree-value => eax
    26684 $size-of-deref:end:
    26685     # . restore registers
    26686     59/pop-to-ecx
    26687     # . epilogue
    26688     89/<- %esp 5/r32/ebp
    26689     5d/pop-to-ebp
    26690     c3/return
    26691
    26692 mu-array?:  # t: (addr type-tree) -> result/eax: boolean
    26693     # . prologue
    26694     55/push-ebp
    26695     89/<- %ebp 4/r32/esp
    26696     # . save registers
    26697     51/push-ecx
    26698     # ecx = t
    26699     8b/-> *(ebp+8) 1/r32/ecx
    26700     # if t->is-atom?, return false
    26701     81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
    26702     75/jump-if-!= $mu-array?:return-false/disp8
    26703     # if !t->left->is-atom?, return false
    26704     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
    26705     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
    26706     74/jump-if-= $mu-array?:return-false/disp8
    26707     # return t->left->value == array
    26708     81 7/subop/compare *(eax+4) 3/imm32/array-type-id  # Type-tree-value
    26709     0f 94/set-if-= %al
    26710     25/and-eax-with 0xff/imm32
    26711     eb/jump $mu-array?:end/disp8
    26712 $mu-array?:return-false:
    26713     b8/copy-to-eax 0/imm32/false
    26714 $mu-array?:end:
    26715     # . restore registers
    26716     59/pop-to-ecx
    26717     # . epilogue
    26718     89/<- %esp 5/r32/ebp
    26719     5d/pop-to-ebp
    26720     c3/return
    26721
    26722 # size of a statically allocated array where the size is part of the type expression
    26723 size-of-array:  # a: (addr type-tree) -> result/eax: int
    26724     # . prologue
    26725     55/push-ebp
    26726     89/<- %ebp 4/r32/esp
    26727     # . save registers
    26728     51/push-ecx
    26729     52/push-edx
    26730     #
    26731     8b/-> *(ebp+8) 1/r32/ecx
    26732     # TODO: assert that a->left is 'array'
    26733     (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
    26734     89/<- %ecx 0/r32/eax
    26735     # var elem-type/edx: type-id = a->right->left->value
    26736     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
    26737     8b/-> *(eax+4) 2/r32/edx  # Type-tree-value
    26738     # TODO: assert that a->right->right->left->value == size
    26739     # var array-size/ecx: int = a->right->right->left->value-size
    26740     (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
    26741     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    26742     8b/-> *(eax+8) 1/r32/ecx  # Type-tree-value-size
    26743     # return 4 + array-size * size-of(elem-type)
    26744     (size-of-type-id-as-array-element %edx)  # => eax
    26745     f7 4/subop/multiply-into-edx-eax %ecx
    26746     05/add-to-eax 4/imm32  # for array size
    26747     # TODO: check edx for overflow
    26748 $size-of-array:end:
    26749     # . restore registers
    26750     5a/pop-to-edx
    26751     59/pop-to-ecx
    26752     # . epilogue
    26753     89/<- %esp 5/r32/ebp
    26754     5d/pop-to-ebp
    26755     c3/return
    26756
    26757 mu-stream?:  # t: (addr type-tree) -> result/eax: boolean
    26758     # . prologue
    26759     55/push-ebp
    26760     89/<- %ebp 4/r32/esp
    26761     # . save registers
    26762     51/push-ecx
    26763     # ecx = t
    26764     8b/-> *(ebp+8) 1/r32/ecx
    26765     # if t->is-atom?, return false
    26766     81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
    26767     75/jump-if-!= $mu-stream?:return-false/disp8
    26768     # if !t->left->is-atom?, return false
    26769     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
    26770     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
    26771     74/jump-if-= $mu-stream?:return-false/disp8
    26772     # return t->left->value == stream
    26773     81 7/subop/compare *(eax+4) 0xb/imm32/stream-type-id  # Type-tree-value
    26774     0f 94/set-if-= %al
    26775     25/and-eax-with 0xff/imm32
    26776     eb/jump $mu-stream?:end/disp8
    26777 $mu-stream?:return-false:
    26778     b8/copy-to-eax 0/imm32/false
    26779 $mu-stream?:end:
    26780     # . restore registers
    26781     59/pop-to-ecx
    26782     # . epilogue
    26783     89/<- %esp 5/r32/ebp
    26784     5d/pop-to-ebp
    26785     c3/return
    26786
    26787 # size of a statically allocated stream where the size is part of the type expression
    26788 size-of-stream:  # a: (addr type-tree) -> result/eax: int
    26789     # . prologue
    26790     55/push-ebp
    26791     89/<- %ebp 4/r32/esp
    26792     #
    26793     (size-of-array *(ebp+8))  # assumes we ignore the actual type name 'array' in the type
    26794     05/add-to-eax 8/imm32  # for read/write pointers
    26795 $size-of-stream:end:
    26796     # . epilogue
    26797     89/<- %esp 5/r32/ebp
    26798     5d/pop-to-ebp
    26799     c3/return
    26800
    26801 size-of-type-id:  # t: type-id -> result/eax: int
    26802     # . prologue
    26803     55/push-ebp
    26804     89/<- %ebp 4/r32/esp
    26805     # . save registers
    26806     51/push-ecx
    26807     # var out/ecx: (handle typeinfo)
    26808     68/push 0/imm32
    26809     68/push 0/imm32
    26810     89/<- %ecx 4/r32/esp
    26811     # eax = t
    26812     8b/-> *(ebp+8) 0/r32/eax
    26813     # if t is a literal, return 0
    26814     3d/compare-eax-and 0/imm32
    26815     0f 84/jump-if-= $size-of-type-id:end/disp32  # eax changes type from type-id to int
    26816     # if t is a byte, return 4 (because we don't really support non-multiples of 4)
    26817     3d/compare-eax-and 8/imm32/byte
    26818     {
    26819       75/jump-if-!= break/disp8
    26820       b8/copy-to-eax 4/imm32
    26821       eb/jump $size-of-type-id:end/disp8
    26822     }
    26823     # if t is a handle, return 8
    26824     3d/compare-eax-and 4/imm32/handle
    26825     {
    26826       75/jump-if-!= break/disp8
    26827       b8/copy-to-eax 8/imm32
    26828       eb/jump $size-of-type-id:end/disp8  # eax changes type from type-id to int
    26829     }
    26830     # if t is a slice, return 8
    26831     3d/compare-eax-and 0xc/imm32/slice
    26832     {
    26833       75/jump-if-!= break/disp8
    26834       b8/copy-to-eax 8/imm32
    26835       eb/jump $size-of-type-id:end/disp8  # eax changes type from type-id to int
    26836     }
    26837     # if t is a user-defined type, return its size
    26838     # TODO: support non-atom type
    26839     (find-typeinfo %eax %ecx)
    26840     {
    26841       81 7/subop/compare *ecx 0/imm32
    26842       74/jump-if-= break/disp8
    26843 $size-of-type-id:user-defined:
    26844       (lookup *ecx *(ecx+4))  # => eax
    26845       8b/-> *(eax+0xc) 0/r32/eax  # Typeinfo-total-size-in-bytes
    26846       eb/jump $size-of-type-id:end/disp8
    26847     }
    26848     # otherwise return the word size
    26849     b8/copy-to-eax 4/imm32
    26850 $size-of-type-id:end:
    26851     # . reclaim locals
    26852     81 0/subop/add %esp 8/imm32
    26853     # . restore registers
    26854     59/pop-to-ecx
    26855     # . epilogue
    26856     89/<- %esp 5/r32/ebp
    26857     5d/pop-to-ebp
    26858     c3/return
    26859
    26860 # Minor violation of our type system since it returns an addr. But we could
    26861 # replace it with a handle some time.
    26862 # Returns null if t is an atom.
    26863 type-tail:  # t: (addr type-tree) -> out/eax: (addr type-tree)
    26864     # . prologue
    26865     55/push-ebp
    26866     89/<- %ebp 4/r32/esp
    26867     # . save registers
    26868     51/push-ecx
    26869     # eax = 0
    26870     b8/copy-to-eax 0/imm32
    26871     # ecx = t
    26872     8b/-> *(ebp+8) 1/r32/ecx
    26873 $type-tail:check-atom:
    26874     # if t->is-atom? return 0
    26875     81 7/subop/compare *ecx 0/imm32/false  # Type-tree-is-atom
    26876     0f 85/jump-if-!= $type-tail:end/disp32
    26877     # var tail = t->right
    26878     (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
    26879     89/<- %ecx 0/r32/eax
    26880 $type-tail:check-singleton:
    26881     # if (tail->right == 0) return tail->left
    26882     {
    26883       81 7/subop/compare *(ecx+0xc) 0/imm32  # Type-tree-right
    26884       75/jump-if-!= break/disp8
    26885       (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
    26886       e9/jump $type-tail:end/disp32
    26887     }
    26888     # if tail->right->left is an array-capacity, return tail->left
    26889     {
    26890 $type-tail:check-array-capacity:
    26891       (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
    26892       81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
    26893       75/jump-if-!= break/disp8
    26894 $type-tail:check-array-capacity-1:
    26895       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    26896       3d/compare-eax-and 0/imm32
    26897       74/jump-if-= break/disp8
    26898 $type-tail:check-array-capacity-2:
    26899       (simple-mu-type? %eax 9)  # array-capacity => eax
    26900       3d/compare-eax-and 0/imm32/false
    26901       74/jump-if-= break/disp8
    26902 $type-tail:array-capacity:
    26903       (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
    26904       eb/jump $type-tail:end/disp8
    26905     }
    26906 $type-tail:check-compound-left:
    26907     # if !tail->left->is-atom? return tail->left
    26908     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
    26909     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
    26910     74/jump-if-= $type-tail:end/disp8
    26911 $type-tail:return-tail:
    26912     # return tail
    26913     89/<- %eax 1/r32/ecx
    26914 $type-tail:end:
    26915     # . restore registers
    26916     59/pop-to-ecx
    26917     # . epilogue
    26918     89/<- %esp 5/r32/ebp
    26919     5d/pop-to-ebp
    26920     c3/return
    26921
    26922 type-equal?:  # a: (addr type-tree), b: (addr type-tree) -> result/eax: boolean
    26923     # . prologue
    26924     55/push-ebp
    26925     89/<- %ebp 4/r32/esp
    26926     # . save registers
    26927     51/push-ecx
    26928     52/push-edx
    26929     53/push-ebx
    26930     # ecx = a
    26931     8b/-> *(ebp+8) 1/r32/ecx
    26932     # edx = b
    26933     8b/-> *(ebp+0xc) 2/r32/edx
    26934 $type-equal?:compare-addr:
    26935     # if (a == b) return true
    26936     8b/-> %ecx 0/r32/eax  # Var-type
    26937     39/compare %edx 0/r32/eax  # Var-type
    26938     b8/copy-to-eax 1/imm32/true
    26939     0f 84/jump-if-= $type-equal?:end/disp32
    26940 $type-equal?:compare-null-a:
    26941     # if (a == 0) return false
    26942     b8/copy-to-eax 0/imm32/false
    26943     81 7/subop/compare %ecx 0/imm32
    26944     0f 84/jump-if-= $type-equal?:end/disp32
    26945 $type-equal?:compare-null-b:
    26946     # if (b == 0) return false
    26947     81 7/subop/compare %edx 0/imm32
    26948     0f 84/jump-if-= $type-equal?:end/disp32
    26949 $type-equal?:compare-atom-state:
    26950     # if (a->is-atom? != b->is-atom?) return false
    26951     8b/-> *ecx 3/r32/ebx  # Type-tree-is-atom
    26952     39/compare *edx 3/r32/ebx  # Type-tree-is-atom
    26953     b8/copy-to-eax 0/imm32/false
    26954     0f 85/jump-if-!= $type-equal?:end/disp32
    26955     # if a->is-atom? return (a->value == b->value)
    26956     {
    26957 $type-equal?:check-atom:
    26958       81 7/subop/compare %ebx 0/imm32/false
    26959       74/jump-if-= break/disp8
    26960 $type-equal?:is-atom:
    26961       8b/-> *(ecx+4) 0/r32/eax  # Type-tree-value
    26962       39/compare *(edx+4) 0/r32/eax  # Type-tree-value
    26963       0f 94/set-if-= %al
    26964       25/and-eax-with 0xff/imm32
    26965       e9/jump $type-equal?:end/disp32
    26966     }
    26967 $type-equal?:check-left:
    26968     # if (!type-equal?(a->left, b->left)) return false
    26969     (lookup *(ecx+4) *(ecx+8))  # Type-tree-left Type-tree-left => eax
    26970     89/<- %ebx 0/r32/eax
    26971     (lookup *(edx+4) *(edx+8))  # Type-tree-left Type-tree-left => eax
    26972     (type-equal? %eax %ebx)  # => eax
    26973     3d/compare-eax-and 0/imm32/false
    26974     74/jump-if-= $type-equal?:end/disp8
    26975 $type-equal?:check-right:
    26976     # return type-equal?(a->right, b->right)
    26977     (lookup *(ecx+0xc) *(ecx+0x10))  # Type-tree-right Type-tree-right => eax
    26978     89/<- %ebx 0/r32/eax
    26979     (lookup *(edx+0xc) *(edx+0x10))  # Type-tree-right Type-tree-right => eax
    26980     (type-equal? %eax %ebx)  # => eax
    26981 $type-equal?:end:
    26982     # . restore registers
    26983     5b/pop-to-ebx
    26984     5a/pop-to-edx
    26985     59/pop-to-ecx
    26986     # . epilogue
    26987     89/<- %esp 5/r32/ebp
    26988     5d/pop-to-ebp
    26989     c3/return
    26990
    26991 #######################################################
    26992 # Code-generation
    26993 #######################################################
    26994
    26995 == data
    26996
    26997 # Global state added to each var record when performing code-generation.
    26998 Curr-local-stack-offset:  # (addr int)
    26999     0/imm32
    27000
    27001 == code
    27002
    27003 # We may not need to pass err/ed everywhere here. I think they're relics of Mu
    27004 # getting type checks later in life.
    27005 # But we do need them for runtime checks, particularly array index bounds checks.
    27006 # So perhaps it's not worth taking them out. They're a safety net.
    27007
    27008 emit-subx:  # out: (addr buffered-file), err: (addr buffered-file), ed: (addr exit-descriptor)
    27009     # . prologue
    27010     55/push-ebp
    27011     89/<- %ebp 4/r32/esp
    27012     # . save registers
    27013     50/push-eax
    27014     # var curr/eax: (addr function) = *Program->functions
    27015     (lookup *_Program-functions *_Program-functions->payload)  # => eax
    27016     {
    27017       # if (curr == null) break
    27018       3d/compare-eax-and 0/imm32
    27019       0f 84/jump-if-= break/disp32
    27020       (emit-subx-function *(ebp+8) %eax *(ebp+0xc) *(ebp+0x10))
    27021       # curr = lookup(curr->next)
    27022       (lookup *(eax+0x20) *(eax+0x24))  # Function-next Function-next => eax
    27023       e9/jump loop/disp32
    27024     }
    27025 $emit-subx:end:
    27026     # . restore registers
    27027     58/pop-to-eax
    27028     # . epilogue
    27029     89/<- %esp 5/r32/ebp
    27030     5d/pop-to-ebp
    27031     c3/return
    27032
    27033 emit-subx-function:  # out: (addr buffered-file), f: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    27034     # . prologue
    27035     55/push-ebp
    27036     89/<- %ebp 4/r32/esp
    27037     # some preprocessing
    27038     (populate-mu-type-offsets-in-inouts *(ebp+0xc))
    27039     # . save registers
    27040     50/push-eax
    27041     51/push-ecx
    27042     52/push-edx
    27043     # initialize some global state
    27044     c7 0/subop/copy *Curr-block-depth 1/imm32  # Important: keep this in sync with the parse phase
    27045     c7 0/subop/copy *Curr-local-stack-offset 0/imm32
    27046     # ecx = f
    27047     8b/-> *(ebp+0xc) 1/r32/ecx
    27048     # var vars/edx: (stack (addr var) 256)
    27049     81 5/subop/subtract %esp 0xc00/imm32
    27050     68/push 0xc00/imm32/size
    27051     68/push 0/imm32/top
    27052     89/<- %edx 4/r32/esp
    27053     # var name/eax: (addr array byte) = lookup(f->name)
    27054     (lookup *ecx *(ecx+4))  # Function-name Function-name => eax
    27055     #
    27056     (write-buffered *(ebp+8) %eax)
    27057     (write-buffered *(ebp+8) ":\n")
    27058     (emit-subx-prologue *(ebp+8))
    27059     # var body/eax: (addr block) = lookup(f->body)
    27060     (lookup *(ecx+0x18) *(ecx+0x1c))  # Function-body Function-body => eax
    27061     #
    27062     (emit-subx-block *(ebp+8) %eax %edx *(ebp+0xc) *(ebp+0x10) *(ebp+0x14))
    27063     (emit-subx-epilogue *(ebp+8))
    27064     # TODO: validate that *Curr-block-depth and *Curr-local-stack-offset have
    27065     # been cleaned up
    27066 $emit-subx-function:end:
    27067     # . reclaim locals
    27068     81 0/subop/add %esp 0xc08/imm32
    27069     # . restore registers
    27070     5a/pop-to-edx
    27071     59/pop-to-ecx
    27072     58/pop-to-eax
    27073     # . epilogue
    27074     89/<- %esp 5/r32/ebp
    27075     5d/pop-to-ebp
    27076     c3/return
    27077
    27078 populate-mu-type-offsets-in-inouts:  # f: (addr function)
    27079     # . prologue
    27080     55/push-ebp
    27081     89/<- %ebp 4/r32/esp
    27082     # . save registers
    27083     50/push-eax
    27084     51/push-ecx
    27085     52/push-edx
    27086     53/push-ebx
    27087     57/push-edi
    27088     # var next-offset/edx: int = 8
    27089     ba/copy-to-edx 8/imm32
    27090     # var curr/ecx: (addr list var) = lookup(f->inouts)
    27091     8b/-> *(ebp+8) 1/r32/ecx
    27092     (lookup *(ecx+8) *(ecx+0xc))  # Function-inouts Function-inouts => eax
    27093     89/<- %ecx 0/r32/eax
    27094     {
    27095 $populate-mu-type-offsets-in-inouts:loop:
    27096       81 7/subop/compare %ecx 0/imm32
    27097       74/jump-if-= break/disp8
    27098       # var v/ebx: (addr var) = lookup(curr->value)
    27099       (lookup *ecx *(ecx+4))  # List-value List-value => eax
    27100       89/<- %ebx 0/r32/eax
    27101 #?       (lookup *ebx *(ebx+4))
    27102 #?       (write-buffered Stderr "setting offset of fn inout ")
    27103 #?       (write-buffered Stderr %eax)
    27104 #?       (write-buffered Stderr "@")
    27105 #?       (write-int32-hex-buffered Stderr %ebx)
    27106 #?       (write-buffered Stderr " to ")
    27107 #?       (write-int32-hex-buffered Stderr %edx)
    27108 #?       (write-buffered Stderr Newline)
    27109 #?       (flush Stderr)
    27110       # v->offset = next-offset
    27111       89/<- *(ebx+0x14) 2/r32/edx  # Var-offset
    27112       # next-offset += size-of(v)
    27113       (size-of %ebx)  # => eax
    27114       01/add-to %edx 0/r32/eax
    27115       # curr = lookup(curr->next)
    27116       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
    27117       89/<- %ecx 0/r32/eax
    27118       #
    27119       eb/jump loop/disp8
    27120     }
    27121 $populate-mu-type-offsets-in-inouts:end:
    27122     # . restore registers
    27123     5f/pop-to-edi
    27124     5b/pop-to-ebx
    27125     5a/pop-to-edx
    27126     59/pop-to-ecx
    27127     58/pop-to-eax
    27128     # . epilogue
    27129     89/<- %esp 5/r32/ebp
    27130     5d/pop-to-ebp
    27131     c3/return
    27132
    27133 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)
    27134     # . prologue
    27135     55/push-ebp
    27136     89/<- %ebp 4/r32/esp
    27137     # . save registers
    27138     50/push-eax
    27139     51/push-ecx
    27140     53/push-ebx
    27141     56/push-esi
    27142     # esi = stmts
    27143     8b/-> *(ebp+0xc) 6/r32/esi
    27144     #
    27145     {
    27146 $emit-subx-stmt-list:loop:
    27147       81 7/subop/compare %esi 0/imm32
    27148       0f 84/jump-if-= break/disp32
    27149       # var curr-stmt/ecx: (addr stmt) = lookup(stmts->value)
    27150       (lookup *esi *(esi+4))  # List-value List-value => eax
    27151       89/<- %ecx 0/r32/eax
    27152       {
    27153 $emit-subx-stmt-list:check-for-block:
    27154         81 7/subop/compare *ecx 0/imm32/block  # Stmt-tag
    27155         75/jump-if-!= break/disp8
    27156 $emit-subx-stmt-list:block:
    27157         (emit-subx-block *(ebp+8) %ecx *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
    27158       }
    27159       {
    27160 $emit-subx-stmt-list:check-for-stmt:
    27161         81 7/subop/compare *ecx 1/imm32/stmt1  # Stmt-tag
    27162         0f 85/jump-if-!= break/disp32
    27163 $emit-subx-stmt-list:stmt1:
    27164         {
    27165           (mu-branch? %ecx)  # => eax
    27166           3d/compare-eax-and 0/imm32/false
    27167           0f 84/jump-if-= break/disp32
    27168 $emit-subx-stmt-list:branch-stmt:
    27169 +-- 25 lines: # unconditional return ---------------------------------------------------------------------------------------------------------------------------------------
    27194 +-- 27 lines: # unconditional loops ----------------------------------------------------------------------------------------------------------------------------------------
    27221 +-- 16 lines: # unconditional breaks ---------------------------------------------------------------------------------------------------------------------------------------
    27237 +-- 38 lines: # simple conditional branches without a target ---------------------------------------------------------------------------------------------------------------
    27275 +-- 19 lines: # conditional branches with an explicit target ---------------------------------------------------------------------------------------------------------------
    27294         }
    27295 $emit-subx-stmt-list:1-to-1:
    27296         (emit-subx-stmt *(ebp+8) %ecx Primitives *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
    27297         e9/jump $emit-subx-stmt-list:continue/disp32
    27298       }
    27299       {
    27300 $emit-subx-stmt-list:check-for-var-def:
    27301         81 7/subop/compare *ecx 2/imm32/var-def  # Stmt-tag
    27302         75/jump-if-!= break/disp8
    27303 $emit-subx-stmt-list:var-def:
    27304         (emit-subx-var-def *(ebp+8) %ecx *(ebp+0x18) *(ebp+0x1c))
    27305         (push *(ebp+0x10) *(ecx+4))  # Vardef-var
    27306         (push *(ebp+0x10) *(ecx+8))  # Vardef-var
    27307         (push *(ebp+0x10) 0)  # Live-var-register-spilled = 0 for vars on the stack
    27308         #
    27309         eb/jump $emit-subx-stmt-list:continue/disp8
    27310       }
    27311       {
    27312 $emit-subx-stmt-list:check-for-reg-var-def:
    27313         81 7/subop/compare *ecx 3/imm32/reg-var-def  # Stmt-tag
    27314         0f 85/jump-if-!= break/disp32
    27315 $emit-subx-stmt-list:reg-var-def:
    27316         # TODO: ensure that there's exactly one output
    27317         (push-output-and-maybe-emit-spill *(ebp+8) %ecx *(ebp+0x10) %esi *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
    27318         # emit the instruction as usual
    27319         (emit-subx-stmt *(ebp+8) %ecx Primitives *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
    27320         #
    27321         eb/jump $emit-subx-stmt-list:continue/disp8
    27322       }
    27323 $emit-subx-stmt-list:continue:
    27324       # TODO: raise an error on unrecognized Stmt-tag
    27325       (lookup *(esi+8) *(esi+0xc))  # List-next List-next => eax
    27326       89/<- %esi 0/r32/eax
    27327       e9/jump loop/disp32
    27328     }
    27329 $emit-subx-stmt-list:emit-cleanup:
    27330     (emit-cleanup-code-until-depth *(ebp+8) *(ebp+0x10) *Curr-block-depth)
    27331 $emit-subx-stmt-list:clean-up:
    27332     (clean-up-stack-offset-state *(ebp+0x10) *Curr-block-depth)
    27333     (clean-up-blocks *(ebp+0x10) *Curr-block-depth *(ebp+0x14))
    27334 $emit-subx-stmt-list:end:
    27335     # . restore registers
    27336     5e/pop-to-esi
    27337     5b/pop-to-ebx
    27338     59/pop-to-ecx
    27339     58/pop-to-eax
    27340     # . epilogue
    27341     89/<- %esp 5/r32/ebp
    27342     5d/pop-to-ebp
    27343     c3/return
    27344
    27345 # 'later-stmts' includes 'stmt', but will behave the same even without it; reg-var-def stmts are guaranteed not to write to function outputs.
    27346 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)
    27347     # . prologue
    27348     55/push-ebp
    27349     89/<- %ebp 4/r32/esp
    27350     # . save registers
    27351     50/push-eax
    27352     51/push-ecx
    27353     52/push-edx
    27354     # ecx = stmt
    27355     8b/-> *(ebp+0xc) 1/r32/ecx
    27356     # var sv/eax: (addr stmt-var) = lookup(curr-stmt->outputs)
    27357     (lookup *(ecx+0x14) *(ecx+0x18))  # Regvardef-outputs Regvardef-outputs => eax
    27358     # TODO: assert !sv->is-deref?
    27359     # var v/ecx: (addr var) = lookup(sv->value)
    27360     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    27361     89/<- %ecx 0/r32/eax
    27362     # v->block-depth = *Curr-block-depth
    27363     8b/-> *Curr-block-depth 0/r32/eax
    27364     89/<- *(ecx+0x10) 0/r32/eax  # Var-block-depth
    27365 #?     (write-buffered Stderr "var ")
    27366 #?     (lookup *ecx *(ecx+4))
    27367 #?     (write-buffered Stderr %eax)
    27368 #?     (write-buffered Stderr " at depth ")
    27369 #?     (write-int32-hex-buffered Stderr *(ecx+0x10))
    27370 #?     (write-buffered Stderr Newline)
    27371 #?     (flush Stderr)
    27372     # ensure that v is in a register
    27373     81 7/subop/compare *(ecx+0x18) 0/imm32  # Var-register
    27374     0f 84/jump-if-= $push-output-and-maybe-emit-spill:abort/disp32
    27375     # var emit-spill?/edx: boolean = not-yet-spilled-this-block? && will-not-write-some-register?(fn)
    27376     (not-yet-spilled-this-block? %ecx *(ebp+0x10))  # => eax
    27377     89/<- %edx 0/r32/eax
    27378     3d/compare-eax-and 0/imm32/false
    27379     0f 84/jump-if-= $push-output-and-maybe-emit-spill:push/disp32
    27380     (will-not-write-some-register? %ecx *(ebp+0x14) *(ebp+0x18))  # => eax
    27381     89/<- %edx 0/r32/eax
    27382     # check emit-spill?
    27383     3d/compare-eax-and 0/imm32/false
    27384     0f 84/jump-if-= $push-output-and-maybe-emit-spill:push/disp32
    27385     # TODO: assert(size-of(output) == 4)
    27386     # *Curr-local-stack-offset -= 4
    27387     81 5/subop/subtract *Curr-local-stack-offset 4/imm32
    27388     # emit spill
    27389     (lookup *(ecx+0x18) *(ecx+0x1c))  # Var-register Var-register => eax
    27390     (emit-push-register *(ebp+8) %eax)
    27391 $push-output-and-maybe-emit-spill:push:
    27392     8b/-> *(ebp+0xc) 1/r32/ecx
    27393     (lookup *(ecx+0x14) *(ecx+0x18))  # Regvardef-outputs Regvardef-outputs => eax
    27394     # push(vars, {sv->value, emit-spill?})
    27395     (push *(ebp+0x10) *eax)  # Stmt-var-value
    27396     (push *(ebp+0x10) *(eax+4))  # Stmt-var-value
    27397     (push *(ebp+0x10) %edx)
    27398 $push-output-and-maybe-emit-spill:end:
    27399     # . restore registers
    27400     5a/pop-to-edx
    27401     59/pop-to-ecx
    27402     58/pop-to-eax
    27403     # . epilogue
    27404     89/<- %esp 5/r32/ebp
    27405     5d/pop-to-ebp
    27406     c3/return
    27407
    27408 $push-output-and-maybe-emit-spill:abort:
    27409     # error("var '" var->name "' initialized from an instruction must live in a register\n")
    27410     (write-buffered *(ebp+0x1c) "var '")
    27411     (write-buffered *(ebp+0x1c) *eax)  # Var-name
    27412     (write-buffered *(ebp+0x1c) "' initialized from an instruction must live in a register\n")
    27413     (flush *(ebp+0x1c))
    27414     (stop *(ebp+0x20) 1)
    27415     # never gets here
    27416
    27417 emit-subx-cleanup-and-unconditional-nonlocal-branch:  # out: (addr buffered-file), stmt: (addr stmt1), vars: (addr stack live-var)
    27418     # . prologue
    27419     55/push-ebp
    27420     89/<- %ebp 4/r32/esp
    27421     # . save registers
    27422     50/push-eax
    27423     51/push-ecx
    27424     # ecx = stmt
    27425     8b/-> *(ebp+0xc) 1/r32/ecx
    27426     # var target/eax: (addr array byte) = curr-stmt->inouts->value->name
    27427     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    27428     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    27429     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    27430     # clean up until target block
    27431     (emit-cleanup-code-until-target *(ebp+8) *(ebp+0x10) %eax)
    27432     # emit jump to target block
    27433     (emit-indent *(ebp+8) *Curr-block-depth)
    27434     (write-buffered *(ebp+8) "e9/jump ")
    27435     (write-buffered *(ebp+8) %eax)
    27436     (lookup *(ecx+4) *(ecx+8))  # Stmt1-operation Stmt1-operation => eax
    27437     (string-starts-with? %eax "break")
    27438     3d/compare-eax-and 0/imm32/false
    27439     {
    27440       74/jump-if-= break/disp8
    27441       (write-buffered *(ebp+8) ":break/disp32\n")
    27442       eb/jump $emit-subx-cleanup-and-unconditional-nonlocal-branch:end/disp8
    27443     }
    27444     (write-buffered *(ebp+8) ":loop/disp32\n")
    27445 $emit-subx-cleanup-and-unconditional-nonlocal-branch:end:
    27446     # . restore registers
    27447     59/pop-to-ecx
    27448     58/pop-to-eax
    27449     # . epilogue
    27450     89/<- %esp 5/r32/ebp
    27451     5d/pop-to-ebp
    27452     c3/return
    27453
    27454 emit-outputs:  # out: (addr buffered-file), return-stmt: (addr stmt1), fn: (addr function)
    27455     # . prologue
    27456     55/push-ebp
    27457     89/<- %ebp 4/r32/esp
    27458     # . save registers
    27459     50/push-eax
    27460     51/push-ecx
    27461     56/push-esi
    27462     57/push-edi
    27463     # var curr-inout/esi: (addr stmt-var) = return-stmt->inouts
    27464     8b/-> *(ebp+0xc) 0/r32/eax
    27465     (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    27466     89/<- %esi 0/r32/eax
    27467     # var curr-output/edi: (addr list var) = fn->outputs
    27468     8b/-> *(ebp+0x10) 0/r32/eax
    27469     (lookup *(eax+0x10) *(eax+0x14))  # Function-outputs Function-outputs => eax
    27470     89/<- %edi 0/r32/eax
    27471     {
    27472 $emit-outputs:loop:
    27473       81 7/subop/compare %esi 0/imm32
    27474       0f 84/jump-if-= break/disp32
    27475       # emit copy to output register
    27476       # var curr-output-register/ecx: (addr array byte) = curr-output->value->register
    27477       (lookup *edi *(edi+4))  # List-value List-value => eax
    27478       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    27479       89/<- %ecx 0/r32/eax
    27480       # if curr-output-register starts with "x", emit a floating-point copy
    27481       8a/copy-byte *(ecx+4) 0/r32/AL
    27482       25/and-eax-with 0xff/imm32
    27483       3d/compare-eax-and 0x78/imm32/x
    27484       {
    27485         75/jump-if-!= break/disp8
    27486         (emit-float-output *(ebp+8) %esi %ecx)
    27487         eb/jump $emit-outputs:continue/disp8
    27488       }
    27489       # otherwise emit an int copy
    27490       (emit-int-output *(ebp+8) %esi %ecx)
    27491 $emit-outputs:continue:
    27492       # curr-inout = curr-inout->next
    27493       (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
    27494       89/<- %esi 0/r32/eax
    27495       # curr-output = curr-output->next
    27496       (lookup *(edi+8) *(edi+0xc))  # List-next List-next => eax
    27497       89/<- %edi 0/r32/eax
    27498       #
    27499       e9/jump loop/disp32
    27500     }
    27501 $emit-outputs:end:
    27502     # . restore registers
    27503     5f/pop-to-edi
    27504     5e/pop-to-esi
    27505     59/pop-to-ecx
    27506     58/pop-to-eax
    27507     # . epilogue
    27508     89/<- %esp 5/r32/ebp
    27509     5d/pop-to-ebp
    27510     c3/return
    27511
    27512 emit-int-output:  # out: (addr buffered-file), return-var: (addr stmt-var), dest-reg: (addr array byte)
    27513     # . prologue
    27514     55/push-ebp
    27515     89/<- %ebp 4/r32/esp
    27516     # . save registers
    27517     50/push-eax
    27518     51/push-ecx
    27519     # ecx = return-var->value
    27520     8b/-> *(ebp+0xc) 0/r32/eax
    27521     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    27522     89/<- %ecx 0/r32/eax
    27523     # if curr-var is a literal, emit copy of a literal to the output
    27524     (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
    27525     (simple-mu-type? %eax 0)  # literal => eax
    27526     {
    27527       3d/compare-eax-and 0/imm32/false
    27528       0f 84/jump-if-= break/disp32
    27529       (emit-indent *(ebp+8) *Curr-block-depth)
    27530       (write-buffered *(ebp+8) "c7 0/subop/copy %")
    27531       (write-buffered *(ebp+8) *(ebp+0x10))
    27532       (write-buffered *(ebp+8) " ")
    27533       (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    27534       (write-buffered *(ebp+8) %eax)
    27535       (write-buffered *(ebp+8) "/imm32\n")
    27536       e9/jump $emit-int-output:end/disp32
    27537     }
    27538     # otherwise emit an integer copy
    27539     (emit-indent *(ebp+8) *Curr-block-depth)
    27540     (write-buffered *(ebp+8) "8b/->")
    27541     (emit-subx-var-as-rm32 *(ebp+8) *(ebp+0xc))
    27542     (write-buffered *(ebp+8) " ")
    27543     (get Mu-registers *(ebp+0x10) 0xc "Mu-registers")  # => eax
    27544     (write-int32-hex-buffered *(ebp+8) *eax)
    27545     (write-buffered *(ebp+8) "/r32\n")
    27546 $emit-int-output:end:
    27547     # . restore registers
    27548     59/pop-to-ecx
    27549     58/pop-to-eax
    27550     # . epilogue
    27551     89/<- %esp 5/r32/ebp
    27552     5d/pop-to-ebp
    27553     c3/return
    27554
    27555 emit-float-output:  # out: (addr buffered-file), return-var: (addr stmt-var), dest-reg: (addr array byte)
    27556     # . prologue
    27557     55/push-ebp
    27558     89/<- %ebp 4/r32/esp
    27559     # . save registers
    27560     50/push-eax
    27561     #
    27562     (emit-indent *(ebp+8) *Curr-block-depth)
    27563     (write-buffered *(ebp+8) "f3 0f 10/->")
    27564     (emit-subx-var-as-rm32 *(ebp+8) *(ebp+0xc))
    27565     (write-buffered *(ebp+8) " ")
    27566     (get Mu-registers *(ebp+0x10) 0xc "Mu-registers")  # => eax
    27567     (write-int32-hex-buffered *(ebp+8) *eax)
    27568     (write-buffered *(ebp+8) "/x32\n")
    27569 $emit-float-output:end:
    27570     # . restore registers
    27571     58/pop-to-eax
    27572     # . epilogue
    27573     89/<- %esp 5/r32/ebp
    27574     5d/pop-to-ebp
    27575     c3/return
    27576
    27577 mu-branch?:  # stmt: (addr stmt1) -> result/eax: boolean
    27578     # . prologue
    27579     55/push-ebp
    27580     89/<- %ebp 4/r32/esp
    27581     # . save registers
    27582     51/push-ecx
    27583     # ecx = lookup(stmt->operation)
    27584     8b/-> *(ebp+8) 1/r32/ecx
    27585     (lookup *(ecx+4) *(ecx+8))  # Stmt1-operation Stmt1-operation => eax
    27586     89/<- %ecx 0/r32/eax
    27587     # if (stmt->operation starts with "loop") return true
    27588     (string-starts-with? %ecx "loop")  # => eax
    27589     3d/compare-eax-and 0/imm32/false
    27590     75/jump-if-not-equal $mu-branch?:end/disp8
    27591     # if (stmt->operation starts with "break") return true
    27592     (string-starts-with? %ecx "break")  # => eax
    27593     3d/compare-eax-and 0/imm32/false
    27594     75/jump-if-not-equal $mu-branch?:end/disp8
    27595     # otherwise return (stmt->operation starts with "return")
    27596     (string-starts-with? %ecx "return")  # => eax
    27597 $mu-branch?:end:
    27598     # . restore registers
    27599     59/pop-to-ecx
    27600     # . epilogue
    27601     89/<- %esp 5/r32/ebp
    27602     5d/pop-to-ebp
    27603     c3/return
    27604
    27605 emit-reverse-break:  # out: (addr buffered-file), stmt: (addr stmt1)
    27606     # . prologue
    27607     55/push-ebp
    27608     89/<- %ebp 4/r32/esp
    27609     # . save registers
    27610     50/push-eax
    27611     # eax = stmt
    27612     8b/-> *(ebp+0xc) 0/r32/eax
    27613     #
    27614     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
    27615     (get Reverse-branch %eax 0x10 "reverse-branch: ")  # => eax: (addr handle array byte)
    27616     (emit-indent *(ebp+8) *Curr-block-depth)
    27617     (lookup *eax *(eax+4))  # => eax
    27618     (write-buffered *(ebp+8) %eax)
    27619     (write-buffered *(ebp+8) " break/disp32\n")
    27620 $emit-reverse-break:end:
    27621     # . restore registers
    27622     58/pop-to-eax
    27623     # . epilogue
    27624     89/<- %esp 5/r32/ebp
    27625     5d/pop-to-ebp
    27626     c3/return
    27627
    27628 == data
    27629
    27630 # Table from Mu branch instructions to the reverse SubX opcodes for them.
    27631 Reverse-branch:  # (table (handle array byte) (handle array byte))
    27632   # a table is a stream
    27633   0x240/imm32/write
    27634   0/imm32/read
    27635   0x240/imm32/size
    27636   # data
    27637   0x11/imm32/alloc-id   _string-break-if-=/imm32                0x11/imm32/alloc-id   _string_0f_85_jump_label/imm32
    27638   0x11/imm32/alloc-id   _string-loop-if-=/imm32                 0x11/imm32/alloc-id   _string_0f_85_jump_label/imm32
    27639   0x11/imm32/alloc-id   _string-break-if-!=/imm32               0x11/imm32/alloc-id   _string_0f_84_jump_label/imm32
    27640   0x11/imm32/alloc-id   _string-loop-if-!=/imm32                0x11/imm32/alloc-id   _string_0f_84_jump_label/imm32
    27641   0x11/imm32/alloc-id   _string-break-if-</imm32                0x11/imm32/alloc-id   _string_0f_8d_jump_label/imm32
    27642   0x11/imm32/alloc-id   _string-loop-if-</imm32                 0x11/imm32/alloc-id   _string_0f_8d_jump_label/imm32
    27643   0x11/imm32/alloc-id   _string-break-if->/imm32                0x11/imm32/alloc-id   _string_0f_8e_jump_label/imm32
    27644   0x11/imm32/alloc-id   _string-loop-if->/imm32                 0x11/imm32/alloc-id   _string_0f_8e_jump_label/imm32
    27645   0x11/imm32/alloc-id   _string-break-if-<=/imm32               0x11/imm32/alloc-id   _string_0f_8f_jump_label/imm32
    27646   0x11/imm32/alloc-id   _string-loop-if-<=/imm32                0x11/imm32/alloc-id   _string_0f_8f_jump_label/imm32
    27647   0x11/imm32/alloc-id   _string-break-if->=/imm32               0x11/imm32/alloc-id   _string_0f_8c_jump_label/imm32
    27648   0x11/imm32/alloc-id   _string-loop-if->=/imm32                0x11/imm32/alloc-id   _string_0f_8c_jump_label/imm32
    27649   0x11/imm32/alloc-id   _string-break-if-addr</imm32            0x11/imm32/alloc-id   _string_0f_83_jump_label/imm32
    27650   0x11/imm32/alloc-id   _string-loop-if-addr</imm32             0x11/imm32/alloc-id   _string_0f_83_jump_label/imm32
    27651   0x11/imm32/alloc-id   _string-break-if-addr>/imm32            0x11/imm32/alloc-id   _string_0f_86_jump_label/imm32
    27652   0x11/imm32/alloc-id   _string-loop-if-addr>/imm32             0x11/imm32/alloc-id   _string_0f_86_jump_label/imm32
    27653   0x11/imm32/alloc-id   _string-break-if-addr<=/imm32           0x11/imm32/alloc-id   _string_0f_87_jump_label/imm32
    27654   0x11/imm32/alloc-id   _string-loop-if-addr<=/imm32            0x11/imm32/alloc-id   _string_0f_87_jump_label/imm32
    27655   0x11/imm32/alloc-id   _string-break-if-addr>=/imm32           0x11/imm32/alloc-id   _string_0f_82_jump_label/imm32
    27656   0x11/imm32/alloc-id   _string-loop-if-addr>=/imm32            0x11/imm32/alloc-id   _string_0f_82_jump_label/imm32
    27657   0x11/imm32/alloc-id   _string-break-if-float</imm32           0x11/imm32/alloc-id   _string_0f_83_jump_label/imm32
    27658   0x11/imm32/alloc-id   _string-loop-if-float</imm32            0x11/imm32/alloc-id   _string_0f_83_jump_label/imm32
    27659   0x11/imm32/alloc-id   _string-break-if-float>/imm32           0x11/imm32/alloc-id   _string_0f_86_jump_label/imm32
    27660   0x11/imm32/alloc-id   _string-loop-if-float>/imm32            0x11/imm32/alloc-id   _string_0f_86_jump_label/imm32
    27661   0x11/imm32/alloc-id   _string-break-if-float<=/imm32          0x11/imm32/alloc-id   _string_0f_87_jump_label/imm32
    27662   0x11/imm32/alloc-id   _string-loop-if-float<=/imm32           0x11/imm32/alloc-id   _string_0f_87_jump_label/imm32
    27663   0x11/imm32/alloc-id   _string-break-if-float>=/imm32          0x11/imm32/alloc-id   _string_0f_82_jump_label/imm32
    27664   0x11/imm32/alloc-id   _string-loop-if-float>=/imm32           0x11/imm32/alloc-id   _string_0f_82_jump_label/imm32
    27665   0x11/imm32/alloc-id   _string-break-if-carry/imm32            0x11/imm32/alloc-id   _string_0f_83_jump_label/imm32
    27666   0x11/imm32/alloc-id   _string-loop-if-carry/imm32             0x11/imm32/alloc-id   _string_0f_83_jump_label/imm32
    27667   0x11/imm32/alloc-id   _string-break-if-not-carry/imm32        0x11/imm32/alloc-id   _string_0f_82_jump_label/imm32
    27668   0x11/imm32/alloc-id   _string-loop-if-not-carry/imm32         0x11/imm32/alloc-id   _string_0f_82_jump_label/imm32
    27669   0x11/imm32/alloc-id   _string-break-if-overflow/imm32         0x11/imm32/alloc-id   _string_0f_81_jump_label/imm32
    27670   0x11/imm32/alloc-id   _string-loop-if-overflow/imm32          0x11/imm32/alloc-id   _string_0f_81_jump_label/imm32
    27671   0x11/imm32/alloc-id   _string-break-if-not-overflow/imm32     0x11/imm32/alloc-id   _string_0f_80_jump_label/imm32
    27672   0x11/imm32/alloc-id   _string-loop-if-not-overflow/imm32      0x11/imm32/alloc-id   _string_0f_80_jump_label/imm32
    27673
    27674 == code
    27675
    27676 emit-unconditional-jump-to-depth:  # out: (addr buffered-file), vars: (addr stack live-var), depth: int, label-suffix: (addr array byte)
    27677     # . prologue
    27678     55/push-ebp
    27679     89/<- %ebp 4/r32/esp
    27680     # . save registers
    27681     50/push-eax
    27682     51/push-ecx
    27683     52/push-edx
    27684     53/push-ebx
    27685     56/push-esi
    27686     # ecx = vars
    27687     8b/-> *(ebp+0xc) 1/r32/ecx
    27688     # var eax: int = vars->top
    27689     8b/-> *ecx 0/r32/eax
    27690     # var curr/esi: (addr handle var) = &vars->data[vars->top - 12]
    27691     8d/copy-address *(ecx+eax-4) 6/r32/esi  # vars + 8 + vars->top - 12/Live-var-size
    27692     # var min/ecx: (addr handle var) = vars->data
    27693     8d/copy-address *(ecx+8) 1/r32/ecx
    27694     # edx = depth
    27695     8b/-> *(ebp+0x10) 2/r32/edx
    27696     {
    27697 $emit-unconditional-jump-to-depth:loop:
    27698       # if (curr < min) break
    27699       39/compare %esi 1/r32/ecx
    27700       0f 82/jump-if-addr< break/disp32
    27701       # var v/ebx: (addr var) = lookup(*curr)
    27702       (lookup *esi *(esi+4))  # => eax
    27703       89/<- %ebx 0/r32/eax
    27704       # if (v->block-depth < until-block-depth) break
    27705       39/compare *(ebx+0x10) 2/r32/edx  # Var-block-depth
    27706       0f 8c/jump-if-< break/disp32
    27707       {
    27708 $emit-unconditional-jump-to-depth:check:
    27709         # if v->block-depth != until-block-depth, continue
    27710         39/compare *(ebx+0x10) 2/r32/edx  # Var-block-depth
    27711         0f 85/jump-if-!= break/disp32
    27712 $emit-unconditional-jump-to-depth:depth-found:
    27713         # if v is not a literal, continue
    27714         (size-of %ebx)  # => eax
    27715         3d/compare-eax-and 0/imm32
    27716         0f 85/jump-if-!= break/disp32
    27717 $emit-unconditional-jump-to-depth:label-found:
    27718         # emit unconditional jump, then return
    27719         (emit-indent *(ebp+8) *Curr-block-depth)
    27720         (write-buffered *(ebp+8) "e9/jump ")
    27721         (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
    27722         (write-buffered *(ebp+8) %eax)
    27723         (write-buffered *(ebp+8) ":")
    27724         (write-buffered *(ebp+8) *(ebp+0x14))
    27725         (write-buffered *(ebp+8) "/disp32\n")
    27726         eb/jump $emit-unconditional-jump-to-depth:end/disp8
    27727       }
    27728       # curr -= 12
    27729       81 5/subop/subtract %esi 0xc/imm32
    27730       e9/jump loop/disp32
    27731     }
    27732     # TODO: error if no label at 'depth' was found
    27733 $emit-unconditional-jump-to-depth:end:
    27734     # . restore registers
    27735     5e/pop-to-esi
    27736     5b/pop-to-ebx
    27737     5a/pop-to-edx
    27738     59/pop-to-ecx
    27739     58/pop-to-eax
    27740     # . epilogue
    27741     89/<- %esp 5/r32/ebp
    27742     5d/pop-to-ebp
    27743     c3/return
    27744
    27745 # emit clean-up code for 'vars' until some block depth
    27746 # doesn't actually modify 'vars' so we need traverse manually inside the stack
    27747 emit-cleanup-code-until-depth:  # out: (addr buffered-file), vars: (addr stack live-var), until-block-depth: int
    27748     # . prologue
    27749     55/push-ebp
    27750     89/<- %ebp 4/r32/esp
    27751     # . save registers
    27752     50/push-eax
    27753     51/push-ecx
    27754     52/push-edx
    27755     53/push-ebx
    27756     56/push-esi
    27757 #?     (write-buffered Stderr "--- cleanup\n")
    27758 #?     (flush Stderr)
    27759     # ecx = vars
    27760     8b/-> *(ebp+0xc) 1/r32/ecx
    27761     # var esi: int = vars->top
    27762     8b/-> *ecx 6/r32/esi
    27763     # var curr/esi: (addr handle var) = &vars->data[vars->top - 12]
    27764     8d/copy-address *(ecx+esi-4) 6/r32/esi  # vars + 8 + vars->top - 12/Live-var-size
    27765     # var min/ecx: (addr handle var) = vars->data
    27766     81 0/subop/add %ecx 8/imm32
    27767     # edx = until-block-depth
    27768     8b/-> *(ebp+0x10) 2/r32/edx
    27769     {
    27770 $emit-cleanup-code-until-depth:loop:
    27771       # if (curr < min) break
    27772       39/compare %esi 1/r32/ecx
    27773       0f 82/jump-if-addr< break/disp32
    27774       # var v/ebx: (addr var) = lookup(*curr)
    27775       (lookup *esi *(esi+4))  # => eax
    27776       89/<- %ebx 0/r32/eax
    27777 #?       (lookup *ebx *(ebx+4))  # Var-name
    27778 #?       (write-buffered Stderr "var ")
    27779 #?       (write-buffered Stderr %eax)
    27780 #?       (write-buffered Stderr Newline)
    27781 #?       (flush Stderr)
    27782       # if (v->block-depth < until-block-depth) break
    27783       39/compare *(ebx+0x10) 2/r32/edx  # Var-block-depth
    27784       0f 8c/jump-if-< break/disp32
    27785       # if v is in a register
    27786       81 7/subop/compare *(ebx+0x18) 0/imm32  # Var-register
    27787       {
    27788         0f 84/jump-if-= break/disp32
    27789         {
    27790 $emit-cleanup-code-until-depth:check-for-previous-spill:
    27791           8b/-> *(esi+8) 0/r32/eax  # Live-var-register-spilled
    27792           3d/compare-eax-and 0/imm32/false
    27793           74/jump-if-= break/disp8
    27794 $emit-cleanup-code-until-depth:reclaim-var-in-register:
    27795           (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
    27796           (emit-pop-register *(ebp+8) %eax)
    27797         }
    27798         eb/jump $emit-cleanup-code-until-depth:continue/disp8
    27799       }
    27800       # otherwise v is on the stack
    27801       {
    27802         75/jump-if-!= break/disp8
    27803 $emit-cleanup-code-until-depth:var-on-stack:
    27804         (size-of %ebx)  # => eax
    27805         # don't emit code for labels
    27806         3d/compare-eax-and 0/imm32
    27807         74/jump-if-= break/disp8
    27808 $emit-cleanup-code-until-depth:reclaim-var-on-stack:
    27809         (emit-indent *(ebp+8) *Curr-block-depth)
    27810         (write-buffered *(ebp+8) "81 0/subop/add %esp ")
    27811         (write-int32-hex-buffered *(ebp+8) %eax)
    27812         (write-buffered *(ebp+8) "/imm32\n")
    27813       }
    27814 $emit-cleanup-code-until-depth:continue:
    27815       # curr -= 12
    27816       81 5/subop/subtract %esi 0xc/imm32
    27817       e9/jump loop/disp32
    27818     }
    27819 $emit-cleanup-code-until-depth:end:
    27820     # . restore registers
    27821     5e/pop-to-esi
    27822     5b/pop-to-ebx
    27823     5a/pop-to-edx
    27824     59/pop-to-ecx
    27825     58/pop-to-eax
    27826     # . epilogue
    27827     89/<- %esp 5/r32/ebp
    27828     5d/pop-to-ebp
    27829     c3/return
    27830
    27831 # emit clean-up code for 'vars' that don't conflict with output registers
    27832 # doesn't actually modify 'vars' so we need traverse manually inside the stack
    27833 emit-cleanup-code-for-non-outputs:  # out: (addr buffered-file), vars: (addr stack live-var), fn: (addr function)
    27834     # . prologue
    27835     55/push-ebp
    27836     89/<- %ebp 4/r32/esp
    27837     # . save registers
    27838     50/push-eax
    27839     51/push-ecx
    27840     52/push-edx
    27841     53/push-ebx
    27842     56/push-esi
    27843     57/push-edi
    27844     # ecx = vars
    27845     8b/-> *(ebp+0xc) 1/r32/ecx
    27846     # var esi: int = vars->top
    27847     8b/-> *ecx 6/r32/esi
    27848     # var curr/esi: (addr handle var) = &vars->data[vars->top - 12]
    27849     8d/copy-address *(ecx+esi-4) 6/r32/esi  # vars + 8 + vars->top - 12/Live-var-size
    27850     # var min/ecx: (addr handle var) = vars->data
    27851     81 0/subop/add %ecx 8/imm32
    27852     {
    27853 $emit-cleanup-code-for-non-outputs:loop:
    27854       # if (curr < min) break
    27855       39/compare %esi 1/r32/ecx
    27856       0f 82/jump-if-addr< break/disp32
    27857       # var v/ebx: (addr var) = lookup(*curr)
    27858       (lookup *esi *(esi+4))  # => eax
    27859       89/<- %ebx 0/r32/eax
    27860       # if v is in a register
    27861       81 7/subop/compare *(ebx+0x18) 0/imm32  # Var-register
    27862       {
    27863         0f 84/jump-if-= break/disp32
    27864         {
    27865 $emit-cleanup-code-for-non-outputs:check-for-previous-spill:
    27866           8b/-> *(esi+8) 0/r32/eax  # Live-var-register-spilled
    27867           3d/compare-eax-and 0/imm32/false
    27868           0f 84/jump-if-= break/disp32
    27869 $emit-cleanup-code-for-non-outputs:reclaim-var-in-register:
    27870           # var reg/edi: (addr array name) = v->register
    27871           (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
    27872           89/<- %edi 0/r32/eax
    27873           # if reg is not in function outputs, emit a pop
    27874           (reg-in-function-outputs? *(ebp+0x10) %edi)  # => eax
    27875           3d/compare-eax-and 0/imm32/false
    27876           {
    27877             75/jump-if-!= break/disp8
    27878             (emit-pop-register *(ebp+8) %edi)
    27879             eb/jump $emit-cleanup-code-for-non-outputs:reclaim-var-in-register-done/disp8
    27880           }
    27881           # otherwise just drop it from the stack
    27882           (emit-indent *(ebp+8) *Curr-block-depth)
    27883           (write-buffered *(ebp+8) "81 0/subop/add %esp 4/imm32\n")
    27884         }
    27885 $emit-cleanup-code-for-non-outputs:reclaim-var-in-register-done:
    27886         eb/jump $emit-cleanup-code-for-non-outputs:continue/disp8
    27887       }
    27888       # otherwise v is on the stack
    27889       {
    27890         75/jump-if-!= break/disp8
    27891 $emit-cleanup-code-for-non-outputs:var-on-stack:
    27892         (size-of %ebx)  # => eax
    27893         # don't emit code for labels
    27894         3d/compare-eax-and 0/imm32
    27895         74/jump-if-= break/disp8
    27896 $emit-cleanup-code-for-non-outputs:reclaim-var-on-stack:
    27897         (emit-indent *(ebp+8) *Curr-block-depth)
    27898         (write-buffered *(ebp+8) "81 0/subop/add %esp ")
    27899         (write-int32-hex-buffered *(ebp+8) %eax)
    27900         (write-buffered *(ebp+8) "/imm32\n")
    27901       }
    27902 $emit-cleanup-code-for-non-outputs:continue:
    27903       # curr -= 12
    27904       81 5/subop/subtract %esi 0xc/imm32
    27905       e9/jump loop/disp32
    27906     }
    27907 $emit-cleanup-code-for-non-outputs:end:
    27908     # . restore registers
    27909     5f/pop-to-edi
    27910     5e/pop-to-esi
    27911     5b/pop-to-ebx
    27912     5a/pop-to-edx
    27913     59/pop-to-ecx
    27914     58/pop-to-eax
    27915     # . epilogue
    27916     89/<- %esp 5/r32/ebp
    27917     5d/pop-to-ebp
    27918     c3/return
    27919
    27920 emit-push-register:  # out: (addr buffered-file), reg: (addr array byte)
    27921     # . prologue
    27922     55/push-ebp
    27923     89/<- %ebp 4/r32/esp
    27924     # eax = reg
    27925     8b/-> *(ebp+0xc) 0/r32/eax
    27926     # var prefix/eax: byte = reg->data[0]
    27927     8a/copy-byte *(eax+4) 0/r32/AL
    27928     25/and-eax-with 0xff/imm32
    27929     # if (prefix == 'x') push xmm register
    27930     {
    27931       3d/compare-eax-and 0x78/imm32/x
    27932       0f 85/jump-if-!= break/disp32
    27933       # TODO validate register
    27934       (emit-indent *(ebp+8) *Curr-block-depth)
    27935       (write-buffered *(ebp+8) "81 5/subop/subtract %esp 4/imm32\n")
    27936       (emit-indent *(ebp+8) *Curr-block-depth)
    27937       (write-buffered *(ebp+8) "f3 0f 11/<- *esp ")
    27938       # var prefix/eax: byte = reg->data[3]
    27939       8b/-> *(ebp+0xc) 0/r32/eax
    27940       8a/copy-byte *(eax+7) 0/r32/AL
    27941       25/and-eax-with 0xff/imm32
    27942       (write-byte-buffered *(ebp+8) %eax)
    27943       (write-buffered *(ebp+8) "/x32\n")
    27944       e9/jump $emit-push-register:end/disp32
    27945     }
    27946     # otherwise push gp register
    27947     (emit-indent *(ebp+8) *Curr-block-depth)
    27948     (write-buffered *(ebp+8) "ff 6/subop/push %")
    27949     (write-buffered *(ebp+8) *(ebp+0xc))
    27950     (write-buffered *(ebp+8) Newline)
    27951 $emit-push-register:end:
    27952     # . epilogue
    27953     89/<- %esp 5/r32/ebp
    27954     5d/pop-to-ebp
    27955     c3/return
    27956
    27957 emit-pop-register:  # out: (addr buffered-file), reg: (addr array byte)
    27958     # . prologue
    27959     55/push-ebp
    27960     89/<- %ebp 4/r32/esp
    27961     # . save registers
    27962     50/push-eax
    27963     # eax = reg
    27964     8b/-> *(ebp+0xc) 0/r32/eax
    27965     # var prefix/eax: byte = reg->data[0]
    27966     8a/copy-byte *(eax+4) 0/r32/AL
    27967     25/and-eax-with 0xff/imm32
    27968     # if (prefix == 'x') pop to xmm register
    27969     {
    27970       3d/compare-eax-and 0x78/imm32/x
    27971       0f 85/jump-if-!= break/disp32
    27972       # TODO validate register
    27973       (emit-indent *(ebp+8) *Curr-block-depth)
    27974       (write-buffered *(ebp+8) "f3 0f 10/-> *esp ")
    27975       # var prefix/eax: byte = reg->data[3]
    27976       8b/-> *(ebp+0xc) 0/r32/eax
    27977       8a/copy-byte *(eax+7) 0/r32/AL
    27978       25/and-eax-with 0xff/imm32
    27979       (write-byte-buffered *(ebp+8) %eax)
    27980       (write-buffered *(ebp+8) "/x32\n")
    27981       (emit-indent *(ebp+8) *Curr-block-depth)
    27982       (write-buffered *(ebp+8) "81 0/subop/add %esp 4/imm32\n")
    27983       e9/jump $emit-pop-register:end/disp32
    27984     }
    27985     # otherwise pop to gp register
    27986     (emit-indent *(ebp+8) *Curr-block-depth)
    27987     (write-buffered *(ebp+8) "8f 0/subop/pop %")
    27988     (write-buffered *(ebp+8) *(ebp+0xc))
    27989     (write-buffered *(ebp+8) Newline)
    27990 $emit-pop-register:end:
    27991     # . restore registers
    27992     58/pop-to-eax
    27993     # . epilogue
    27994     89/<- %esp 5/r32/ebp
    27995     5d/pop-to-ebp
    27996     c3/return
    27997
    27998 # emit clean-up code for 'vars' until a given label is encountered
    27999 # doesn't actually modify 'vars' so we need traverse manually inside the stack
    28000 emit-cleanup-code-until-target:  # out: (addr buffered-file), vars: (addr stack live-var), until-block-label: (addr array byte)
    28001     # . prologue
    28002     55/push-ebp
    28003     89/<- %ebp 4/r32/esp
    28004     # . save registers
    28005     50/push-eax
    28006     51/push-ecx
    28007     52/push-edx
    28008     53/push-ebx
    28009     # ecx = vars
    28010     8b/-> *(ebp+0xc) 1/r32/ecx
    28011     # var eax: int = vars->top
    28012     8b/-> *ecx 0/r32/eax
    28013     # var curr/edx: (addr handle var) = &vars->data[vars->top - 12]
    28014     8d/copy-address *(ecx+eax-4) 2/r32/edx  # vars + 8 + vars->top - 12/Live-var-size
    28015     # var min/ecx: (addr handle var) = vars->data
    28016     81 0/subop/add %ecx 8/imm32
    28017     {
    28018 $emit-cleanup-code-until-target:loop:
    28019       # if (curr < min) break
    28020       39/compare %edx 1/r32/ecx
    28021       0f 82/jump-if-addr< break/disp32
    28022       # var v/ebx: (handle var) = lookup(*curr)
    28023       (lookup *edx *(edx+4))  # => eax
    28024       89/<- %ebx 0/r32/eax
    28025       # if (v->name == until-block-label) break
    28026       (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
    28027       (string-equal? %eax *(ebp+0x10))  # => eax
    28028       3d/compare-eax-and 0/imm32/false
    28029       0f 85/jump-if-!= break/disp32
    28030       # if v is in a register
    28031       81 7/subop/compare *(ebx+0x18) 0/imm32  # Var-register
    28032       {
    28033         0f 84/jump-if-= break/disp32
    28034         {
    28035 $emit-cleanup-code-until-target:check-for-previous-spill:
    28036           8b/-> *(edx+8) 0/r32/eax  # Live-var-register-spilled
    28037           3d/compare-eax-and 0/imm32/false
    28038           74/jump-if-= break/disp8
    28039 $emit-cleanup-code-until-target:reclaim-var-in-register:
    28040           (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
    28041           (emit-pop-register *(ebp+8) %eax)
    28042         }
    28043         eb/jump $emit-cleanup-code-until-target:continue/disp8
    28044       }
    28045       # otherwise v is on the stack
    28046       {
    28047         75/jump-if-!= break/disp8
    28048 $emit-cleanup-code-until-target:reclaim-var-on-stack:
    28049         (size-of %ebx)  # => eax
    28050         # don't emit code for labels
    28051         3d/compare-eax-and 0/imm32
    28052         74/jump-if-= break/disp8
    28053         #
    28054         (emit-indent *(ebp+8) *Curr-block-depth)
    28055         (write-buffered *(ebp+8) "81 0/subop/add %esp ")
    28056         (write-int32-hex-buffered *(ebp+8) %eax)
    28057         (write-buffered *(ebp+8) "/imm32\n")
    28058       }
    28059 $emit-cleanup-code-until-target:continue:
    28060       # curr -= 12
    28061       81 5/subop/subtract %edx 0xc/imm32
    28062       e9/jump loop/disp32
    28063     }
    28064 $emit-cleanup-code-until-target:end:
    28065     # . restore registers
    28066     5b/pop-to-ebx
    28067     5a/pop-to-edx
    28068     59/pop-to-ecx
    28069     58/pop-to-eax
    28070     # . epilogue
    28071     89/<- %esp 5/r32/ebp
    28072     5d/pop-to-ebp
    28073     c3/return
    28074
    28075 # update Curr-local-stack-offset assuming vars until some block depth are popped
    28076 # doesn't actually modify 'vars', so we need traverse manually inside the stack
    28077 clean-up-stack-offset-state:  # vars: (addr stack live-var), until-block-depth: int
    28078     # . prologue
    28079     55/push-ebp
    28080     89/<- %ebp 4/r32/esp
    28081     # . save registers
    28082     50/push-eax
    28083     51/push-ecx
    28084     52/push-edx
    28085     53/push-ebx
    28086     56/push-esi
    28087     # ecx = vars
    28088     8b/-> *(ebp+8) 1/r32/ecx
    28089     # var esi: int = vars->top
    28090     8b/-> *ecx 6/r32/esi
    28091     # var curr/esi: (addr handle var) = &vars->data[vars->top - 12]
    28092     8d/copy-address *(ecx+esi-4) 6/r32/esi  # vars + 8 + vars->top - 12/Live-var-size
    28093     # var min/ecx: (addr handle var) = vars->data
    28094     81 0/subop/add %ecx 8/imm32
    28095     # edx = until-block-depth
    28096     8b/-> *(ebp+0xc) 2/r32/edx
    28097     {
    28098 $clean-up-stack-offset-state:loop:
    28099       # if (curr < min) break
    28100       39/compare %esi 1/r32/ecx
    28101       0f 82/jump-if-addr< break/disp32
    28102       # var v/ebx: (addr var) = lookup(*curr)
    28103       (lookup *esi *(esi+4))  # => eax
    28104       89/<- %ebx 0/r32/eax
    28105       # if (v->block-depth < until-block-depth) break
    28106       39/compare *(ebx+0x10) 2/r32/edx  # Var-block-depth
    28107       0f 8c/jump-if-< break/disp32
    28108       # if v is in a register
    28109       81 7/subop/compare *(ebx+0x18) 0/imm32  # Var-register
    28110       {
    28111         0f 84/jump-if-= break/disp32
    28112         {
    28113 $clean-up-stack-offset-state:check-for-previous-spill:
    28114           8b/-> *(esi+8) 0/r32/eax  # Live-var-register-spilled
    28115           3d/compare-eax-and 0/imm32/false
    28116           74/jump-if-= break/disp8
    28117 $clean-up-stack-offset-state:reclaim-var-in-register:
    28118           81 0/subop/add *Curr-local-stack-offset 4/imm32
    28119         }
    28120         eb/jump $clean-up-stack-offset-state:continue/disp8
    28121       }
    28122       # otherwise v is on the stack
    28123       {
    28124         75/jump-if-!= break/disp8
    28125 $clean-up-stack-offset-state:var-on-stack:
    28126         (size-of %ebx)  # => eax
    28127         01/add-to *Curr-local-stack-offset 0/r32/eax
    28128       }
    28129 $clean-up-stack-offset-state:continue:
    28130       # curr -= 12
    28131       81 5/subop/subtract %esi 0xc/imm32
    28132       e9/jump loop/disp32
    28133     }
    28134 $clean-up-stack-offset-state:end:
    28135     # . restore registers
    28136     5e/pop-to-esi
    28137     5b/pop-to-ebx
    28138     5a/pop-to-edx
    28139     59/pop-to-ecx
    28140     58/pop-to-eax
    28141     # . epilogue
    28142     89/<- %esp 5/r32/ebp
    28143     5d/pop-to-ebp
    28144     c3/return
    28145
    28146 # Return true if there isn't a variable in 'vars' with the same block-depth
    28147 # and register as 'v'.
    28148 # 'v' is guaranteed not to be within 'vars'.
    28149 not-yet-spilled-this-block?:  # v: (addr var), vars: (addr stack live-var) -> result/eax: boolean
    28150     # . prologue
    28151     55/push-ebp
    28152     89/<- %ebp 4/r32/esp
    28153     # . save registers
    28154     51/push-ecx
    28155     52/push-edx
    28156     53/push-ebx
    28157     56/push-esi
    28158     57/push-edi
    28159     # ecx = vars
    28160     8b/-> *(ebp+0xc) 1/r32/ecx
    28161     # var eax: int = vars->top
    28162     8b/-> *ecx 0/r32/eax
    28163     # var curr/edx: (addr handle var) = &vars->data[vars->top - 12]
    28164     8d/copy-address *(ecx+eax-4) 2/r32/edx  # vars + 8 + vars->top - 12/Live-var-size
    28165     # var min/ecx: (addr handle var) = vars->data
    28166     8d/copy-address *(ecx+8) 1/r32/ecx
    28167     # var depth/ebx: int = v->block-depth
    28168     8b/-> *(ebp+8) 3/r32/ebx
    28169     8b/-> *(ebx+0x10) 3/r32/ebx  # Var-block-depth
    28170     # var needle/esi: (addr array byte) = v->register
    28171     8b/-> *(ebp+8) 6/r32/esi
    28172     (lookup *(esi+0x18) *(esi+0x1c))  # Var-register Var-register => eax
    28173     89/<- %esi 0/r32/eax
    28174     {
    28175 $not-yet-spilled-this-block?:loop:
    28176       # if (curr < min) break
    28177       39/compare %edx 1/r32/ecx
    28178       0f 82/jump-if-addr< break/disp32
    28179       # var cand/edi: (addr var) = lookup(*curr)
    28180       (lookup *edx *(edx+4))  # => eax
    28181       89/<- %edi 0/r32/eax
    28182       # if (cand->block-depth < depth) break
    28183       39/compare *(edi+0x10) 3/r32/ebx  # Var-block-depth
    28184       0f 8c/jump-if-< break/disp32
    28185       # var cand-reg/edi: (array array byte) = cand->reg
    28186       (lookup *(edi+0x18) *(edi+0x1c))  # Var-register Var-register => eax
    28187       89/<- %edi 0/r32/eax
    28188       # if (cand-reg == null) continue
    28189       {
    28190 $not-yet-spilled-this-block?:check-reg:
    28191         81 7/subop/compare %edi 0/imm32
    28192         0f 84/jump-if-= break/disp32
    28193         # if (cand-reg == needle) return true
    28194         (string-equal? %esi %edi)  # => eax
    28195         3d/compare-eax-and 0/imm32/false
    28196         74/jump-if-= break/disp8
    28197 $not-yet-spilled-this-block?:return-false:
    28198         b8/copy-to-eax 0/imm32/false
    28199         eb/jump $not-yet-spilled-this-block?:end/disp8
    28200       }
    28201 $not-yet-spilled-this-block?:continue:
    28202       # curr -= 12
    28203       81 5/subop/subtract %edx 0xc/imm32
    28204       e9/jump loop/disp32
    28205     }
    28206 $not-yet-spilled-this-block?:return-true:
    28207     # return true
    28208     b8/copy-to-eax 1/imm32/true
    28209 $not-yet-spilled-this-block?:end:
    28210     # . restore registers
    28211     5f/pop-to-edi
    28212     5e/pop-to-esi
    28213     5b/pop-to-ebx
    28214     5a/pop-to-edx
    28215     59/pop-to-ecx
    28216     # . epilogue
    28217     89/<- %esp 5/r32/ebp
    28218     5d/pop-to-ebp
    28219     c3/return
    28220
    28221 # could the register of 'v' ever be written to by one of the vars in fn-outputs?
    28222 will-not-write-some-register?:  # v: (addr var), stmts: (addr list stmt), fn: (addr function) -> result/eax: boolean
    28223     # . prologue
    28224     55/push-ebp
    28225     89/<- %ebp 4/r32/esp
    28226     # eax = v
    28227     8b/-> *(ebp+8) 0/r32/eax
    28228     # var reg/eax: (addr array byte) = lookup(v->register)
    28229     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    28230     # var target/eax: (addr var) = find-register(fn-outputs, reg)
    28231     (find-register *(ebp+0x10) %eax)  # => eax
    28232     # if (target == 0) return true
    28233     {
    28234       3d/compare-eax-and 0/imm32
    28235       75/jump-if-!= break/disp8
    28236       b8/copy-to-eax 1/imm32/true
    28237       eb/jump $will-not-write-some-register?:end/disp8
    28238     }
    28239     # return !assigns-in-stmts?(stmts, target)
    28240     (assigns-in-stmts? *(ebp+0xc) %eax)  # => eax
    28241     3d/compare-eax-and 0/imm32/false
    28242     # assume: true = 1, so no need to mask with 0x000000ff
    28243     0f 94/set-if-= %al
    28244 $will-not-write-some-register?:end:
    28245     # . epilogue
    28246     89/<- %esp 5/r32/ebp
    28247     5d/pop-to-ebp
    28248     c3/return
    28249
    28250 # return fn output with matching register
    28251 # always returns false if 'reg' is null
    28252 find-register:  # fn: (addr function), reg: (addr array byte) -> result/eax: (addr var)
    28253     # . prologue
    28254     55/push-ebp
    28255     89/<- %ebp 4/r32/esp
    28256     # . save registers
    28257     51/push-ecx
    28258     # var curr/ecx: (addr list var) = lookup(fn->outputs)
    28259     8b/-> *(ebp+8) 1/r32/ecx
    28260     (lookup *(ecx+0x10) *(ecx+0x14))  # Function-outputs Function-outputs => eax
    28261     89/<- %ecx 0/r32/eax
    28262     {
    28263 $find-register:loop:
    28264       # if (curr == 0) break
    28265       81 7/subop/compare %ecx 0/imm32
    28266       74/jump-if-= break/disp8
    28267       # eax = curr->value->register
    28268       (lookup *ecx *(ecx+4))  # List-value List-value => eax
    28269       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    28270       # if (eax == reg) return curr->value
    28271 $find-register:compare:
    28272       (string-equal? *(ebp+0xc) %eax)  # => eax
    28273       {
    28274         3d/compare-eax-and 0/imm32/false
    28275         74/jump-if-= break/disp8
    28276 $find-register:found:
    28277         (lookup *ecx *(ecx+4))  # List-value List-value => eax
    28278         eb/jump $find-register:end/disp8
    28279       }
    28280       # curr = lookup(curr->next)
    28281       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
    28282       89/<- %ecx 0/r32/eax
    28283       #
    28284       eb/jump loop/disp8
    28285     }
    28286 $find-register:end:
    28287     # . restore registers
    28288     59/pop-to-ecx
    28289     # . epilogue
    28290     89/<- %esp 5/r32/ebp
    28291     5d/pop-to-ebp
    28292     c3/return
    28293
    28294 assigns-in-stmts?:  # stmts: (addr list stmt), v: (addr var) -> result/eax: boolean
    28295     # . prologue
    28296     55/push-ebp
    28297     89/<- %ebp 4/r32/esp
    28298     # . save registers
    28299     51/push-ecx
    28300     # var curr/ecx: (addr list stmt) = stmts
    28301     8b/-> *(ebp+8) 1/r32/ecx
    28302     {
    28303       # if (curr == 0) break
    28304       81 7/subop/compare %ecx 0/imm32
    28305       74/jump-if-= break/disp8
    28306       # if assigns-in-stmt?(curr->value, v) return true
    28307       (lookup *ecx *(ecx+4))  # List-value List-value => eax
    28308       (assigns-in-stmt? %eax *(ebp+0xc))  # => eax
    28309       3d/compare-eax-and 0/imm32/false
    28310       75/jump-if-!= break/disp8
    28311       # curr = lookup(curr->next)
    28312       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
    28313       89/<- %ecx 0/r32/eax
    28314       #
    28315       eb/jump loop/disp8
    28316     }
    28317 $assigns-in-stmts?:end:
    28318     # . restore registers
    28319     59/pop-to-ecx
    28320     # . epilogue
    28321     89/<- %esp 5/r32/ebp
    28322     5d/pop-to-ebp
    28323     c3/return
    28324
    28325 assigns-in-stmt?:  # stmt: (addr stmt), v: (addr var) -> result/eax: boolean
    28326     # . prologue
    28327     55/push-ebp
    28328     89/<- %ebp 4/r32/esp
    28329     # . save registers
    28330     51/push-ecx
    28331     # ecx = stmt
    28332     8b/-> *(ebp+8) 1/r32/ecx
    28333     # if stmt is a stmt1, return assigns-in-stmt-vars?(stmt->outputs, v)
    28334     {
    28335       81 7/subop/compare *ecx 1/imm32/stmt1  # Stmt-tag
    28336       75/jump-if-!= break/disp8
    28337       (lookup *(ecx+0x14) *(ecx+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    28338       (assigns-in-stmt-vars? %eax *(ebp+0xc))  # => eax
    28339       eb/jump $assigns-in-stmt?:end/disp8
    28340     }
    28341     # if stmt is a block, return assigns-in-stmts?(stmt->stmts, v)
    28342     {
    28343       81 7/subop/compare *ecx 0/imm32/block  # Stmt-tag
    28344       75/jump-if-!= break/disp8
    28345       (lookup *(ecx+4) *(ecx+8))  # Block-stmts Block-stmts => eax
    28346       (assigns-in-stmts? %eax *(ebp+0xc))  # => eax
    28347       eb/jump $assigns-in-stmt?:end/disp8
    28348     }
    28349     # otherwise return false
    28350     b8/copy 0/imm32/false
    28351 $assigns-in-stmt?:end:
    28352     # . restore registers
    28353     59/pop-to-ecx
    28354     # . epilogue
    28355     89/<- %esp 5/r32/ebp
    28356     5d/pop-to-ebp
    28357     c3/return
    28358
    28359 assigns-in-stmt-vars?:  # stmt-var: (addr stmt-var), v: (addr var) -> result/eax: boolean
    28360     # . prologue
    28361     55/push-ebp
    28362     89/<- %ebp 4/r32/esp
    28363     # . save registers
    28364     51/push-ecx
    28365     # var curr/ecx: (addr stmt-var) = stmt-var
    28366     8b/-> *(ebp+8) 1/r32/ecx
    28367     {
    28368       # if (curr == 0) break
    28369       81 7/subop/compare %ecx 0/imm32
    28370       74/jump-if-= break/disp8
    28371       # eax = lookup(curr->value)
    28372       (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
    28373       # if (eax == v  &&  curr->is-deref? == false) return true
    28374       {
    28375         39/compare *(ebp+0xc) 0/r32/eax
    28376         75/jump-if-!= break/disp8
    28377         81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
    28378         75/jump-if-!= break/disp8
    28379         b8/copy-to-eax 1/imm32/true
    28380         eb/jump $assigns-in-stmt-vars?:end/disp8
    28381       }
    28382       # curr = lookup(curr->next)
    28383       (lookup *(ecx+8) *(ecx+0xc))  # Stmt-var-next Stmt-var-next => eax
    28384       89/<- %ecx 0/r32/eax
    28385       #
    28386       eb/jump loop/disp8
    28387     }
    28388 $assigns-in-stmt-vars?:end:
    28389     # . restore registers
    28390     59/pop-to-ecx
    28391     # . epilogue
    28392     89/<- %esp 5/r32/ebp
    28393     5d/pop-to-ebp
    28394     c3/return
    28395
    28396 # is there a var before 'v' with the same block-depth and register on the 'vars' stack?
    28397 # v is guaranteed to be within vars
    28398 # 'start' is provided as an optimization, a pointer within vars
    28399 # *start == v
    28400 same-register-spilled-before?:  # v: (addr var), vars: (addr stack (handle var)), start: (addr var) -> result/eax: boolean
    28401     # . prologue
    28402     55/push-ebp
    28403     89/<- %ebp 4/r32/esp
    28404     # . save registers
    28405     51/push-ecx
    28406     52/push-edx
    28407     53/push-ebx
    28408     56/push-esi
    28409     57/push-edi
    28410     # ecx = v
    28411     8b/-> *(ebp+8) 1/r32/ecx
    28412     # var reg/edx: (addr array byte) = lookup(v->register)
    28413     (lookup *(ecx+0x18) *(ecx+0x1c))  # Var-register Var-register => eax
    28414     89/<- %edx 0/r32/eax
    28415     # var depth/ebx: int = v->block-depth
    28416     8b/-> *(ecx+0x10) 3/r32/ebx  # Var-block-depth
    28417     # var min/ecx: (addr handle var) = vars->data
    28418     8b/-> *(ebp+0xc) 1/r32/ecx
    28419     81 0/subop/add %ecx 8/imm32
    28420     # TODO: check that start >= min and start < &vars->data[top]
    28421     # TODO: check that *start == v
    28422     # var curr/esi: (addr handle var) = start
    28423     8b/-> *(ebp+0x10) 6/r32/esi
    28424     # curr -= 8
    28425     81 5/subop/subtract %esi 8/imm32
    28426     {
    28427 $same-register-spilled-before?:loop:
    28428       # if (curr < min) break
    28429       39/compare %esi 1/r32/ecx
    28430       0f 82/jump-if-addr< break/disp32
    28431       # var x/eax: (addr var) = lookup(*curr)
    28432       (lookup *esi *(esi+4))  # => eax
    28433       # if (x->block-depth < depth) break
    28434       39/compare *(eax+0x10) 3/r32/ebx  # Var-block-depth
    28435       0f 8c/jump-if-< break/disp32
    28436       # if (x->register == 0) continue
    28437       81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
    28438       74/jump-if-= $same-register-spilled-before?:continue/disp8
    28439       # if (x->register == reg) return true
    28440       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    28441       (string-equal? %eax %edx)  # => eax
    28442       3d/compare-eax-and 0/imm32/false
    28443       b8/copy-to-eax 1/imm32/true
    28444       75/jump-if-!= $same-register-spilled-before?:end/disp8
    28445 $same-register-spilled-before?:continue:
    28446       # curr -= 8
    28447       81 5/subop/subtract %esi 8/imm32
    28448       e9/jump loop/disp32
    28449     }
    28450 $same-register-spilled-before?:false:
    28451     b8/copy-to-eax 0/imm32/false
    28452 $same-register-spilled-before?:end:
    28453     # . restore registers
    28454     5f/pop-to-edi
    28455     5e/pop-to-esi
    28456     5b/pop-to-ebx
    28457     5a/pop-to-edx
    28458     59/pop-to-ecx
    28459     # . epilogue
    28460     89/<- %esp 5/r32/ebp
    28461     5d/pop-to-ebp
    28462     c3/return
    28463
    28464 # clean up global state for 'vars' until some block depth (inclusive)
    28465 clean-up-blocks:  # vars: (addr stack live-var), until-block-depth: int, fn: (addr function)
    28466     # . prologue
    28467     55/push-ebp
    28468     89/<- %ebp 4/r32/esp
    28469     # . save registers
    28470     50/push-eax
    28471     51/push-ecx
    28472     56/push-esi
    28473     # esi = vars
    28474     8b/-> *(ebp+8) 6/r32/esi
    28475     # ecx = until-block-depth
    28476     8b/-> *(ebp+0xc) 1/r32/ecx
    28477     {
    28478 $clean-up-blocks:reclaim-loop:
    28479       # if (vars->top <= 0) break
    28480       8b/-> *esi 0/r32/eax  # Stack-top
    28481       3d/compare-eax-and 0/imm32
    28482       0f 8e/jump-if-<= break/disp32
    28483       # var v/eax: (addr var) = lookup(vars[vars->top-12])
    28484       (lookup *(esi+eax-4) *(esi+eax))  # vars + 8 + vars->top - 12 => eax
    28485       # if (v->block-depth < until-block-depth) break
    28486       39/compare *(eax+0x10) 1/r32/ecx  # Var-block-depth
    28487       0f 8c/jump-if-< break/disp32
    28488       (pop %esi)  # => eax
    28489       (pop %esi)  # => eax
    28490       (pop %esi)  # => eax
    28491       e9/jump loop/disp32
    28492     }
    28493 $clean-up-blocks:end:
    28494     # . restore registers
    28495     5e/pop-to-esi
    28496     59/pop-to-ecx
    28497     58/pop-to-eax
    28498     # . epilogue
    28499     89/<- %esp 5/r32/ebp
    28500     5d/pop-to-ebp
    28501     c3/return
    28502
    28503 reg-in-function-outputs?:  # fn: (addr function), target: (addr array byte) -> result/eax: boolean
    28504     # . prologue
    28505     55/push-ebp
    28506     89/<- %ebp 4/r32/esp
    28507     # . save registers
    28508     51/push-ecx
    28509     # var curr/ecx: (addr list var) = lookup(fn->outputs)
    28510     8b/-> *(ebp+8) 0/r32/eax
    28511     (lookup *(eax+0x10) *(eax+0x14))  # Function-outputs Function-outputs => eax
    28512     89/<- %ecx 0/r32/eax
    28513     # while curr != null
    28514     {
    28515       81 7/subop/compare %ecx 0/imm32
    28516       74/jump-if-= break/disp8
    28517       # var v/eax: (addr var) = lookup(curr->value)
    28518       (lookup *ecx *(ecx+4))  # List-value List-value => eax
    28519       # var reg/eax: (addr array byte) = lookup(v->register)
    28520       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    28521       # if (reg == target) return true
    28522       (string-equal? %eax *(ebp+0xc))  # => eax
    28523       3d/compare-eax-and 0/imm32/false
    28524       75/jump-if-!= $reg-in-function-outputs?:end/disp8
    28525       # curr = curr->next
    28526       (lookup *(ecx+8) *(ecx+0xc))  # List-next List-next => eax
    28527       89/<- %ecx 0/r32/eax
    28528       #
    28529       eb/jump loop/disp8
    28530     }
    28531     # return false
    28532     b8/copy-to-eax 0/imm32
    28533 $reg-in-function-outputs?:end:
    28534     # . restore registers
    28535     59/pop-to-ecx
    28536     # . epilogue
    28537     89/<- %esp 5/r32/ebp
    28538     5d/pop-to-ebp
    28539     c3/return
    28540
    28541 emit-subx-var-def:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
    28542     # . prologue
    28543     55/push-ebp
    28544     89/<- %ebp 4/r32/esp
    28545     # . save registers
    28546     50/push-eax
    28547     51/push-ecx
    28548     52/push-edx
    28549     # eax = stmt
    28550     8b/-> *(ebp+0xc) 0/r32/eax
    28551     # var v/ecx: (addr var)
    28552     (lookup *(eax+4) *(eax+8))  # Vardef-var Vardef-var => eax
    28553     89/<- %ecx 0/r32/eax
    28554     # v->block-depth = *Curr-block-depth
    28555     8b/-> *Curr-block-depth 0/r32/eax
    28556     89/<- *(ecx+0x10) 0/r32/eax  # Var-block-depth
    28557     # var n/edx: int = size-of(stmt->var)
    28558     (size-of %ecx)  # => eax
    28559     89/<- %edx 0/r32/eax
    28560     # *Curr-local-stack-offset -= n
    28561     29/subtract-from *Curr-local-stack-offset 2/r32/edx
    28562     # v->offset = *Curr-local-stack-offset
    28563     8b/-> *Curr-local-stack-offset 0/r32/eax
    28564     89/<- *(ecx+0x14) 0/r32/eax  # Var-offset
    28565     # if v is an array, do something special to initialize it
    28566     {
    28567       (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
    28568       (mu-array? %eax)  # => eax
    28569       3d/compare-eax-and 0/imm32/false
    28570       0f 84/jump-if-= break/disp32
    28571       # var array-size-without-size/edx: int = n-4
    28572       81 5/subop/subtract %edx 4/imm32
    28573       #
    28574       (emit-array-data-initialization *(ebp+8) %edx)
    28575       e9/jump $emit-subx-var-def:end/disp32
    28576     }
    28577     # another special-case for initializing streams
    28578     # a stream is an array with 2 extra pointers
    28579     {
    28580       (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
    28581       (mu-stream? %eax)  # => eax
    28582       3d/compare-eax-and 0/imm32/false
    28583       0f 84/jump-if-= break/disp32
    28584       # var array-size-without-size/edx: int = n-12
    28585       81 5/subop/subtract %edx 0xc/imm32
    28586       (lookup *(ecx+8) *(ecx+0xc))  # Var-type Var-type => eax
    28587       (emit-stream-data-initialization *(ebp+8) %edx %eax *(ebp+0x10) *(ebp+0x14))
    28588       # emit read and write pointers
    28589       (emit-indent *(ebp+8) *Curr-block-depth)
    28590       (write-buffered *(ebp+8) "68/push 0/imm32\n")
    28591       (emit-indent *(ebp+8) *Curr-block-depth)
    28592       (write-buffered *(ebp+8) "68/push 0/imm32\n")
    28593       #
    28594       eb/jump $emit-subx-var-def:end/disp8
    28595     }
    28596     # while n > 0
    28597     {
    28598       81 7/subop/compare %edx 0/imm32
    28599       7e/jump-if-<= break/disp8
    28600       (emit-indent *(ebp+8) *Curr-block-depth)
    28601       (write-buffered *(ebp+8) "68/push 0/imm32\n")
    28602       # n -= 4
    28603       81 5/subop/subtract %edx 4/imm32
    28604       #
    28605       eb/jump loop/disp8
    28606     }
    28607 $emit-subx-var-def:end:
    28608     # . restore registers
    28609     5a/pop-to-edx
    28610     59/pop-to-ecx
    28611     58/pop-to-eax
    28612     # . epilogue
    28613     89/<- %esp 5/r32/ebp
    28614     5d/pop-to-ebp
    28615     c3/return
    28616
    28617 emit-array-data-initialization:  # out: (addr buffered-file), n: int
    28618     # . prologue
    28619     55/push-ebp
    28620     89/<- %ebp 4/r32/esp
    28621     #
    28622     (emit-indent *(ebp+8) *Curr-block-depth)
    28623     (write-buffered *(ebp+8) "(push-n-zero-bytes ")
    28624     (write-int32-hex-buffered *(ebp+8) *(ebp+0xc))
    28625     (write-buffered *(ebp+8) ")\n")
    28626     (emit-indent *(ebp+8) *Curr-block-depth)
    28627     (write-buffered *(ebp+8) "68/push ")
    28628     (write-int32-hex-buffered *(ebp+8) *(ebp+0xc))
    28629     (write-buffered *(ebp+8) "/imm32\n")
    28630 $emit-array-data-initialization:end:
    28631     # . epilogue
    28632     89/<- %esp 5/r32/ebp
    28633     5d/pop-to-ebp
    28634     c3/return
    28635
    28636 emit-stream-data-initialization:  # out: (addr buffered-file), n: int, type: (addr type-tree), err: (addr buffered-file), ed: (addr exit-descriptor)
    28637     # . prologue
    28638     55/push-ebp
    28639     89/<- %ebp 4/r32/esp
    28640     # . save registers
    28641     50/push-eax
    28642     # Optimization: if it's a stream of bytes, don't initialize.
    28643     #
    28644     # We often construct large temporary streams on the stack for 'trace'
    28645     # statements. Initializing such streams can significantly slow programs
    28646     # down.
    28647     #
    28648     # Mu doesn't really depend on initializing stream contents for type- or
    28649     # memory-safety; we're mostly doing so to make it easy to debug unsafe
    28650     # SubX code that misuses stream objects by manipulating read/write
    28651     # pointers. But you can't _really_ protect from unsafe SubX, so I think we
    28652     # don't give up much safety or security here.
    28653     {
    28654       (stream-element-type-id *(ebp+0x10) *(ebp+0x14) *(ebp+0x18))  # => eax
    28655       3d/compare-eax-and 8/imm32/byte
    28656       75/jump-if-!= break/disp8
    28657       (emit-indent *(ebp+8) *Curr-block-depth)
    28658       (write-buffered *(ebp+8) "81 5/subop/subtract %esp ")
    28659       (write-int32-hex-buffered *(ebp+8) *(ebp+0xc))
    28660       (write-buffered *(ebp+8) "/imm32\n")
    28661       eb/jump $emit-stream-data-initialization:emit-length/disp8
    28662     }
    28663     (emit-indent *(ebp+8) *Curr-block-depth)
    28664     (write-buffered *(ebp+8) "(push-n-zero-bytes ")
    28665     (write-int32-hex-buffered *(ebp+8) *(ebp+0xc))
    28666     (write-buffered *(ebp+8) ")\n")
    28667 $emit-stream-data-initialization:emit-length:
    28668     (emit-indent *(ebp+8) *Curr-block-depth)
    28669     (write-buffered *(ebp+8) "68/push ")
    28670     (write-int32-hex-buffered *(ebp+8) *(ebp+0xc))
    28671     (write-buffered *(ebp+8) "/imm32\n")
    28672 $emit-stream-data-initialization:end:
    28673     # . restore registers
    28674     58/pop-to-eax
    28675     # . epilogue
    28676     89/<- %esp 5/r32/ebp
    28677     5d/pop-to-ebp
    28678     c3/return
    28679
    28680 emit-subx-stmt:  # out: (addr buffered-file), stmt: (addr stmt), primitives: (addr primitive), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    28681     # . prologue
    28682     55/push-ebp
    28683     89/<- %ebp 4/r32/esp
    28684     # . save registers
    28685     50/push-eax
    28686     51/push-ecx
    28687     # - some special-case primitives that don't actually use the 'primitives' data structure
    28688     # var op/ecx: (addr array byte) = lookup(stmt->operation)
    28689     8b/-> *(ebp+0xc) 1/r32/ecx
    28690     (lookup *(ecx+4) *(ecx+8))  # Stmt1-operation Stmt1-operation => eax
    28691     89/<- %ecx 0/r32/eax
    28692     # copy byte (can be a primitive except we need to emit a second instruction)
    28693     {
    28694       # if (!string-equal?(stmt->operation, "copy-byte")) break
    28695       (string-equal? %ecx "copy-byte")  # => eax
    28696       3d/compare-eax-and 0/imm32/false
    28697       0f 84/jump-if-= break/disp32
    28698       (translate-mu-copy-byte-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
    28699       e9/jump $emit-subx-stmt:end/disp32
    28700     }
    28701     # copy-byte-to can be a primitive; writes to memory don't need to clear surrounding bytes
    28702     # array size
    28703     {
    28704       # if (!string-equal?(stmt->operation, "length")) break
    28705       (string-equal? %ecx "length")  # => eax
    28706       3d/compare-eax-and 0/imm32/false
    28707       0f 84/jump-if-= break/disp32
    28708       (translate-mu-length-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
    28709       e9/jump $emit-subx-stmt:end/disp32
    28710     }
    28711     # index into array
    28712     {
    28713       # if (!string-equal?(stmt->operation, "index")) break
    28714       (string-equal? %ecx "index")  # => eax
    28715       3d/compare-eax-and 0/imm32/false
    28716       0f 84/jump-if-= break/disp32
    28717       (translate-mu-index-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
    28718       e9/jump $emit-subx-stmt:end/disp32
    28719     }
    28720     # compute-offset for index into array
    28721     {
    28722       # if (!string-equal?(stmt->operation, "compute-offset")) break
    28723       (string-equal? %ecx "compute-offset")  # => eax
    28724       3d/compare-eax-and 0/imm32/false
    28725       0f 84/jump-if-= break/disp32
    28726       (translate-mu-compute-index-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
    28727       e9/jump $emit-subx-stmt:end/disp32
    28728     }
    28729     # get field from record
    28730     {
    28731       # if (!string-equal?(stmt->operation, "get")) break
    28732       (string-equal? %ecx "get")  # => eax
    28733       3d/compare-eax-and 0/imm32/false
    28734       0f 84/jump-if-= break/disp32
    28735       (translate-mu-get-stmt *(ebp+8) *(ebp+0xc))
    28736       e9/jump $emit-subx-stmt:end/disp32
    28737     }
    28738     # allocate scalar
    28739     {
    28740       # if (!string-equal?(stmt->operation, "allocate")) break
    28741       (string-equal? %ecx "allocate")  # => eax
    28742       3d/compare-eax-and 0/imm32/false
    28743       0f 84/jump-if-= break/disp32
    28744       (translate-mu-allocate-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
    28745       e9/jump $emit-subx-stmt:end/disp32
    28746     }
    28747     # copy-object
    28748     {
    28749       # if (!string-equal?(stmt->operation, "copy-object")) break
    28750       (string-equal? %ecx "copy-object")  # => eax
    28751       3d/compare-eax-and 0/imm32/false
    28752       0f 84/jump-if-= break/disp32
    28753       (translate-mu-copy-object-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
    28754       e9/jump $emit-subx-stmt:end/disp32
    28755     }
    28756     # clear-object
    28757     {
    28758       # if (!string-equal?(stmt->operation, "clear-object")) break
    28759       (string-equal? %ecx "clear-object")  # => eax
    28760       3d/compare-eax-and 0/imm32/false
    28761       0f 84/jump-if-= break/disp32
    28762       (translate-mu-clear-object-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
    28763       e9/jump $emit-subx-stmt:end/disp32
    28764     }
    28765     # allocate array
    28766     {
    28767       # if (!string-equal?(stmt->operation, "populate")) break
    28768       (string-equal? %ecx "populate")  # => eax
    28769       3d/compare-eax-and 0/imm32/false
    28770       0f 84/jump-if-= break/disp32
    28771       (translate-mu-populate-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
    28772       e9/jump $emit-subx-stmt:end/disp32
    28773     }
    28774     # allocate stream
    28775     {
    28776       # if (!string-equal?(stmt->operation, "populate-stream")) break
    28777       (string-equal? %ecx "populate-stream")  # => eax
    28778       3d/compare-eax-and 0/imm32/false
    28779       0f 84/jump-if-= break/disp32
    28780       (translate-mu-populate-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
    28781       e9/jump $emit-subx-stmt:end/disp32
    28782     }
    28783     # read from stream
    28784     {
    28785       # if (!string-equal?(stmt->operation, "read-from-stream")) break
    28786       (string-equal? %ecx "read-from-stream")  # => eax
    28787       3d/compare-eax-and 0/imm32/false
    28788       0f 84/jump-if-= break/disp32
    28789       (translate-mu-read-from-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
    28790       e9/jump $emit-subx-stmt:end/disp32
    28791     }
    28792     # write to stream
    28793     {
    28794       # if (!string-equal?(stmt->operation, "write-to-stream")) break
    28795       (string-equal? %ecx "write-to-stream")  # => eax
    28796       3d/compare-eax-and 0/imm32/false
    28797       0f 84/jump-if-= break/disp32
    28798       (translate-mu-write-to-stream-stmt *(ebp+8) *(ebp+0xc) *(ebp+0x18) *(ebp+0x1c))
    28799       e9/jump $emit-subx-stmt:end/disp32
    28800     }
    28801     # - optimizations
    28802     # if copy instruction has same register in source and destination, emit nothing
    28803     (redundant-copy? *(ebp+0xc))  # => eax
    28804     3d/compare-eax-and 0/imm32/false
    28805     75/jump-if-!= $emit-subx-stmt:end/disp8
    28806     # - if stmt matches a primitive, emit it
    28807     {
    28808 $emit-subx-stmt:check-for-primitive:
    28809       # var curr/eax: (addr primitive)
    28810       (find-matching-primitive *(ebp+0x10) *(ebp+0xc))  # primitives, stmt => eax
    28811       3d/compare-eax-and 0/imm32
    28812       74/jump-if-= break/disp8
    28813 $emit-subx-stmt:primitive:
    28814       (emit-subx-primitive *(ebp+8) *(ebp+0xc) %eax)  # out, stmt, curr
    28815       e9/jump $emit-subx-stmt:end/disp32
    28816     }
    28817     # - otherwise emit a call
    28818 $emit-subx-stmt:call:
    28819     (emit-call *(ebp+8) *(ebp+0xc))
    28820 $emit-subx-stmt:end:
    28821     # . restore registers
    28822     59/pop-to-ecx
    28823     58/pop-to-eax
    28824     # . epilogue
    28825     89/<- %esp 5/r32/ebp
    28826     5d/pop-to-ebp
    28827     c3/return
    28828
    28829 redundant-copy?:  # stmt: (addr stmt) -> result/eax: boolean
    28830     # . prologue
    28831     55/push-ebp
    28832     89/<- %ebp 4/r32/esp
    28833     # . save registers
    28834     56/push-esi
    28835     57/push-edi
    28836     # esi = stmt
    28837     8b/-> *(ebp+8) 6/r32/esi
    28838     # if stmt->operation != "copy" return false
    28839     (lookup *(esi+4) *(esi+8))  # Stmt1-operation Stmt1-operation => eax
    28840     (string-equal? %eax "copy")  # => eax
    28841     3d/compare-eax-and 0/imm32/false
    28842     0f 84/jump-if-= $redundant-copy?:end/disp32
    28843     # var output-reg/edi: (addr stmt-var) = stmt->outputs->value->register
    28844     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    28845     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    28846     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    28847     # . if output-reg == null, return false
    28848     3d/compare-eax-and 0/imm32
    28849     74/jump-if-= $redundant-copy?:end/disp8
    28850     89/<- %edi 0/r32/eax
    28851     # return (inout->value->register == output->value->register)
    28852     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    28853     # . if inout->is-deref return false
    28854     81 7/subop/compare *(eax+0x10) 0/imm32/false  # Stmt-var-is-deref
    28855     {
    28856       74/jump-if-= break/disp8
    28857       b8/copy-to-eax 0/imm32/false
    28858       e9/jump $redundant-copy?:end/disp32
    28859     }
    28860     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    28861     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    28862     # . if inout-reg == null, return false
    28863     3d/compare-eax-and 0/imm32
    28864     74/jump-if-= $redundant-copy?:end/disp8
    28865     (string-equal? %eax %edi)  # => eax
    28866 $redundant-copy?:end:
    28867     # . restore registers
    28868     5f/pop-to-edi
    28869     5e/pop-to-esi
    28870     # . epilogue
    28871     89/<- %esp 5/r32/ebp
    28872     5d/pop-to-ebp
    28873     c3/return
    28874
    28875 translate-mu-length-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
    28876     # . prologue
    28877     55/push-ebp
    28878     89/<- %ebp 4/r32/esp
    28879     # . save registers
    28880     50/push-eax
    28881     51/push-ecx
    28882     52/push-edx
    28883     53/push-ebx
    28884     56/push-esi
    28885     # esi = stmt
    28886     8b/-> *(ebp+0xc) 6/r32/esi
    28887     # var base/ebx: (addr var) = stmt->inouts[0]->value
    28888     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    28889     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    28890     89/<- %ebx 0/r32/eax
    28891     # var elemsize/ecx: int = array-element-size(base)
    28892     (array-element-size %ebx *(ebp+0x10) *(ebp+0x14))  # => eax
    28893     89/<- %ecx 0/r32/eax
    28894     # var outreg/edx: (addr array byte) = stmt->outputs[0]->value->register
    28895     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    28896     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    28897     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    28898     89/<- %edx 0/r32/eax
    28899     # if elemsize == 1
    28900     {
    28901       81 7/subop/compare %ecx 1/imm32
    28902       75/jump-if-!= break/disp8
    28903 $translate-mu-length-stmt:size-1:
    28904       (emit-save-size-to *(ebp+8) %ebx %edx)
    28905       e9/jump $translate-mu-length-stmt:end/disp32
    28906     }
    28907     # if elemsize is a power of 2 less than 256
    28908     {
    28909       (power-of-2? %ecx *(ebp+0x10) *(ebp+0x14))  # => eax
    28910       3d/compare-eax-and 0/imm32/false
    28911       74/jump-if-= break/disp8
    28912       81 7/subop/compare %ecx 0xff/imm32
    28913       7f/jump-if-> break/disp8
    28914 $translate-mu-length-stmt:size-power-of-2:
    28915       (emit-save-size-to *(ebp+8) %ebx %edx)
    28916       (emit-divide-by-shift-right *(ebp+8) %edx %ecx)
    28917       e9/jump $translate-mu-length-stmt:end/disp32
    28918     }
    28919     # otherwise, the complex case
    28920     # . emit register spills
    28921     {
    28922 $translate-mu-length-stmt:complex:
    28923       (string-equal? %edx "eax")  # => eax
    28924       3d/compare-eax-and 0/imm32/false
    28925       75/break-if-!= break/disp8
    28926       (emit-indent *(ebp+8) *Curr-block-depth)
    28927       (write-buffered *(ebp+8) "50/push-eax\n")
    28928     }
    28929     {
    28930       (string-equal? %edx "ecx")  # => eax
    28931       3d/compare-eax-and 0/imm32/false
    28932       75/break-if-!= break/disp8
    28933       (emit-indent *(ebp+8) *Curr-block-depth)
    28934       (write-buffered *(ebp+8) "51/push-ecx\n")
    28935     }
    28936     {
    28937       (string-equal? %edx "edx")  # => eax
    28938       3d/compare-eax-and 0/imm32/false
    28939       75/break-if-!= break/disp8
    28940       (emit-indent *(ebp+8) *Curr-block-depth)
    28941       (write-buffered *(ebp+8) "52/push-edx\n")
    28942     }
    28943     # .
    28944     (emit-save-size-to *(ebp+8) %ebx "eax")
    28945     (emit-indent *(ebp+8) *Curr-block-depth)
    28946     (write-buffered *(ebp+8) "31/xor %edx 2/r32/edx\n")
    28947     (emit-indent *(ebp+8) *Curr-block-depth)
    28948     (write-buffered *(ebp+8) "b9/copy-to-ecx ")
    28949     (write-int32-hex-buffered *(ebp+8) %ecx)
    28950     (write-buffered *(ebp+8) "/imm32\n")
    28951     (emit-indent *(ebp+8) *Curr-block-depth)
    28952     (write-buffered *(ebp+8) "f7 7/subop/idiv-eax-edx-by %ecx\n")
    28953     {
    28954       (string-equal? %edx "eax")  # => eax
    28955       3d/compare-eax-and 0/imm32/false
    28956       75/break-if-!= break/disp8
    28957       (emit-indent *(ebp+8) *Curr-block-depth)
    28958       (write-buffered *(ebp+8) "89/<- %")
    28959       (write-buffered *(ebp+8) %edx)
    28960       (write-buffered *(ebp+8) " 0/r32/eax\n")
    28961     }
    28962     # . emit register restores
    28963     {
    28964       (string-equal? %edx "edx")  # => eax
    28965       3d/compare-eax-and 0/imm32/false
    28966       75/break-if-!= break/disp8
    28967       (emit-indent *(ebp+8) *Curr-block-depth)
    28968       (write-buffered *(ebp+8) "5a/pop-to-edx\n")
    28969     }
    28970     {
    28971       (string-equal? %edx "ecx")  # => eax
    28972       3d/compare-eax-and 0/imm32/false
    28973       75/break-if-!= break/disp8
    28974       (emit-indent *(ebp+8) *Curr-block-depth)
    28975       (write-buffered *(ebp+8) "59/pop-to-ecx\n")
    28976     }
    28977     {
    28978       (string-equal? %edx "eax")  # => eax
    28979       3d/compare-eax-and 0/imm32/false
    28980       75/break-if-!= break/disp8
    28981       (emit-indent *(ebp+8) *Curr-block-depth)
    28982       (write-buffered *(ebp+8) "58/pop-to-eax\n")
    28983     }
    28984 $translate-mu-length-stmt:end:
    28985     # . restore registers
    28986     5e/pop-to-esi
    28987     5b/pop-to-ebx
    28988     5a/pop-to-edx
    28989     59/pop-to-ecx
    28990     58/pop-to-eax
    28991     # . epilogue
    28992     89/<- %esp 5/r32/ebp
    28993     5d/pop-to-ebp
    28994     c3/return
    28995
    28996 array-element-size:  # arr: (addr var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
    28997     # . prologue
    28998     55/push-ebp
    28999     89/<- %ebp 4/r32/esp
    29000     #
    29001     (array-element-type-id *(ebp+8) *(ebp+0xc) *(ebp+0x10))  # => eax
    29002     (size-of-type-id-as-array-element %eax)  # => eax
    29003 $array-element-size:end:
    29004     # . epilogue
    29005     89/<- %esp 5/r32/ebp
    29006     5d/pop-to-ebp
    29007     c3/return
    29008
    29009 array-element-type-id:  # v: (addr var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: type-id
    29010     # precondition: n is positive
    29011     # . prologue
    29012     55/push-ebp
    29013     89/<- %ebp 4/r32/esp
    29014     #
    29015     8b/-> *(ebp+8) 0/r32/eax
    29016     # var t/eax: (addr type-tree)
    29017     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    29018     # if t == 0 abort
    29019     3d/compare-eax-with 0/imm32
    29020     0f 84/jump-if-== $array-element-type-id:error0/disp32
    29021     # if t->is-atom? abort
    29022     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
    29023     0f 85/jump-if-!= $array-element-type-id:error1/disp32
    29024     # if (t->left == addr) t = t->right
    29025     {
    29026       50/push-eax
    29027       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    29028       (simple-mu-type? %eax 2)  # addr => eax
    29029       3d/compare-eax-with 0/imm32/false
    29030       58/pop-to-eax
    29031       74/jump-if-= break/disp8
    29032 $array-element-type-id:skip-addr:
    29033       (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
    29034     }
    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     # if t->left != array abort
    29042     {
    29043       50/push-eax
    29044       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    29045       (simple-mu-type? %eax 3)  # array => eax
    29046       3d/compare-eax-with 0/imm32/false
    29047       58/pop-to-eax
    29048 $array-element-type-id:no-array:
    29049       0f 84/jump-if-= $array-element-type-id:error2/disp32
    29050     }
    29051 $array-element-type-id:skip-array:
    29052     # t = t->right
    29053     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
    29054     # if t == 0 abort
    29055     3d/compare-eax-with 0/imm32
    29056     0f 84/jump-if-= $array-element-type-id:error2/disp32
    29057     # if t->is-atom? abort
    29058     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
    29059     0f 85/jump-if-!= $array-element-type-id:error2/disp32
    29060     # t = t->left
    29061     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    29062     # if (!t->is-atom?) t = t->left     # TODO: assumes array element size can be determined from just first word of array element type
    29063     # if (t->is-atom == false) t = lookup(t->left)
    29064     {
    29065       81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
    29066       75/jump-if-!= break/disp8
    29067       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    29068     }
    29069     # return t->value
    29070     8b/-> *(eax+4) 0/r32/eax  # Type-tree-value
    29071 $array-element-type-id:end:
    29072     # . epilogue
    29073     89/<- %esp 5/r32/ebp
    29074     5d/pop-to-ebp
    29075     c3/return
    29076
    29077 $array-element-type-id:error0:
    29078     (write-buffered *(ebp+0xc) "array-element-type-id: var '")
    29079     50/push-eax
    29080     8b/-> *(ebp+8) 0/r32/eax
    29081     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    29082     (write-buffered *(ebp+0xc) %eax)
    29083     58/pop-to-eax
    29084     (write-buffered *(ebp+0xc) "' has no type\n")
    29085     (flush *(ebp+0xc))
    29086     (stop *(ebp+0x10) 1)
    29087     # never gets here
    29088
    29089 $array-element-type-id:error1:
    29090     (write-buffered *(ebp+0xc) "array-element-type-id: var '")
    29091     50/push-eax
    29092     8b/-> *(ebp+8) 0/r32/eax
    29093     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    29094     (write-buffered *(ebp+0xc) %eax)
    29095     58/pop-to-eax
    29096     (write-buffered *(ebp+0xc) "' has atomic type ")
    29097     (write-int32-hex-buffered *(ebp+0xc) *(eax+4))  # Type-tree-value
    29098     (write-buffered *(ebp+0xc) Newline)
    29099     (flush *(ebp+0xc))
    29100     (stop *(ebp+0x10) 1)
    29101     # never gets here
    29102
    29103 $array-element-type-id:error2:
    29104     (write-buffered *(ebp+0xc) "array-element-type-id: var '")
    29105     50/push-eax
    29106     8b/-> *(ebp+8) 0/r32/eax
    29107     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    29108     (write-buffered *(ebp+0xc) %eax)
    29109     58/pop-to-eax
    29110     (write-buffered *(ebp+0xc) "' has non-array type\n")
    29111     (flush *(ebp+0xc))
    29112     (stop *(ebp+0x10) 1)
    29113     # never gets here
    29114
    29115 size-of-type-id-as-array-element:  # t: type-id -> result/eax: int
    29116     # . prologue
    29117     55/push-ebp
    29118     89/<- %ebp 4/r32/esp
    29119     # eax = t
    29120     8b/-> *(ebp+8) 0/r32/eax
    29121     # if t is 'byte', size is 1
    29122     3d/compare-eax-and 8/imm32/byte
    29123     {
    29124       75/jump-if-!= break/disp8
    29125       b8/copy-to-eax 1/imm32
    29126       eb/jump $size-of-type-id-as-array-element:end/disp8
    29127     }
    29128     # otherwise proceed as usual
    29129     (size-of-type-id %eax)  # => eax
    29130 $size-of-type-id-as-array-element:end:
    29131     # . epilogue
    29132     89/<- %esp 5/r32/ebp
    29133     5d/pop-to-ebp
    29134     c3/return
    29135
    29136 stream-element-type-id:  # type: (addr type-tree), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: type-id
    29137     # precondition: n is positive
    29138     # . prologue
    29139     55/push-ebp
    29140     89/<- %ebp 4/r32/esp
    29141     # eax = type
    29142     8b/-> *(ebp+8) 0/r32/eax
    29143     # if type == 0 abort
    29144     3d/compare-eax-with 0/imm32
    29145     0f 84/jump-if-== $stream-element-type-id:error0/disp32
    29146     # if type->is-atom? abort
    29147     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
    29148     0f 85/jump-if-!= $stream-element-type-id:error1/disp32
    29149     # if (type->left == addr) type = type->right
    29150     {
    29151       50/push-eax
    29152       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    29153       (simple-mu-type? %eax 2)  # addr => eax
    29154       3d/compare-eax-with 0/imm32/false
    29155       58/pop-to-eax
    29156       74/jump-if-= break/disp8
    29157 $stream-element-type-id:skip-addr:
    29158       (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
    29159     }
    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     # if type->left != stream abort
    29167     {
    29168       50/push-eax
    29169       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    29170       (simple-mu-type? %eax 0xb)  # stream => eax
    29171       3d/compare-eax-with 0/imm32/false
    29172       58/pop-to-eax
    29173 $stream-element-type-id:no-stream:
    29174       0f 84/jump-if-= $stream-element-type-id:error2/disp32
    29175     }
    29176 $stream-element-type-id:skip-stream:
    29177     # type = type->right
    29178     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
    29179     # if type == 0 abort
    29180     3d/compare-eax-with 0/imm32
    29181     0f 84/jump-if-= $stream-element-type-id:error2/disp32
    29182     # if type->is-atom? abort
    29183     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
    29184     0f 85/jump-if-!= $stream-element-type-id:error2/disp32
    29185     # t = type->left
    29186     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    29187     # if (!type->is-atom?) type = type->left     # TODO: assumes stream element size can be determined from just first word of stream element type
    29188     {
    29189       81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
    29190       75/jump-if-!= break/disp8
    29191       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    29192     }
    29193     # return type->value
    29194     8b/-> *(eax+4) 0/r32/eax  # Type-tree-value
    29195 $stream-element-type-id:end:
    29196     # . epilogue
    29197     89/<- %esp 5/r32/ebp
    29198     5d/pop-to-ebp
    29199     c3/return
    29200
    29201 $stream-element-type-id:error0:
    29202     (write-buffered *(ebp+0xc) "stream-element-type-id: var '")
    29203     50/push-eax
    29204     8b/-> *(ebp+8) 0/r32/eax
    29205     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    29206     (write-buffered *(ebp+0xc) %eax)
    29207     58/pop-to-eax
    29208     (write-buffered *(ebp+0xc) "' has no type\n")
    29209     (flush *(ebp+0xc))
    29210     (stop *(ebp+0x10) 1)
    29211     # never gets here
    29212
    29213 $stream-element-type-id:error1:
    29214     (write-buffered *(ebp+0xc) "stream-element-type-id: var '")
    29215     50/push-eax
    29216     8b/-> *(ebp+8) 0/r32/eax
    29217     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    29218     (write-buffered *(ebp+0xc) %eax)
    29219     58/pop-to-eax
    29220     (write-buffered *(ebp+0xc) "' has atomic type ")
    29221     (write-int32-hex-buffered *(ebp+0xc) *(eax+4))  # Type-tree-value
    29222     (write-buffered *(ebp+0xc) Newline)
    29223     (flush *(ebp+0xc))
    29224     (stop *(ebp+0x10) 1)
    29225     # never gets here
    29226
    29227 $stream-element-type-id:error2:
    29228     (write-buffered *(ebp+0xc) "stream-element-type-id: var '")
    29229     50/push-eax
    29230     8b/-> *(ebp+8) 0/r32/eax
    29231     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    29232     (write-buffered *(ebp+0xc) %eax)
    29233     58/pop-to-eax
    29234     (write-buffered *(ebp+0xc) "' has non-stream type\n")
    29235     (flush *(ebp+0xc))
    29236     (stop *(ebp+0x10) 1)
    29237     # never gets here
    29238
    29239 emit-save-size-to:  # out: (addr buffered-file), base: (addr var), outreg: (addr array byte)
    29240     # . prologue
    29241     55/push-ebp
    29242     89/<- %ebp 4/r32/esp
    29243     # . save registers
    29244     50/push-eax
    29245     53/push-ebx
    29246     # ebx = base
    29247     8b/-> *(ebp+0xc) 3/r32/ebx
    29248     (emit-indent *(ebp+8) *Curr-block-depth)
    29249     (write-buffered *(ebp+8) "8b/-> *")
    29250     # if base is an (addr array ...) in a register
    29251     {
    29252       81 7/subop/compare *(ebx+0x18)) 0/imm32  # Var-register
    29253       74/jump-if-= break/disp8
    29254 $emit-save-size-to:emit-base-from-register:
    29255       (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
    29256       (write-buffered *(ebp+8) %eax)
    29257       eb/jump $emit-save-size-to:emit-output/disp8
    29258     }
    29259     # otherwise if base is an (array ...) on the stack
    29260     {
    29261       81 7/subop/compare *(ebx+0x14)) 0/imm32  # Var-offset
    29262       74/jump-if-= break/disp8
    29263 $emit-save-size-to:emit-base-from-stack:
    29264       (write-buffered *(ebp+8) "(ebp+")
    29265       (write-int32-hex-buffered *(ebp+8) *(ebx+0x14))  # Var-offset
    29266       (write-buffered *(ebp+8) ")")
    29267     }
    29268 $emit-save-size-to:emit-output:
    29269     (write-buffered *(ebp+8) " ")
    29270     (get Mu-registers *(ebp+0x10) 0xc "Mu-registers")  # => eax
    29271     (write-int32-hex-buffered *(ebp+8) *eax)
    29272     (write-buffered *(ebp+8) "/r32\n")
    29273 $emit-save-size-to:end:
    29274     # . restore registers
    29275     5b/pop-to-ebx
    29276     58/pop-to-eax
    29277     # . epilogue
    29278     89/<- %esp 5/r32/ebp
    29279     5d/pop-to-ebp
    29280     c3/return
    29281
    29282 emit-divide-by-shift-right:  # out: (addr buffered-file), reg: (addr array byte), size: int
    29283     # . prologue
    29284     55/push-ebp
    29285     89/<- %ebp 4/r32/esp
    29286     # . save registers
    29287     50/push-eax
    29288     #
    29289     (emit-indent *(ebp+8) *Curr-block-depth)
    29290     (write-buffered *(ebp+8) "c1/shift 5/subop/>> %")
    29291     (write-buffered *(ebp+8) *(ebp+0xc))
    29292     (write-buffered *(ebp+8) Space)
    29293     (num-shift-rights *(ebp+0x10))  # => eax
    29294     (write-int32-hex-buffered *(ebp+8) %eax)
    29295     (write-buffered *(ebp+8) "/imm8\n")
    29296 $emit-divide-by-shift-right:end:
    29297     # . restore registers
    29298     58/pop-to-eax
    29299     # . epilogue
    29300     89/<- %esp 5/r32/ebp
    29301     5d/pop-to-ebp
    29302     c3/return
    29303
    29304 translate-mu-copy-byte-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
    29305     # . prologue
    29306     55/push-ebp
    29307     89/<- %ebp 4/r32/esp
    29308     # . save registers
    29309     50/push-eax
    29310     56/push-esi
    29311     # esi = stmt
    29312     8b/-> *(ebp+0xc) 6/r32/esi
    29313     #
    29314     (emit-indent *(ebp+8) *Curr-block-depth)
    29315     (write-buffered *(ebp+8) "8a/byte->")
    29316     # emit stmt->inouts[0]
    29317     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    29318     (emit-subx-var-as-rm32 *(ebp+8) %eax)
    29319     # emit /r32 for stmt->outputs[0]->register
    29320     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    29321     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    29322     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    29323     (maybe-get Mu-registers %eax 0xc)  # => eax: (addr register-index)
    29324     (write-buffered *(ebp+8) Space)
    29325     (write-int32-hex-buffered *(ebp+8) *eax)
    29326     (write-buffered *(ebp+8) "/r32\n")
    29327     # clear rest of register
    29328     (emit-indent *(ebp+8) *Curr-block-depth)
    29329     (write-buffered *(ebp+8) "81 4/subop/and %")
    29330     8b/-> *(ebp+0xc) 0/r32/eax
    29331     (lookup *(esi+0x14) *(esi+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    29332     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    29333     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    29334     (write-buffered *(ebp+8) %eax)
    29335     (write-buffered *(ebp+8) " 0xff/imm32\n")
    29336 $translate-mu-copy-byte-stmt:end:
    29337     # . restore registers
    29338     5e/pop-to-esi
    29339     58/pop-to-eax
    29340     # . epilogue
    29341     89/<- %esp 5/r32/ebp
    29342     5d/pop-to-ebp
    29343     c3/return
    29344
    29345 # a little different from other translate- functions; notice the extra 'fn' argument
    29346 translate-mu-index-stmt:  # out: (addr buffered-file), stmt: (addr stmt), fn: (addr function), err: (addr buffered-file), ed: (addr exit-descriptor)
    29347     # . prologue
    29348     55/push-ebp
    29349     89/<- %ebp 4/r32/esp
    29350     # . save registers
    29351     53/push-ebx
    29352     # ebx = stmt
    29353     8b/-> *(ebp+0xc) 3/r32/ebx
    29354     # var base/ebx: (addr var) = stmt->inouts[0]
    29355     (lookup *(ebx+0xc) *(ebx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    29356     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    29357     89/<- %ebx 0/r32/eax
    29358     # emit bounds-check
    29359     (emit-mu-index-bounds-check *(ebp+8) *(ebp+0xc) *(ebp+0x10) *(ebp+0x14) *(ebp+0x18))
    29360     # if (var->register) do one thing
    29361     {
    29362       81 7/subop/compare *(ebx+0x18) 0/imm32  # Var-register
    29363       74/jump-if-= break/disp8
    29364       # TODO: ensure there's no dereference
    29365       (translate-mu-index-stmt-with-array-in-register *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))
    29366       eb/jump $translate-mu-index-stmt:end/disp8
    29367     }
    29368     # if (var->offset) do a different thing
    29369     {
    29370       81 7/subop/compare *(ebx+0x14) 0/imm32  # Var-offset
    29371       74/jump-if-= break/disp8
    29372       # TODO: ensure there's no dereference
    29373       (translate-mu-index-stmt-with-array-on-stack *(ebp+8) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))
    29374       eb/jump $translate-mu-index-stmt:end/disp8
    29375     }
    29376 $translate-mu-index-stmt:end:
    29377     # . restore registers
    29378     5b/pop-to-ebx
    29379     # . epilogue
    29380     89/<- %esp 5/r32/ebp
    29381     5d/pop-to-ebp
    29382     c3/return
    29383
    29384 $translate-mu-index-stmt:error1:
    29385     (write-buffered *(ebp+0x14) "couldn't translate an index instruction. second (index) input must either lie in a register or be a literal\n")
    29386     (flush *(ebp+0x14))
    29387     (stop *(ebp+0x18) 1)
    29388     # never gets here
    29389
    29390 $translate-mu-index-stmt:error2:
    29391     (write-buffered *(ebp+0x14) "couldn't translate an index instruction. second (index) input when in a register must be an int or offset\n")
    29392     (flush *(ebp+0x14))
    29393     (stop *(ebp+0x18) 1)
    29394     # never gets here
    29395
    29396 emit-mu-index-bounds-check:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
    29397     # . prologue
    29398     55/push-ebp
    29399     89/<- %ebp 4/r32/esp
    29400     # . save registers
    29401     50/push-eax
    29402     51/push-ecx
    29403     52/push-edx
    29404     53/push-ebx
    29405     # ecx = stmt
    29406     8b/-> *(ebp+0xc) 1/r32/ecx
    29407     #
    29408     (emit-indent *(ebp+8) *Curr-block-depth)
    29409     (write-buffered *(ebp+8) "(__check-mu-array-bounds ")
    29410 $emit-mu-index-bounds-check:compute-base:
    29411     # var base/ebx: (addr var) = inouts[0]
    29412     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    29413     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    29414     89/<- %ebx 0/r32/eax
    29415 $emit-mu-index-bounds-check:emit-index:
    29416     # var index/edx: (addr var) = inouts[1]
    29417     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    29418     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    29419     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    29420     89/<- %edx 0/r32/eax
    29421     # if index->register, print its code
    29422     81 7/subop/compare *(edx+0x18) 0/imm32  # Var-register
    29423     {
    29424       0f 84/jump-if-= break/disp32
    29425 $emit-mu-index-bounds-check:emit-register-index:
    29426       (write-buffered *(ebp+8) "%")
    29427       (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
    29428       (write-buffered *(ebp+8) %eax)
    29429       eb/jump $emit-mu-index-bounds-check:index-done/disp8
    29430     }
    29431     # otherwise if index is a literal, print it
    29432 $emit-mu-index-bounds-check:emit-literal-index:
    29433     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
    29434     (simple-mu-type? %eax 0)  # => eax
    29435     3d/compare-eax-and 0/imm32/false
    29436     {
    29437       0f 84/jump-if-= break/disp32
    29438       (lookup *edx *(edx+4))  # Var-name Var-name => eax
    29439       (write-buffered *(ebp+8) %eax)
    29440     }
    29441 $emit-mu-index-bounds-check:index-done:
    29442     (write-buffered *(ebp+8) " ")
    29443 $emit-mu-index-bounds-check:emit-element-size:
    29444     # if index is a literal or int, print size of array element
    29445     {
    29446       {
    29447         (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
    29448         (simple-mu-type? %eax 0)  # literal => eax
    29449         3d/compare-eax-and 0/imm32/false
    29450         75/jump-if-!= break/disp8
    29451         (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
    29452         (simple-mu-type? %eax 1)  # int => eax
    29453         3d/compare-eax-and 0/imm32/false
    29454         75/jump-if-!= break/disp8
    29455         eb/jump $emit-mu-index-bounds-check:emit-element-size-offset/disp8
    29456       }
    29457 $emit-mu-index-bounds-check:emit-int-register-index:
    29458       (array-element-size %ebx *(ebp+0x14) *(ebp+0x18))  # => eax
    29459       (write-int32-hex-buffered *(ebp+8) %eax)
    29460       e9/jump $emit-mu-index-bounds-check:emit-base/disp32
    29461     }
    29462 $emit-mu-index-bounds-check:emit-element-size-offset:
    29463     # if index has type (offset ...), print "1"
    29464     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
    29465     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
    29466     {
    29467       75/jump-if-!= break/disp8
    29468       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    29469       (simple-mu-type? %eax 7)  # => eax
    29470       3d/compare-eax-and 0/imm32/false
    29471       {
    29472         0f 84/jump-if-= break/disp32
    29473 $emit-mu-index-bounds-check:emit-offset-register-index:
    29474         (write-buffered *(ebp+8) "1")
    29475       }
    29476     }
    29477 $emit-mu-index-bounds-check:emit-base:
    29478     # if base is in a register, print " *" base->register
    29479     81 7/subop/compare *(ebx+0x18) 0/imm32  # Var-register
    29480     {
    29481       74/jump-if-= break/disp8
    29482       (write-buffered *(ebp+8) " *")
    29483       (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
    29484       (write-buffered *(ebp+8) %eax)
    29485       e9/jump $emit-mu-index-bounds-check:emit-function-name/disp32
    29486     }
    29487     # otherwise print " *(ebp+" base->offset ")"
    29488     (write-buffered *(ebp+8) " *(ebp+")
    29489     (write-int32-hex-buffered *(ebp+8) *(ebx+0x14))  # Var-offset
    29490     (write-buffered *(ebp+8) ")")
    29491 $emit-mu-index-bounds-check:emit-function-name:
    29492     # " \"" function-name "\""
    29493     (write-buffered *(ebp+8) " \"")
    29494     8b/-> *(ebp+0x10) 1/r32/ecx
    29495     (lookup *ecx *(ecx+4))  # Function-name Function-name => eax
    29496     (write-buffered *(ebp+8) %eax)
    29497     (write-buffered *(ebp+8) "\"")
    29498 $emit-mu-index-bounds-check:emit-array-name:
    29499     # " \"" base->name "\""
    29500     (write-buffered *(ebp+8) " \"")
    29501     (lookup *ebx *(ebx+4))  # Var-name Var-name => eax
    29502     (write-buffered *(ebp+8) %eax)
    29503     (write-buffered *(ebp+8) "\")\n")
    29504 $emit-mu-index-bounds-check:end:
    29505     # . restore registers
    29506     5b/pop-to-ebx
    29507     5a/pop-to-edx
    29508     59/pop-to-ecx
    29509     58/pop-to-eax
    29510     # . epilogue
    29511     89/<- %esp 5/r32/ebp
    29512     5d/pop-to-ebp
    29513     c3/return
    29514
    29515 translate-mu-index-stmt-with-array-in-register:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
    29516     # . prologue
    29517     55/push-ebp
    29518     89/<- %ebp 4/r32/esp
    29519     # . save registers
    29520     50/push-eax
    29521     51/push-ecx
    29522     52/push-edx
    29523     53/push-ebx
    29524     # ecx = stmt
    29525     8b/-> *(ebp+0xc) 1/r32/ecx
    29526     # var base/ebx: (addr var) = inouts[0]
    29527     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    29528     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    29529     89/<- %ebx 0/r32/eax
    29530     # emit null check
    29531     (emit-indent *(ebp+8) *Curr-block-depth)
    29532     (write-buffered *(ebp+8) "81 7/subop/compare %")
    29533     (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
    29534     (write-buffered *(ebp+8) %eax)
    29535     (write-buffered *(ebp+8) " 0/imm32\n")
    29536     (emit-indent *(ebp+8) *Curr-block-depth)
    29537     (write-buffered *(ebp+8) "0f 84/jump-if-= __mu-abort-null-index-base-address/disp32\n")
    29538     #
    29539     (emit-indent *(ebp+8) *Curr-block-depth)
    29540     (write-buffered *(ebp+8) "8d/copy-address *(")
    29541     # TODO: ensure inouts[0] is in a register and not dereferenced
    29542 $translate-mu-index-stmt-with-array-in-register:emit-base:
    29543     # print base->register " + "
    29544     (lookup *(ebx+0x18) *(ebx+0x1c))  # Var-register Var-register => eax
    29545     (write-buffered *(ebp+8) %eax)
    29546     (write-buffered *(ebp+8) " + ")
    29547     # var index/edx: (addr var) = inouts[1]
    29548     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    29549     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    29550     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    29551     89/<- %edx 0/r32/eax
    29552     # if index->register
    29553     81 7/subop/compare *(edx+0x18) 0/imm32  # Var-register
    29554     {
    29555       0f 84/jump-if-= break/disp32
    29556 $translate-mu-index-stmt-with-array-in-register:emit-register-index:
    29557       # if index is an int
    29558       (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
    29559       (simple-mu-type? %eax 1)  # int => eax
    29560       3d/compare-eax-and 0/imm32/false
    29561       {
    29562         0f 84/jump-if-= break/disp32
    29563 $translate-mu-index-stmt-with-array-in-register:emit-int-register-index:
    29564         # print index->register "<<" log2(array-element-size(base)) " + 4) "
    29565         # . index->register "<<"
    29566         (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
    29567         (write-buffered *(ebp+8) %eax)
    29568         (write-buffered *(ebp+8) "<<")
    29569         # . log2(array-element-size(base->type))
    29570         # we know size is a power of 2
    29571         (array-element-size %ebx *(ebp+0x10) *(ebp+0x14))  # => eax
    29572         (num-shift-rights %eax)  # => eax
    29573         (write-int32-hex-buffered *(ebp+8) %eax)
    29574         e9/jump $translate-mu-index-stmt-with-array-in-register:emit-register-index-done/disp32
    29575       }
    29576       # if index->type is any other atom, abort
    29577       (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
    29578       81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
    29579       0f 85/jump-if-!= $translate-mu-index-stmt:error2/disp32
    29580       # if index has type (offset ...)
    29581       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    29582       (simple-mu-type? %eax 7)  # => eax
    29583       3d/compare-eax-and 0/imm32/false
    29584       {
    29585         0f 84/jump-if-= break/disp32
    29586         # print index->register
    29587 $translate-mu-index-stmt-with-array-in-register:emit-offset-register-index:
    29588         (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
    29589         (write-buffered *(ebp+8) %eax)
    29590       }
    29591 $translate-mu-index-stmt-with-array-in-register:emit-register-index-done:
    29592       (write-buffered *(ebp+8) " + 4) ")
    29593       e9/jump $translate-mu-index-stmt-with-array-in-register:emit-output/disp32
    29594     }
    29595     # otherwise if index is a literal
    29596     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
    29597     (simple-mu-type? %eax 0)  # => eax
    29598     3d/compare-eax-and 0/imm32/false
    29599     {
    29600       0f 84/jump-if-= break/disp32
    29601 $translate-mu-index-stmt-with-array-in-register:emit-literal-index:
    29602       # var index-value/edx: int = parse-hex-int(index->name)
    29603       (lookup *edx *(edx+4))  # Var-name Var-name => eax
    29604       (parse-hex-int %eax)  # => eax
    29605       89/<- %edx 0/r32/eax
    29606       # offset = idx-value * array-element-size(base->type)
    29607       (array-element-size %ebx *(ebp+0x10) *(ebp+0x14))  # => eax
    29608       f7 4/subop/multiply-into-edx-eax %edx  # clobbers edx
    29609       # offset += 4 for array size
    29610       05/add-to-eax 4/imm32
    29611       # TODO: check edx for overflow
    29612       # print offset
    29613       (write-int32-hex-buffered *(ebp+8) %eax)
    29614       (write-buffered *(ebp+8) ") ")
    29615       e9/jump $translate-mu-index-stmt-with-array-in-register:emit-output/disp32
    29616     }
    29617     # otherwise abort
    29618     e9/jump $translate-mu-index-stmt:error1/disp32
    29619 $translate-mu-index-stmt-with-array-in-register:emit-output:
    29620     # outputs[0] "/r32"
    29621     8b/-> *(ebp+0xc) 1/r32/ecx
    29622     (lookup *(ecx+0x14) *(ecx+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    29623     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    29624     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    29625     (get Mu-registers %eax 0xc "Mu-registers")  # => eax: (addr int)
    29626     (write-int32-hex-buffered *(ebp+8) *eax)
    29627     (write-buffered *(ebp+8) "/r32\n")
    29628 $translate-mu-index-stmt-with-array-in-register:end:
    29629     # . restore registers
    29630     5b/pop-to-ebx
    29631     5a/pop-to-edx
    29632     59/pop-to-ecx
    29633     58/pop-to-eax
    29634     # . epilogue
    29635     89/<- %esp 5/r32/ebp
    29636     5d/pop-to-ebp
    29637     c3/return
    29638
    29639 translate-mu-index-stmt-with-array-on-stack:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
    29640     # . prologue
    29641     55/push-ebp
    29642     89/<- %ebp 4/r32/esp
    29643     # . save registers
    29644     50/push-eax
    29645     51/push-ecx
    29646     52/push-edx
    29647     53/push-ebx
    29648     #
    29649     (emit-indent *(ebp+8) *Curr-block-depth)
    29650     (write-buffered *(ebp+8) "8d/copy-address *(ebp + ")
    29651     # var curr/edx: (addr stmt-var) = lookup(stmt->inouts)
    29652     8b/-> *(ebp+0xc) 0/r32/eax
    29653     (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    29654     89/<- %edx 0/r32/eax
    29655     # var base/ecx: (addr var) = lookup(curr->value)
    29656     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    29657     89/<- %ecx 0/r32/eax
    29658     # var curr2/eax: (addr stmt-var) = lookup(curr->next)
    29659     (lookup *(edx+8) *(edx+0xc))  # Stmt-var-next Stmt-var-next => eax
    29660     # var index/edx: (handle var) = curr2->value
    29661     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    29662     89/<- %edx 0/r32/eax
    29663     # if index->register
    29664     81 7/subop/compare *(edx+0x18) 0/imm32  # Var-register
    29665     {
    29666       0f 84/jump-if-= break/disp32
    29667 $translate-mu-index-stmt-with-array-on-stack:emit-register-index:
    29668       # if index is an int
    29669       (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
    29670       (simple-mu-type? %eax 1)  # int => eax
    29671       3d/compare-eax-and 0/imm32/false
    29672       {
    29673         0f 84/jump-if-= break/disp32
    29674 $translate-mu-index-stmt-with-array-on-stack:emit-int-register-index:
    29675         # print index->register "<<" log2(array-element-size(base)) " + " base->offset+4
    29676         # . inouts[1]->register "<<"
    29677         (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
    29678         (write-buffered *(ebp+8) %eax)
    29679         (write-buffered *(ebp+8) "<<")
    29680         # . log2(array-element-size(base))
    29681         # TODO: ensure size is a power of 2
    29682         (array-element-size %ecx *(ebp+0x10) *(ebp+0x14))  # => eax
    29683         (num-shift-rights %eax)  # => eax
    29684         (write-int32-hex-buffered *(ebp+8) %eax)
    29685         #
    29686         (write-buffered *(ebp+8) " + ")
    29687         #
    29688         8b/-> *(ecx+0x14) 0/r32/eax  # Var-offset
    29689         05/add-to-eax 4/imm32  # for array length
    29690         (write-int32-hex-buffered *(ebp+8) %eax)
    29691         e9/jump $translate-mu-index-stmt-with-array-on-stack:emit-register-index-done/disp32
    29692       }
    29693       # if index->type is any other atom, abort
    29694       (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
    29695       81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
    29696       0f 85/jump-if-!= $translate-mu-index-stmt:error2/disp32
    29697       # if index has type (offset ...)
    29698       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    29699       (simple-mu-type? %eax 7)  # => eax
    29700       3d/compare-eax-and 0/imm32/false
    29701       {
    29702         0f 84/jump-if-= break/disp32
    29703         # print index->register
    29704 $translate-mu-index-stmt-with-array-on-stack:emit-offset-register-index:
    29705         (lookup *(edx+0x18) *(edx+0x1c))  # Var-register Var-register => eax
    29706         (write-buffered *(ebp+8) %eax)
    29707       }
    29708 $translate-mu-index-stmt-with-array-on-stack:emit-register-index-done:
    29709       (write-buffered *(ebp+8) ") ")
    29710       e9/jump $translate-mu-index-stmt-with-array-on-stack:emit-output/disp32
    29711     }
    29712     # otherwise if index is a literal
    29713     (lookup *(edx+8) *(edx+0xc))  # Var-type Var-type => eax
    29714     (simple-mu-type? %eax 0)  # => eax
    29715     3d/compare-eax-and 0/imm32/false
    29716     {
    29717       0f 84/jump-if-= break/disp32
    29718 $translate-mu-index-stmt-with-array-on-stack:emit-literal-index:
    29719       # var idx-value/edx: int = parse-hex-int(index->name)
    29720       (lookup *edx *(edx+4))  # Var-name Var-name => eax
    29721       (parse-hex-int %eax)  # Var-name => eax
    29722       89/<- %edx 0/r32/eax
    29723       # offset = idx-value * array-element-size(base)
    29724       (array-element-size %ecx *(ebp+0x10) *(ebp+0x14))  # => eax
    29725       f7 4/subop/multiply-into-edx-eax %edx  # clobbers edx
    29726       # offset += base->offset
    29727       03/add *(ecx+0x14) 0/r32/eax  # Var-offset
    29728       # offset += 4 for array size
    29729       05/add-to-eax 4/imm32
    29730       # TODO: check edx for overflow
    29731       # print offset
    29732       (write-int32-hex-buffered *(ebp+8) %eax)
    29733       (write-buffered *(ebp+8) ") ")
    29734       e9/jump $translate-mu-index-stmt-with-array-on-stack:emit-output/disp32
    29735     }
    29736     # otherwise abort
    29737     e9/jump $translate-mu-index-stmt:error1/disp32
    29738 $translate-mu-index-stmt-with-array-on-stack:emit-output:
    29739     # outputs[0] "/r32"
    29740     8b/-> *(ebp+0xc) 0/r32/eax
    29741     (lookup *(eax+0x14) *(eax+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    29742     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    29743     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    29744     (get Mu-registers %eax 0xc "Mu-registers")  # => eax: (addr int)
    29745     (write-int32-hex-buffered *(ebp+8) *eax)
    29746     (write-buffered *(ebp+8) "/r32\n")
    29747 $translate-mu-index-stmt-with-array-on-stack:end:
    29748     # . restore registers
    29749     5b/pop-to-ebx
    29750     5a/pop-to-edx
    29751     59/pop-to-ecx
    29752     58/pop-to-eax
    29753     # . epilogue
    29754     89/<- %esp 5/r32/ebp
    29755     5d/pop-to-ebp
    29756     c3/return
    29757
    29758 translate-mu-compute-index-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
    29759     # . prologue
    29760     55/push-ebp
    29761     89/<- %ebp 4/r32/esp
    29762     # . save registers
    29763     50/push-eax
    29764     51/push-ecx
    29765     52/push-edx
    29766     53/push-ebx
    29767     #
    29768     (emit-indent *(ebp+8) *Curr-block-depth)
    29769     (write-buffered *(ebp+8) "69/multiply")
    29770     # ecx = stmt
    29771     8b/-> *(ebp+0xc) 1/r32/ecx
    29772     # var first-inout/ebx: (addr stmt-var) = stmt->inouts[0]
    29773     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    29774     89/<- %ebx 0/r32/eax
    29775 $translate-mu-compute-index-stmt:emit-index:
    29776     (lookup *(ebx+8) *(ebx+0xc))  # Stmt-var-next Stmt-var-next => eax
    29777     (emit-subx-var-as-rm32 *(ebp+8) %eax)
    29778     (write-buffered *(ebp+8) Space)
    29779 $translate-mu-compute-index-stmt:emit-elem-size:
    29780     # var base/ebx: (addr var)
    29781     (lookup *ebx *(ebx+4))  # Stmt-var-value Stmt-var-value => eax
    29782     89/<- %ebx 0/r32/eax
    29783     # print array-element-size(base)
    29784     (array-element-size %ebx *(ebp+0x10) *(ebp+0x14))  # => eax
    29785     (write-int32-hex-buffered *(ebp+8) %eax)
    29786     (write-buffered *(ebp+8) "/imm32 ")
    29787 $translate-mu-compute-index-stmt:emit-output:
    29788     # outputs[0] "/r32"
    29789     (lookup *(ecx+0x14) *(ecx+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    29790     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    29791     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    29792     (get Mu-registers %eax 0xc "Mu-registers")  # => eax: (addr int)
    29793     (write-int32-hex-buffered *(ebp+8) *eax)
    29794     (write-buffered *(ebp+8) "/r32\n")
    29795 $translate-mu-compute-index-stmt:end:
    29796     # . restore registers
    29797     5b/pop-to-ebx
    29798     5a/pop-to-edx
    29799     59/pop-to-ecx
    29800     58/pop-to-eax
    29801     # . epilogue
    29802     89/<- %esp 5/r32/ebp
    29803     5d/pop-to-ebp
    29804     c3/return
    29805
    29806 translate-mu-get-stmt:  # out: (addr buffered-file), stmt: (addr stmt)
    29807     # . prologue
    29808     55/push-ebp
    29809     89/<- %ebp 4/r32/esp
    29810     # . save registers
    29811     50/push-eax
    29812     51/push-ecx
    29813     52/push-edx
    29814     # ecx = stmt
    29815     8b/-> *(ebp+0xc) 1/r32/ecx
    29816     # var base/eax: (addr var) = stmt->inouts->value
    29817     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    29818     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    29819     # if base is in a register, insert a null check
    29820     81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
    29821     {
    29822       0f 84/jump-if-= break/disp32
    29823 $translate-mu-get-stmt:emit-null-check-for-register-input:
    29824       # emit "81 7/subop/compare %" base->register " 0/imm32\n"
    29825       (emit-indent *(ebp+8) *Curr-block-depth)
    29826       (write-buffered *(ebp+8) "81 7/subop/compare %")
    29827       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    29828       (write-buffered *(ebp+8) %eax)
    29829       (write-buffered *(ebp+8) " 0/imm32\n")
    29830       #
    29831       (emit-indent *(ebp+8) *Curr-block-depth)
    29832       (write-buffered *(ebp+8) "0f 84/jump-if-= __mu-abort-null-get-base-address/disp32\n")
    29833     }
    29834     # var offset/edx: int = get offset of stmt
    29835     (mu-get-offset %ecx)  # => eax
    29836     89/<- %edx 0/r32/eax
    29837     # var base/eax: (addr var) = stmt->inouts->value
    29838     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    29839     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    29840     #
    29841     (emit-indent *(ebp+8) *Curr-block-depth)
    29842     (write-buffered *(ebp+8) "8d/copy-address ")
    29843     # if base is in a register
    29844     81 7/subop/compare *(eax+0x18) 0/imm32  # Var-register
    29845     {
    29846       0f 84/jump-if-= break/disp32
    29847 $translate-mu-get-stmt:emit-register-input:
    29848       # emit "*(" base->register " + " offset ") "
    29849       (write-buffered *(ebp+8) "*(")
    29850       (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    29851       (write-buffered *(ebp+8) %eax)
    29852       (write-buffered *(ebp+8) " + ")
    29853       (write-int32-hex-buffered *(ebp+8) %edx)
    29854       (write-buffered *(ebp+8) ") ")
    29855       e9/jump $translate-mu-get-stmt:emit-output/disp32
    29856     }
    29857     # otherwise base is on the stack
    29858     {
    29859 $translate-mu-get-stmt:emit-stack-input:
    29860       # emit "*(ebp + " inouts[0]->stack-offset + offset ") "
    29861       (write-buffered *(ebp+8) "*(ebp+")
    29862       03/add *(eax+0x14) 2/r32/edx  # Var-offset
    29863       (write-int32-hex-buffered *(ebp+8) %edx)
    29864       (write-buffered *(ebp+8) ") ")
    29865       eb/jump $translate-mu-get-stmt:emit-output/disp8
    29866     }
    29867 $translate-mu-get-stmt:emit-output:
    29868     # var output/eax: (addr var) = stmt->outputs->value
    29869     (lookup *(ecx+0x14) *(ecx+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    29870     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    29871     # emit offset->register "/r32"
    29872     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    29873     (get Mu-registers %eax 0xc "Mu-registers")  # => eax: (addr int)
    29874     (write-int32-hex-buffered *(ebp+8) *eax)
    29875     (write-buffered *(ebp+8) "/r32\n")
    29876 $translate-mu-get-stmt:end:
    29877     # . restore registers
    29878     5a/pop-to-edx
    29879     59/pop-to-ecx
    29880     58/pop-to-eax
    29881     # . epilogue
    29882     89/<- %esp 5/r32/ebp
    29883     5d/pop-to-ebp
    29884     c3/return
    29885
    29886 translate-mu-copy-object-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
    29887     # . prologue
    29888     55/push-ebp
    29889     89/<- %ebp 4/r32/esp
    29890     # . save registers
    29891     50/push-eax
    29892     #
    29893     (emit-indent *(ebp+8) *Curr-block-depth)
    29894     (write-buffered *(ebp+8) "(copy-bytes")
    29895     # eax = stmt
    29896     8b/-> *(ebp+0xc) 0/r32/eax
    29897     # var first-inout/eax: (addr stmt-var) = stmt->inouts[0]
    29898     (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    29899     (emit-subx-call-operand *(ebp+8) %eax)
    29900     # var second-inout/eax: (addr stmt-var) = stmt->inouts[1]
    29901     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    29902     (emit-subx-call-operand *(ebp+8) %eax)
    29903     # emit size of inouts
    29904     (write-buffered *(ebp+8) Space)
    29905     (addr-payload-size %eax *(ebp+0x10) *(ebp+0x14))  # => eax
    29906     (write-int32-hex-buffered *(ebp+8) %eax)
    29907     (write-buffered *(ebp+8) ")\n")
    29908 $translate-mu-copy-object-stmt:end:
    29909     # . restore registers
    29910     58/pop-to-eax
    29911     # . epilogue
    29912     89/<- %esp 5/r32/ebp
    29913     5d/pop-to-ebp
    29914     c3/return
    29915
    29916 translate-mu-clear-object-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
    29917     # . prologue
    29918     55/push-ebp
    29919     89/<- %ebp 4/r32/esp
    29920     # . save registers
    29921     50/push-eax
    29922     #
    29923     (emit-indent *(ebp+8) *Curr-block-depth)
    29924     (write-buffered *(ebp+8) "(zero-out")
    29925     # eax = stmt
    29926     8b/-> *(ebp+0xc) 0/r32/eax
    29927     # var dest/eax: (addr stmt-var) = stmt->inouts[0]
    29928     (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    29929     #
    29930     (emit-subx-call-operand *(ebp+8) %eax)
    29931     (write-buffered *(ebp+8) Space)
    29932     (addr-payload-size %eax *(ebp+0x10) *(ebp+0x14))  # => eax
    29933     (write-int32-hex-buffered *(ebp+8) %eax)
    29934     (write-buffered *(ebp+8) ")\n")
    29935 $translate-mu-clear-object-stmt:end:
    29936     # . restore registers
    29937     58/pop-to-eax
    29938     # . epilogue
    29939     89/<- %esp 5/r32/ebp
    29940     5d/pop-to-ebp
    29941     c3/return
    29942
    29943 translate-mu-allocate-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
    29944     # . prologue
    29945     55/push-ebp
    29946     89/<- %ebp 4/r32/esp
    29947     # . save registers
    29948     50/push-eax
    29949     56/push-esi
    29950     57/push-edi
    29951     # esi = stmt
    29952     8b/-> *(ebp+0xc) 6/r32/esi
    29953     # var target/edi: (addr stmt-var) = stmt->inouts[0]
    29954     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    29955     89/<- %edi 0/r32/eax
    29956     #
    29957     (emit-indent *(ebp+8) *Curr-block-depth)
    29958     (write-buffered *(ebp+8) "(allocate Heap ")
    29959     (addr-handle-payload-size %edi *(ebp+0x10) *(ebp+0x14))  # => eax
    29960     (write-int32-hex-buffered *(ebp+8) %eax)
    29961     (emit-subx-call-operand *(ebp+8) %edi)
    29962     (write-buffered *(ebp+8) ")\n")
    29963 $translate-mu-allocate-stmt:end:
    29964     # . restore registers
    29965     5f/pop-to-edi
    29966     5e/pop-to-esi
    29967     58/pop-to-eax
    29968     # . epilogue
    29969     89/<- %esp 5/r32/ebp
    29970     5d/pop-to-ebp
    29971     c3/return
    29972
    29973 addr-handle-payload-size:  # s: (addr stmt-var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
    29974     # . prologue
    29975     55/push-ebp
    29976     89/<- %ebp 4/r32/esp
    29977     # var t/eax: (addr type-tree) = s->value->type
    29978     8b/-> *(ebp+8) 0/r32/eax
    29979     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    29980     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    29981     # TODO: check eax != 0
    29982     # TODO: check !t->is-atom?
    29983     # TODO: check t->left == addr
    29984     # t = t->right
    29985 $addr-handle-payload-size:skip-addr:
    29986     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
    29987     # TODO: check eax != 0
    29988     # TODO: check !t->is-atom?
    29989     # TODO: check t->left == handle
    29990     # t = t->right
    29991 $addr-handle-payload-size:skip-handle:
    29992     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
    29993     # TODO: check eax != 0
    29994     # if !t->is-atom? t = t->left
    29995     81 7/subop/compare *eax 0/imm32/false
    29996     {
    29997       75/jump-if-!= break/disp8
    29998       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    29999     }
    30000     # TODO: check t->is-atom?
    30001     # return size(t->value)
    30002     (size-of-type-id *(eax+4))  # Type-tree-value => eax
    30003 $addr-handle-payload-size:end:
    30004     # . epilogue
    30005     89/<- %esp 5/r32/ebp
    30006     5d/pop-to-ebp
    30007     c3/return
    30008
    30009 addr-payload-size:  # s: (addr stmt-var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
    30010     # . prologue
    30011     55/push-ebp
    30012     89/<- %ebp 4/r32/esp
    30013     # var t/eax: (addr type-tree) = s->value->type
    30014     8b/-> *(ebp+8) 0/r32/eax
    30015     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    30016     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    30017     # TODO: check eax != 0
    30018     # TODO: check !t->is-atom?
    30019     # TODO: check t->left == addr
    30020     # t = t->right
    30021 $addr-payload-size:skip-addr:
    30022     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
    30023     # TODO: check eax != 0
    30024     # if !t->is-atom? t = t->left
    30025     81 7/subop/compare *eax 0/imm32/false
    30026     {
    30027       75/jump-if-!= break/disp8
    30028       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    30029     }
    30030     # TODO: check t->is-atom?
    30031     # return size(t->value)
    30032     (size-of-type-id *(eax+4))  # Type-tree-value => eax
    30033 $addr-payload-size:end:
    30034     # . epilogue
    30035     89/<- %esp 5/r32/ebp
    30036     5d/pop-to-ebp
    30037     c3/return
    30038
    30039 translate-mu-populate-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
    30040     # . prologue
    30041     55/push-ebp
    30042     89/<- %ebp 4/r32/esp
    30043     # . save registers
    30044     50/push-eax
    30045     51/push-ecx
    30046     56/push-esi
    30047     57/push-edi
    30048     # esi = stmt
    30049     8b/-> *(ebp+0xc) 6/r32/esi
    30050     # var target/edi: (addr stmt-var) = stmt->inouts[0]
    30051     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    30052     89/<- %edi 0/r32/eax
    30053     # var len/ecx: (addr stmt-var) = stmt->inouts[1]
    30054     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
    30055     89/<- %ecx 0/r32/eax
    30056     #
    30057     (emit-indent *(ebp+8) *Curr-block-depth)
    30058     (write-buffered *(ebp+8) "(allocate-array2 Heap ")
    30059     (addr-handle-array-payload-size %edi *(ebp+0x10) *(ebp+0x14))  # => eax
    30060     (write-int32-hex-buffered *(ebp+8) %eax)
    30061     (emit-subx-call-operand *(ebp+8) %ecx)
    30062     (emit-subx-call-operand *(ebp+8) %edi)
    30063     (write-buffered *(ebp+8) ")\n")
    30064 $translate-mu-populate-stmt:end:
    30065     # . restore registers
    30066     5f/pop-to-edi
    30067     5e/pop-to-esi
    30068     59/pop-to-ecx
    30069     58/pop-to-eax
    30070     # . epilogue
    30071     89/<- %esp 5/r32/ebp
    30072     5d/pop-to-ebp
    30073     c3/return
    30074
    30075 translate-mu-populate-stream-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
    30076     # . prologue
    30077     55/push-ebp
    30078     89/<- %ebp 4/r32/esp
    30079     # . save registers
    30080     50/push-eax
    30081     51/push-ecx
    30082     56/push-esi
    30083     57/push-edi
    30084     # esi = stmt
    30085     8b/-> *(ebp+0xc) 6/r32/esi
    30086     # var target/edi: (addr stmt-var) = stmt->inouts[0]
    30087     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    30088     89/<- %edi 0/r32/eax
    30089     # var len/ecx: (addr stmt-var) = stmt->inouts[1]
    30090     (lookup *(edi+8) *(edi+0xc))  # Stmt-var-next Stmt-var-next => eax
    30091     89/<- %ecx 0/r32/eax
    30092     #
    30093     (emit-indent *(ebp+8) *Curr-block-depth)
    30094     (write-buffered *(ebp+8) "(new-stream Heap ")
    30095     (addr-handle-stream-payload-size %edi *(ebp+0x10) *(ebp+0x14))  # => eax
    30096     (write-int32-hex-buffered *(ebp+8) %eax)
    30097     (emit-subx-call-operand *(ebp+8) %ecx)
    30098     (emit-subx-call-operand *(ebp+8) %edi)
    30099     (write-buffered *(ebp+8) ")\n")
    30100 $translate-mu-populate-stream-stmt:end:
    30101     # . restore registers
    30102     5f/pop-to-edi
    30103     5e/pop-to-esi
    30104     59/pop-to-ecx
    30105     58/pop-to-eax
    30106     # . epilogue
    30107     89/<- %esp 5/r32/ebp
    30108     5d/pop-to-ebp
    30109     c3/return
    30110
    30111 translate-mu-read-from-stream-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
    30112     # . prologue
    30113     55/push-ebp
    30114     89/<- %ebp 4/r32/esp
    30115     # . save registers
    30116     50/push-eax
    30117     51/push-ecx
    30118     56/push-esi
    30119     57/push-edi
    30120     # esi = stmt
    30121     8b/-> *(ebp+0xc) 6/r32/esi
    30122     # var stream/ecx: (addr stmt-var) = stmt->inouts[0]
    30123     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    30124     89/<- %ecx 0/r32/eax
    30125     # var target/edi: (addr stmt-var) = stmt->inouts[1]
    30126     (lookup *(ecx+8) *(ecx+0xc))  # Stmt-var-next Stmt-var-next => eax
    30127     89/<- %edi 0/r32/eax
    30128     #
    30129     (emit-indent *(ebp+8) *Curr-block-depth)
    30130     (write-buffered *(ebp+8) "(read-from-stream")
    30131     (emit-subx-call-operand *(ebp+8) %ecx)
    30132     (emit-subx-call-operand *(ebp+8) %edi)
    30133     (write-buffered *(ebp+8) Space)
    30134     (addr-payload-size %edi *(ebp+0x10) *(ebp+0x14))  # => eax
    30135     (write-int32-hex-buffered *(ebp+8) %eax)
    30136     (write-buffered *(ebp+8) ")\n")
    30137 $translate-mu-read-from-stream-stmt:end:
    30138     # . restore registers
    30139     5f/pop-to-edi
    30140     5e/pop-to-esi
    30141     59/pop-to-ecx
    30142     58/pop-to-eax
    30143     # . epilogue
    30144     89/<- %esp 5/r32/ebp
    30145     5d/pop-to-ebp
    30146     c3/return
    30147
    30148 translate-mu-write-to-stream-stmt:  # out: (addr buffered-file), stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
    30149     # . prologue
    30150     55/push-ebp
    30151     89/<- %ebp 4/r32/esp
    30152     # . save registers
    30153     50/push-eax
    30154     51/push-ecx
    30155     56/push-esi
    30156     57/push-edi
    30157     # esi = stmt
    30158     8b/-> *(ebp+0xc) 6/r32/esi
    30159     # var stream/ecx: (addr stmt-var) = stmt->inouts[0]
    30160     (lookup *(esi+0xc) *(esi+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    30161     89/<- %ecx 0/r32/eax
    30162     # var target/edi: (addr stmt-var) = stmt->inouts[1]
    30163     (lookup *(ecx+8) *(ecx+0xc))  # Stmt-var-next Stmt-var-next => eax
    30164     89/<- %edi 0/r32/eax
    30165     #
    30166     (emit-indent *(ebp+8) *Curr-block-depth)
    30167     (write-buffered *(ebp+8) "(write-to-stream")
    30168     (emit-subx-call-operand *(ebp+8) %ecx)
    30169     (flush *(ebp+8))
    30170     (emit-subx-call-operand *(ebp+8) %edi)
    30171     (flush *(ebp+8))
    30172     (write-buffered *(ebp+8) Space)
    30173     (flush *(ebp+8))
    30174     (addr-payload-size %edi *(ebp+0x10) *(ebp+0x14))  # => eax
    30175     (write-int32-hex-buffered *(ebp+8) %eax)
    30176     (write-buffered *(ebp+8) ")\n")
    30177 $translate-mu-write-to-stream-stmt:end:
    30178     # . restore registers
    30179     5f/pop-to-edi
    30180     5e/pop-to-esi
    30181     59/pop-to-ecx
    30182     58/pop-to-eax
    30183     # . epilogue
    30184     89/<- %esp 5/r32/ebp
    30185     5d/pop-to-ebp
    30186     c3/return
    30187
    30188 addr-handle-array-payload-size:  # s: (addr stmt-var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
    30189     # . prologue
    30190     55/push-ebp
    30191     89/<- %ebp 4/r32/esp
    30192     # var t/eax: (addr type-tree) = s->value->type
    30193     8b/-> *(ebp+8) 0/r32/eax
    30194     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    30195     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    30196     # TODO: check eax != 0
    30197     # TODO: check !t->is-atom?
    30198     # TODO: check t->left == addr
    30199     # t = t->right
    30200 $addr-handle-array-payload-size:skip-addr:
    30201     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
    30202     # TODO: check eax != 0
    30203     # TODO: check !t->is-atom?
    30204     # TODO: check t->left == handle
    30205     # t = t->right
    30206 $addr-handle-array-payload-size:skip-handle:
    30207     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
    30208     # TODO: check eax != 0
    30209     # TODO: check !t->is-atom?
    30210     # TODO: check t->left == array
    30211     # t = t->right
    30212 $addr-handle-array-payload-size:skip-array:
    30213     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
    30214     # TODO: check eax != 0
    30215     # if !t->is-atom? t = t->left
    30216     81 7/subop/compare *eax 0/imm32/false
    30217     {
    30218       75/jump-if-!= break/disp8
    30219       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    30220     }
    30221 $addr-handle-array-payload-size:compute-size:
    30222     # TODO: check t->is-atom?
    30223     # return size(t->value)
    30224     (size-of-type-id-as-array-element *(eax+4))  # Type-tree-value => eax
    30225 $addr-handle-array-payload-size:end:
    30226     # . epilogue
    30227     89/<- %esp 5/r32/ebp
    30228     5d/pop-to-ebp
    30229     c3/return
    30230
    30231 addr-handle-stream-payload-size:  # s: (addr stmt-var), err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: int
    30232     # . prologue
    30233     55/push-ebp
    30234     89/<- %ebp 4/r32/esp
    30235     # var t/eax: (addr type-tree) = s->value->type
    30236     8b/-> *(ebp+8) 0/r32/eax
    30237     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    30238     (lookup *(eax+8) *(eax+0xc))  # Var-type Var-type => eax
    30239     # TODO: check eax != 0
    30240     # TODO: check !t->is-atom?
    30241     # TODO: check t->left == addr
    30242     # t = t->right
    30243 $addr-handle-stream-payload-size:skip-addr:
    30244     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
    30245     # TODO: check eax != 0
    30246     # TODO: check !t->is-atom?
    30247     # TODO: check t->left == handle
    30248     # t = t->right
    30249 $addr-handle-stream-payload-size:skip-handle:
    30250     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
    30251     # TODO: check eax != 0
    30252     # TODO: check !t->is-atom?
    30253     # TODO: check t->left == stream
    30254     # t = t->right
    30255 $addr-handle-stream-payload-size:skip-stream:
    30256     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
    30257     # TODO: check eax != 0
    30258     # if !t->is-atom? t = t->left
    30259     81 7/subop/compare *eax 0/imm32/false
    30260     {
    30261       75/jump-if-!= break/disp8
    30262       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    30263     }
    30264 $addr-handle-stream-payload-size:compute-size:
    30265     # TODO: check t->is-atom?
    30266     # return size(t->value)
    30267     (size-of-type-id-as-array-element *(eax+4))  # Type-tree-value => eax
    30268 $addr-handle-stream-payload-size:end:
    30269     # . epilogue
    30270     89/<- %esp 5/r32/ebp
    30271     5d/pop-to-ebp
    30272     c3/return
    30273
    30274 power-of-2?:  # n: int, err: (addr buffered-file), ed: (addr exit-descriptor) -> result/eax: boolean
    30275     # precondition: n is positive
    30276     # . prologue
    30277     55/push-ebp
    30278     89/<- %ebp 4/r32/esp
    30279     # eax = n
    30280     8b/-> *(ebp+8) 0/r32/eax
    30281     # if (n < 0) abort
    30282     3d/compare-eax-with 0/imm32
    30283     0f 8c/jump-if-< $power-of-2?:abort/disp32
    30284     # var tmp/eax: int = n-1
    30285     48/decrement-eax
    30286     # var tmp2/eax: int = n & tmp
    30287     23/and-> *(ebp+8) 0/r32/eax
    30288     # return (tmp2 == 0)
    30289     3d/compare-eax-and 0/imm32
    30290     0f 94/set-byte-if-= %al
    30291     25/and-eax-with 0xff/imm32
    30292 $power-of-2?:end:
    30293     # . epilogue
    30294     89/<- %esp 5/r32/ebp
    30295     5d/pop-to-ebp
    30296     c3/return
    30297
    30298 $power-of-2?:abort:
    30299     (write-buffered *(ebp+0xc) "power-of-2?: negative number\n")
    30300     (flush *(ebp+0xc))
    30301     (stop *(ebp+0x10) 1)
    30302     # never gets here
    30303
    30304 num-shift-rights:  # n: int -> result/eax: int
    30305     # precondition: n is a positive power of 2
    30306     # . prologue
    30307     55/push-ebp
    30308     89/<- %ebp 4/r32/esp
    30309     # . save registers
    30310     51/push-ecx
    30311     # var curr/ecx: int = n
    30312     8b/-> *(ebp+8) 1/r32/ecx
    30313     # result = 0
    30314     b8/copy-to-eax 0/imm32
    30315     {
    30316       # if (curr <= 1) break
    30317       81 7/subop/compare %ecx 1/imm32
    30318       7e/jump-if-<= break/disp8
    30319       40/increment-eax
    30320       c1/shift 5/subop/arithmetic-right %ecx 1/imm8
    30321       eb/jump loop/disp8
    30322     }
    30323 $num-shift-rights:end:
    30324     # . restore registers
    30325     59/pop-to-ecx
    30326     # . epilogue
    30327     89/<- %esp 5/r32/ebp
    30328     5d/pop-to-ebp
    30329     c3/return
    30330
    30331 mu-get-offset:  # stmt: (addr stmt) -> result/eax: int
    30332     # . prologue
    30333     55/push-ebp
    30334     89/<- %ebp 4/r32/esp
    30335     # var second-inout/eax: (addr stmt-var) = stmt->inouts->next
    30336     8b/-> *(ebp+8) 0/r32/eax
    30337     (lookup *(eax+0xc) *(eax+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    30338     (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    30339     # var output-var/eax: (addr var) = second-inout->value
    30340     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    30341 #?     (write-buffered Stderr "mu-get-offset: ")
    30342 #?     (write-int32-hex-buffered Stderr %eax)
    30343 #?     (write-buffered Stderr " name: ")
    30344 #?     50/push-eax
    30345 #?     (lookup *eax *(eax+4))  # Var-name
    30346 #?     (write-buffered Stderr %eax)
    30347 #?     58/pop-to-eax
    30348 #?     (write-buffered Stderr Newline)
    30349 #?     (flush Stderr)
    30350     # return output-var->stack-offset
    30351     8b/-> *(eax+0x14) 0/r32/eax  # Var-offset
    30352 #?     (write-buffered Stderr "=> ")
    30353 #?     (write-int32-hex-buffered Stderr %eax)
    30354 #?     (write-buffered Stderr Newline)
    30355 #?     (flush Stderr)
    30356 $emit-get-offset:end:
    30357     # . epilogue
    30358     89/<- %esp 5/r32/ebp
    30359     5d/pop-to-ebp
    30360     c3/return
    30361
    30362 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)
    30363     # . prologue
    30364     55/push-ebp
    30365     89/<- %ebp 4/r32/esp
    30366     # . save registers
    30367     50/push-eax
    30368     51/push-ecx
    30369     56/push-esi
    30370     # esi = block
    30371     8b/-> *(ebp+0xc) 6/r32/esi
    30372     # block->var->block-depth = *Curr-block-depth
    30373     (lookup *(esi+0xc) *(esi+0x10))  # Block-var Block-var => eax
    30374     8b/-> *Curr-block-depth 1/r32/ecx
    30375     89/<- *(eax+0x10) 1/r32/ecx  # Var-block-depth
    30376     # var stmts/eax: (addr list stmt) = lookup(block->statements)
    30377     (lookup *(esi+4) *(esi+8))  # Block-stmts Block-stmts => eax
    30378     #
    30379     {
    30380 $emit-subx-block:check-empty:
    30381       3d/compare-eax-and 0/imm32
    30382       0f 84/jump-if-= break/disp32
    30383       (emit-indent *(ebp+8) *Curr-block-depth)
    30384       (write-buffered *(ebp+8) "{\n")
    30385       # var v/ecx: (addr var) = lookup(block->var)
    30386       (lookup *(esi+0xc) *(esi+0x10))  # Block-var Block-var => eax
    30387       89/<- %ecx 0/r32/eax
    30388       #
    30389       (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    30390       (write-buffered *(ebp+8) %eax)
    30391       (write-buffered *(ebp+8) ":loop:\n")
    30392       ff 0/subop/increment *Curr-block-depth
    30393       (push *(ebp+0x10) *(esi+0xc))  # Block-var
    30394       (push *(ebp+0x10) *(esi+0x10))  # Block-var
    30395       (push *(ebp+0x10) 0)  # false
    30396       # emit block->statements
    30397       (lookup *(esi+4) *(esi+8))  # Block-stmts Block-stmts => eax
    30398       (emit-subx-stmt-list *(ebp+8) %eax *(ebp+0x10) *(ebp+0x14) *(ebp+0x18) *(ebp+0x1c))
    30399       (pop *(ebp+0x10))  # => eax
    30400       (pop *(ebp+0x10))  # => eax
    30401       (pop *(ebp+0x10))  # => eax
    30402       ff 1/subop/decrement *Curr-block-depth
    30403       (emit-indent *(ebp+8) *Curr-block-depth)
    30404       (write-buffered *(ebp+8) "}\n")
    30405       (lookup *ecx *(ecx+4))  # Var-name Var-name => eax
    30406       (write-buffered *(ebp+8) %eax)
    30407       (write-buffered *(ebp+8) ":break:\n")
    30408     }
    30409 $emit-subx-block:end:
    30410     # . restore registers
    30411     5e/pop-to-esi
    30412     59/pop-to-ecx
    30413     58/pop-to-eax
    30414     # . epilogue
    30415     89/<- %esp 5/r32/ebp
    30416     5d/pop-to-ebp
    30417     c3/return
    30418
    30419 # Primitives supported
    30420 # See mu_instructions for a summary of this linked-list data structure.
    30421 #
    30422 # For each operation, put variants with hard-coded registers before flexible ones.
    30423 #
    30424 # Unfortunately, our restrictions on addresses require that various fields in
    30425 # primitives be handles, which complicates these definitions.
    30426 #   - we need to insert dummy fields all over the place for fake alloc-ids
    30427 #   - we can't use our syntax sugar of quoted literals for string fields
    30428 #
    30429 # Fake alloc-ids are needed because our type definitions up top require
    30430 # handles but it's clearer to statically allocate these long-lived objects.
    30431 # Fake alloc-ids are perfectly safe, but they can't be reclaimed.
    30432 #
    30433 # Every 'object' below starts with a fake alloc-id. It may also contain other
    30434 # fake alloc-ids for various handle fields.
    30435 #
    30436 # I think of objects starting with a fake alloc-id as having type 'payload'.
    30437 # It's not really intended to be created dynamically; for that use `allocate`
    30438 # as usual.
    30439 #
    30440 # Idea for a notation to simplify such definitions:
    30441 #   _Primitive-increment-eax:  # (payload primitive)
    30442 #     0x11/alloc-id:fake:payload
    30443 #     0x11 @(0x11 "increment")  # name
    30444 #     0 0                       # inouts
    30445 #     0x11 @(0x11/payload
    30446 #            0x11 @(0x11/payload  # List-value
    30447 #                   0 0             # Var-name
    30448 #                   0x11 @(0x11     # Var-type
    30449 #                          1/is-atom
    30450 #                          1/value 0/unused   # Type-tree-left
    30451 #                          0 0                # Type-tree-right
    30452 #                         )
    30453 #                   1               # block-depth
    30454 #                   0               # stack-offset
    30455 #                   0x11 @(0x11 "eax")  # Var-register
    30456 #                  )
    30457 #            0 0)                 # List-next
    30458 #     ...
    30459 #     _Primitive-increment-ecx/imm32/next
    30460 #   ...
    30461 # Awfully complex and non-obvious. But also clearly signals there's something
    30462 # to learn here, so may be worth trying.
    30463 #
    30464 # '@' is just an initial thought. Punctuation used so far in Mu: () * % # / "
    30465 #
    30466 # For now we'll continue to just use comments and manually ensure they stay up
    30467 # to date.
    30468 == data
    30469 Primitives:  # (addr primitive)
    30470 # - increment/decrement
    30471 _Primitive-increment-eax:  # (addr primitive)
    30472     # var/eax <- increment => 40/increment-eax
    30473     0x11/imm32/alloc-id:fake
    30474     _string-increment/imm32/name
    30475     0/imm32/no-inouts
    30476     0/imm32/no-inouts
    30477     0x11/imm32/alloc-id:fake
    30478     Single-int-var-in-eax/imm32/outputs
    30479     0x11/imm32/alloc-id:fake
    30480     _string_40_increment_eax/imm32/subx-name
    30481     0/imm32/no-rm32
    30482     0/imm32/no-r32
    30483     0/imm32/no-imm32
    30484     0/imm32/no-imm8
    30485     0/imm32/no-disp32
    30486     0/imm32/no-xm32
    30487     0/imm32/no-x32
    30488     0x11/imm32/alloc-id:fake
    30489     _Primitive-increment-ecx/imm32/next
    30490 _Primitive-increment-ecx:  # (payload primitive)
    30491     0x11/imm32/alloc-id:fake:payload
    30492     # var/ecx <- increment => 41/increment-ecx
    30493     0x11/imm32/alloc-id:fake
    30494     _string-increment/imm32/name
    30495     0/imm32/no-inouts
    30496     0/imm32/no-inouts
    30497     0x11/imm32/alloc-id:fake
    30498     Single-int-var-in-ecx/imm32/outputs
    30499     0x11/imm32/alloc-id:fake
    30500     _string_41_increment_ecx/imm32/subx-name
    30501     0/imm32/no-rm32
    30502     0/imm32/no-r32
    30503     0/imm32/no-imm32
    30504     0/imm32/no-imm8
    30505     0/imm32/no-disp32
    30506     0/imm32/no-xm32
    30507     0/imm32/no-x32
    30508     0x11/imm32/alloc-id:fake
    30509     _Primitive-increment-edx/imm32/next
    30510 _Primitive-increment-edx:  # (payload primitive)
    30511     0x11/imm32/alloc-id:fake:payload
    30512     # var/edx <- increment => 42/increment-edx
    30513     0x11/imm32/alloc-id:fake
    30514     _string-increment/imm32/name
    30515     0/imm32/no-inouts
    30516     0/imm32/no-inouts
    30517     0x11/imm32/alloc-id:fake
    30518     Single-int-var-in-edx/imm32/outputs
    30519     0x11/imm32/alloc-id:fake
    30520     _string_42_increment_edx/imm32/subx-name
    30521     0/imm32/no-rm32
    30522     0/imm32/no-r32
    30523     0/imm32/no-imm32
    30524     0/imm32/no-imm8
    30525     0/imm32/no-disp32
    30526     0/imm32/no-xm32
    30527     0/imm32/no-x32
    30528     0x11/imm32/alloc-id:fake
    30529     _Primitive-increment-ebx/imm32/next
    30530 _Primitive-increment-ebx:  # (payload primitive)
    30531     0x11/imm32/alloc-id:fake:payload
    30532     # var/ebx <- increment => 43/increment-ebx
    30533     0x11/imm32/alloc-id:fake
    30534     _string-increment/imm32/name
    30535     0/imm32/no-inouts
    30536     0/imm32/no-inouts
    30537     0x11/imm32/alloc-id:fake
    30538     Single-int-var-in-ebx/imm32/outputs
    30539     0x11/imm32/alloc-id:fake
    30540     _string_43_increment_ebx/imm32/subx-name
    30541     0/imm32/no-rm32
    30542     0/imm32/no-r32
    30543     0/imm32/no-imm32
    30544     0/imm32/no-imm8
    30545     0/imm32/no-disp32
    30546     0/imm32/no-xm32
    30547     0/imm32/no-x32
    30548     0x11/imm32/alloc-id:fake
    30549     _Primitive-increment-esi/imm32/next
    30550 _Primitive-increment-esi:  # (payload primitive)
    30551     0x11/imm32/alloc-id:fake:payload
    30552     # var/esi <- increment => 46/increment-esi
    30553     0x11/imm32/alloc-id:fake
    30554     _string-increment/imm32/name
    30555     0/imm32/no-inouts
    30556     0/imm32/no-inouts
    30557     0x11/imm32/alloc-id:fake
    30558     Single-int-var-in-esi/imm32/outputs
    30559     0x11/imm32/alloc-id:fake
    30560     _string_46_increment_esi/imm32/subx-name
    30561     0/imm32/no-rm32
    30562     0/imm32/no-r32
    30563     0/imm32/no-imm32
    30564     0/imm32/no-imm8
    30565     0/imm32/no-disp32
    30566     0/imm32/no-xm32
    30567     0/imm32/no-x32
    30568     0x11/imm32/alloc-id:fake
    30569     _Primitive-increment-edi/imm32/next
    30570 _Primitive-increment-edi:  # (payload primitive)
    30571     0x11/imm32/alloc-id:fake:payload
    30572     # var/edi <- increment => 47/increment-edi
    30573     0x11/imm32/alloc-id:fake
    30574     _string-increment/imm32/name
    30575     0/imm32/no-inouts
    30576     0/imm32/no-inouts
    30577     0x11/imm32/alloc-id:fake
    30578     Single-int-var-in-edi/imm32/outputs
    30579     0x11/imm32/alloc-id:fake
    30580     _string_47_increment_edi/imm32/subx-name
    30581     0/imm32/no-rm32
    30582     0/imm32/no-r32
    30583     0/imm32/no-imm32
    30584     0/imm32/no-imm8
    30585     0/imm32/no-disp32
    30586     0/imm32/no-xm32
    30587     0/imm32/no-x32
    30588     0x11/imm32/alloc-id:fake
    30589     _Primitive-decrement-eax/imm32/next
    30590 _Primitive-decrement-eax:  # (payload primitive)
    30591     0x11/imm32/alloc-id:fake:payload
    30592     # var/eax <- decrement => 48/decrement-eax
    30593     0x11/imm32/alloc-id:fake
    30594     _string-decrement/imm32/name
    30595     0/imm32/no-inouts
    30596     0/imm32/no-inouts
    30597     0x11/imm32/alloc-id:fake
    30598     Single-int-var-in-eax/imm32/outputs
    30599     0x11/imm32/alloc-id:fake
    30600     _string_48_decrement_eax/imm32/subx-name
    30601     0/imm32/no-rm32
    30602     0/imm32/no-r32
    30603     0/imm32/no-imm32
    30604     0/imm32/no-imm8
    30605     0/imm32/no-disp32
    30606     0/imm32/no-xm32
    30607     0/imm32/no-x32
    30608     0x11/imm32/alloc-id:fake
    30609     _Primitive-decrement-ecx/imm32/next
    30610 _Primitive-decrement-ecx:  # (payload primitive)
    30611     0x11/imm32/alloc-id:fake:payload
    30612     # var/ecx <- decrement => 49/decrement-ecx
    30613     0x11/imm32/alloc-id:fake
    30614     _string-decrement/imm32/name
    30615     0/imm32/no-inouts
    30616     0/imm32/no-inouts
    30617     0x11/imm32/alloc-id:fake
    30618     Single-int-var-in-ecx/imm32/outputs
    30619     0x11/imm32/alloc-id:fake
    30620     _string_49_decrement_ecx/imm32/subx-name
    30621     0/imm32/no-rm32
    30622     0/imm32/no-r32
    30623     0/imm32/no-imm32
    30624     0/imm32/no-imm8
    30625     0/imm32/no-disp32
    30626     0/imm32/no-xm32
    30627     0/imm32/no-x32
    30628     0x11/imm32/alloc-id:fake
    30629     _Primitive-decrement-edx/imm32/next
    30630 _Primitive-decrement-edx:  # (payload primitive)
    30631     0x11/imm32/alloc-id:fake:payload
    30632     # var/edx <- decrement => 4a/decrement-edx
    30633     0x11/imm32/alloc-id:fake
    30634     _string-decrement/imm32/name
    30635     0/imm32/no-inouts
    30636     0/imm32/no-inouts
    30637     0x11/imm32/alloc-id:fake
    30638     Single-int-var-in-edx/imm32/outputs
    30639     0x11/imm32/alloc-id:fake
    30640     _string_4a_decrement_edx/imm32/subx-name
    30641     0/imm32/no-rm32
    30642     0/imm32/no-r32
    30643     0/imm32/no-imm32
    30644     0/imm32/no-imm8
    30645     0/imm32/no-disp32
    30646     0/imm32/no-xm32
    30647     0/imm32/no-x32
    30648     0x11/imm32/alloc-id:fake
    30649     _Primitive-decrement-ebx/imm32/next
    30650 _Primitive-decrement-ebx:  # (payload primitive)
    30651     0x11/imm32/alloc-id:fake:payload
    30652     # var/ebx <- decrement => 4b/decrement-ebx
    30653     0x11/imm32/alloc-id:fake
    30654     _string-decrement/imm32/name
    30655     0/imm32/no-inouts
    30656     0/imm32/no-inouts
    30657     0x11/imm32/alloc-id:fake
    30658     Single-int-var-in-ebx/imm32/outputs
    30659     0x11/imm32/alloc-id:fake
    30660     _string_4b_decrement_ebx/imm32/subx-name
    30661     0/imm32/no-rm32
    30662     0/imm32/no-r32
    30663     0/imm32/no-imm32
    30664     0/imm32/no-imm8
    30665     0/imm32/no-disp32
    30666     0/imm32/no-xm32
    30667     0/imm32/no-x32
    30668     0x11/imm32/alloc-id:fake
    30669     _Primitive-decrement-esi/imm32/next
    30670 _Primitive-decrement-esi:  # (payload primitive)
    30671     0x11/imm32/alloc-id:fake:payload
    30672     # var/esi <- decrement => 4e/decrement-esi
    30673     0x11/imm32/alloc-id:fake
    30674     _string-decrement/imm32/name
    30675     0/imm32/no-inouts
    30676     0/imm32/no-inouts
    30677     0x11/imm32/alloc-id:fake
    30678     Single-int-var-in-esi/imm32/outputs
    30679     0x11/imm32/alloc-id:fake
    30680     _string_4e_decrement_esi/imm32/subx-name
    30681     0/imm32/no-rm32
    30682     0/imm32/no-r32
    30683     0/imm32/no-imm32
    30684     0/imm32/no-imm8
    30685     0/imm32/no-disp32
    30686     0/imm32/no-xm32
    30687     0/imm32/no-x32
    30688     0x11/imm32/alloc-id:fake
    30689     _Primitive-decrement-edi/imm32/next
    30690 _Primitive-decrement-edi:  # (payload primitive)
    30691     0x11/imm32/alloc-id:fake:payload
    30692     # var/edi <- decrement => 4f/decrement-edi
    30693     0x11/imm32/alloc-id:fake
    30694     _string-decrement/imm32/name
    30695     0/imm32/no-inouts
    30696     0/imm32/no-inouts
    30697     0x11/imm32/alloc-id:fake
    30698     Single-int-var-in-edi/imm32/outputs
    30699     0x11/imm32/alloc-id:fake
    30700     _string_4f_decrement_edi/imm32/subx-name
    30701     0/imm32/no-rm32
    30702     0/imm32/no-r32
    30703     0/imm32/no-imm32
    30704     0/imm32/no-imm8
    30705     0/imm32/no-disp32
    30706     0/imm32/no-xm32
    30707     0/imm32/no-x32
    30708     0x11/imm32/alloc-id:fake
    30709     _Primitive-increment-mem/imm32/next
    30710 _Primitive-increment-mem:  # (payload primitive)
    30711     0x11/imm32/alloc-id:fake:payload
    30712     # increment var => ff 0/subop/increment *(ebp+__)
    30713     0x11/imm32/alloc-id:fake
    30714     _string-increment/imm32/name
    30715     0x11/imm32/alloc-id:fake
    30716     Single-int-var-in-mem/imm32/inouts
    30717     0/imm32/no-outputs
    30718     0/imm32/no-outputs
    30719     0x11/imm32/alloc-id:fake
    30720     _string_ff_subop_increment/imm32/subx-name
    30721     1/imm32/rm32-is-first-inout
    30722     0/imm32/no-r32
    30723     0/imm32/no-imm32
    30724     0/imm32/no-imm8
    30725     0/imm32/no-disp32
    30726     0/imm32/no-xm32
    30727     0/imm32/no-x32
    30728     0x11/imm32/alloc-id:fake
    30729     _Primitive-increment-reg/imm32/next
    30730 _Primitive-increment-reg:  # (payload primitive)
    30731     0x11/imm32/alloc-id:fake:payload
    30732     # var/reg <- increment => ff 0/subop/increment %__
    30733     0x11/imm32/alloc-id:fake
    30734     _string-increment/imm32/name
    30735     0/imm32/no-inouts
    30736     0/imm32/no-inouts
    30737     0x11/imm32/alloc-id:fake
    30738     Single-int-var-in-some-register/imm32/outputs
    30739     0x11/imm32/alloc-id:fake
    30740     _string_ff_subop_increment/imm32/subx-name
    30741     3/imm32/rm32-is-first-output
    30742     0/imm32/no-r32
    30743     0/imm32/no-imm32
    30744     0/imm32/no-imm8
    30745     0/imm32/no-disp32
    30746     0/imm32/no-xm32
    30747     0/imm32/no-x32
    30748     0x11/imm32/alloc-id:fake
    30749     _Primitive-decrement-mem/imm32/next
    30750 _Primitive-decrement-mem:  # (payload primitive)
    30751     0x11/imm32/alloc-id:fake:payload
    30752     # decrement var => ff 1/subop/decrement *(ebp+__)
    30753     0x11/imm32/alloc-id:fake
    30754     _string-decrement/imm32/name
    30755     0x11/imm32/alloc-id:fake
    30756     Single-int-var-in-mem/imm32/inouts
    30757     0/imm32/no-outputs
    30758     0/imm32/no-outputs
    30759     0x11/imm32/alloc-id:fake
    30760     _string_ff_subop_decrement/imm32/subx-name
    30761     1/imm32/rm32-is-first-inout
    30762     0/imm32/no-r32
    30763     0/imm32/no-imm32
    30764     0/imm32/no-imm8
    30765     0/imm32/no-disp32
    30766     0/imm32/no-xm32
    30767     0/imm32/no-x32
    30768     0x11/imm32/alloc-id:fake
    30769     _Primitive-decrement-reg/imm32/next
    30770 _Primitive-decrement-reg:  # (payload primitive)
    30771     0x11/imm32/alloc-id:fake:payload
    30772     # var/reg <- decrement => ff 1/subop/decrement %__
    30773     0x11/imm32/alloc-id:fake
    30774     _string-decrement/imm32/name
    30775     0/imm32/no-inouts
    30776     0/imm32/no-inouts
    30777     0x11/imm32/alloc-id:fake
    30778     Single-int-var-in-some-register/imm32/outputs
    30779     0x11/imm32/alloc-id:fake
    30780     _string_ff_subop_decrement/imm32/subx-name
    30781     3/imm32/rm32-is-first-output
    30782     0/imm32/no-r32
    30783     0/imm32/no-imm32
    30784     0/imm32/no-imm8
    30785     0/imm32/no-disp32
    30786     0/imm32/no-xm32
    30787     0/imm32/no-x32
    30788     0x11/imm32/alloc-id:fake
    30789     _Primitive-add-to-eax/imm32/next
    30790 # - add
    30791 _Primitive-add-to-eax:  # (payload primitive)
    30792     0x11/imm32/alloc-id:fake:payload
    30793     # var/eax <- add lit => 05/add-to-eax lit/imm32
    30794     0x11/imm32/alloc-id:fake
    30795     _string-add/imm32/name
    30796     0x11/imm32/alloc-id:fake
    30797     Single-lit-var/imm32/inouts
    30798     0x11/imm32/alloc-id:fake
    30799     Single-int-var-in-eax/imm32/outputs
    30800     0x11/imm32/alloc-id:fake
    30801     _string_05_add_to_eax/imm32/subx-name
    30802     0/imm32/no-rm32
    30803     0/imm32/no-r32
    30804     1/imm32/imm32-is-first-inout
    30805     0/imm32/no-imm8
    30806     0/imm32/no-disp32
    30807     0/imm32/no-xm32
    30808     0/imm32/no-x32
    30809     0x11/imm32/alloc-id:fake
    30810     _Primitive-add-reg-to-reg/imm32/next
    30811 _Primitive-add-reg-to-reg:  # (payload primitive)
    30812     0x11/imm32/alloc-id:fake:payload
    30813     # var1/reg <- add var2/reg => 01/add-to var1/rm32 var2/r32
    30814     0x11/imm32/alloc-id:fake
    30815     _string-add/imm32/name
    30816     0x11/imm32/alloc-id:fake
    30817     Single-int-var-in-some-register/imm32/inouts
    30818     0x11/imm32/alloc-id:fake
    30819     Single-int-var-in-some-register/imm32/outputs
    30820     0x11/imm32/alloc-id:fake
    30821     _string_01_add_to/imm32/subx-name
    30822     3/imm32/rm32-is-first-output
    30823     1/imm32/r32-is-first-inout
    30824     0/imm32/no-imm32
    30825     0/imm32/no-imm8
    30826     0/imm32/no-disp32
    30827     0/imm32/no-xm32
    30828     0/imm32/no-x32
    30829     0x11/imm32/alloc-id:fake
    30830     _Primitive-add-reg-to-mem/imm32/next
    30831 _Primitive-add-reg-to-mem:  # (payload primitive)
    30832     0x11/imm32/alloc-id:fake:payload
    30833     # add-to var1 var2/reg => 01/add-to var1 var2/r32
    30834     0x11/imm32/alloc-id:fake
    30835     _string-add-to/imm32/name
    30836     0x11/imm32/alloc-id:fake
    30837     Two-args-int-stack-int-reg/imm32/inouts
    30838     0/imm32/no-outputs
    30839     0/imm32/no-outputs
    30840     0x11/imm32/alloc-id:fake
    30841     _string_01_add_to/imm32/subx-name
    30842     1/imm32/rm32-is-first-inout
    30843     2/imm32/r32-is-second-inout
    30844     0/imm32/no-imm32
    30845     0/imm32/no-imm8
    30846     0/imm32/no-disp32
    30847     0/imm32/no-xm32
    30848     0/imm32/no-x32
    30849     0x11/imm32/alloc-id:fake
    30850     _Primitive-add-mem-to-reg/imm32/next
    30851 _Primitive-add-mem-to-reg:  # (payload primitive)
    30852     0x11/imm32/alloc-id:fake:payload
    30853     # var1/reg <- add var2 => 03/add var2/rm32 var1/r32
    30854     0x11/imm32/alloc-id:fake
    30855     _string-add/imm32/name
    30856     0x11/imm32/alloc-id:fake
    30857     Single-int-var-in-mem/imm32/inouts
    30858     0x11/imm32/alloc-id:fake
    30859     Single-int-var-in-some-register/imm32/outputs
    30860     0x11/imm32/alloc-id:fake
    30861     _string_03_add/imm32/subx-name
    30862     1/imm32/rm32-is-first-inout
    30863     3/imm32/r32-is-first-output
    30864     0/imm32/no-imm32
    30865     0/imm32/no-imm8
    30866     0/imm32/no-disp32
    30867     0/imm32/no-xm32
    30868     0/imm32/no-x32
    30869     0x11/imm32/alloc-id:fake
    30870     _Primitive-add-lit-to-reg/imm32/next
    30871 _Primitive-add-lit-to-reg:  # (payload primitive)
    30872     0x11/imm32/alloc-id:fake:payload
    30873     # var1/reg <- add lit => 81 0/subop/add var1/rm32 lit/imm32
    30874     0x11/imm32/alloc-id:fake
    30875     _string-add/imm32/name
    30876     0x11/imm32/alloc-id:fake
    30877     Single-lit-var/imm32/inouts
    30878     0x11/imm32/alloc-id:fake
    30879     Single-int-var-in-some-register/imm32/outputs
    30880     0x11/imm32/alloc-id:fake
    30881     _string_81_subop_add/imm32/subx-name
    30882     3/imm32/rm32-is-first-output
    30883     0/imm32/no-r32
    30884     1/imm32/imm32-is-first-inout
    30885     0/imm32/no-imm8
    30886     0/imm32/no-disp32
    30887     0/imm32/no-xm32
    30888     0/imm32/no-x32
    30889     0x11/imm32/alloc-id:fake
    30890     _Primitive-add-lit-to-mem/imm32/next
    30891 _Primitive-add-lit-to-mem:  # (payload primitive)
    30892     0x11/imm32/alloc-id:fake:payload
    30893     # add-to var1, lit => 81 0/subop/add var1/rm32 lit/imm32
    30894     0x11/imm32/alloc-id:fake
    30895     _string-add-to/imm32/name
    30896     0x11/imm32/alloc-id:fake
    30897     Int-var-and-literal/imm32/inouts
    30898     0/imm32/no-outputs
    30899     0/imm32/no-outputs
    30900     0x11/imm32/alloc-id:fake
    30901     _string_81_subop_add/imm32/subx-name
    30902     1/imm32/rm32-is-first-inout
    30903     0/imm32/no-r32
    30904     2/imm32/imm32-is-second-inout
    30905     0/imm32/no-imm8
    30906     0/imm32/no-disp32
    30907     0/imm32/no-xm32
    30908     0/imm32/no-x32
    30909     0x11/imm32/alloc-id:fake
    30910     _Primitive-subtract-from-eax/imm32/next
    30911 # - subtract
    30912 _Primitive-subtract-from-eax:  # (payload primitive)
    30913     0x11/imm32/alloc-id:fake:payload
    30914     # var/eax <- subtract lit => 2d/subtract-from-eax lit/imm32
    30915     0x11/imm32/alloc-id:fake
    30916     _string-subtract/imm32/name
    30917     0x11/imm32/alloc-id:fake
    30918     Single-lit-var/imm32/inouts
    30919     0x11/imm32/alloc-id:fake
    30920     Single-int-var-in-eax/imm32/outputs
    30921     0x11/imm32/alloc-id:fake
    30922     _string_2d_subtract_from_eax/imm32/subx-name
    30923     0/imm32/no-rm32
    30924     0/imm32/no-r32
    30925     1/imm32/imm32-is-first-inout
    30926     0/imm32/no-imm8
    30927     0/imm32/no-disp32
    30928     0/imm32/no-xm32
    30929     0/imm32/no-x32
    30930     0x11/imm32/alloc-id:fake
    30931     _Primitive-subtract-reg-from-reg/imm32/next
    30932 _Primitive-subtract-reg-from-reg:  # (payload primitive)
    30933     0x11/imm32/alloc-id:fake:payload
    30934     # var1/reg <- subtract var2/reg => 29/subtract-from var1/rm32 var2/r32
    30935     0x11/imm32/alloc-id:fake
    30936     _string-subtract/imm32/name
    30937     0x11/imm32/alloc-id:fake
    30938     Single-int-var-in-some-register/imm32/inouts
    30939     0x11/imm32/alloc-id:fake
    30940     Single-int-var-in-some-register/imm32/outputs
    30941     0x11/imm32/alloc-id:fake
    30942     _string_29_subtract_from/imm32/subx-name
    30943     3/imm32/rm32-is-first-output
    30944     1/imm32/r32-is-first-inout
    30945     0/imm32/no-imm32
    30946     0/imm32/no-imm8
    30947     0/imm32/no-disp32
    30948     0/imm32/no-xm32
    30949     0/imm32/no-x32
    30950     0x11/imm32/alloc-id:fake
    30951     _Primitive-subtract-reg-from-mem/imm32/next
    30952 _Primitive-subtract-reg-from-mem:  # (payload primitive)
    30953     0x11/imm32/alloc-id:fake:payload
    30954     # subtract-from var1 var2/reg => 29/subtract-from var1 var2/r32
    30955     0x11/imm32/alloc-id:fake
    30956     _string-subtract-from/imm32/name
    30957     0x11/imm32/alloc-id:fake
    30958     Two-args-int-stack-int-reg/imm32/inouts
    30959     0/imm32/no-outputs
    30960     0/imm32/no-outputs
    30961     0x11/imm32/alloc-id:fake
    30962     _string_29_subtract_from/imm32/subx-name
    30963     1/imm32/rm32-is-first-inout
    30964     2/imm32/r32-is-second-inout
    30965     0/imm32/no-imm32
    30966     0/imm32/no-imm8
    30967     0/imm32/no-disp32
    30968     0/imm32/no-xm32
    30969     0/imm32/no-x32
    30970     0x11/imm32/alloc-id:fake
    30971     _Primitive-subtract-mem-from-reg/imm32/next
    30972 _Primitive-subtract-mem-from-reg:  # (payload primitive)
    30973     0x11/imm32/alloc-id:fake:payload
    30974     # var1/reg <- subtract var2 => 2b/subtract var2/rm32 var1/r32
    30975     0x11/imm32/alloc-id:fake
    30976     _string-subtract/imm32/name
    30977     0x11/imm32/alloc-id:fake
    30978     Single-int-var-in-mem/imm32/inouts
    30979     0x11/imm32/alloc-id:fake
    30980     Single-int-var-in-some-register/imm32/outputs
    30981     0x11/imm32/alloc-id:fake
    30982     _string_2b_subtract/imm32/subx-name
    30983     1/imm32/rm32-is-first-inout
    30984     3/imm32/r32-is-first-output
    30985     0/imm32/no-imm32
    30986     0/imm32/no-imm8
    30987     0/imm32/no-disp32
    30988     0/imm32/no-xm32
    30989     0/imm32/no-x32
    30990     0x11/imm32/alloc-id:fake
    30991     _Primitive-subtract-lit-from-reg/imm32/next
    30992 _Primitive-subtract-lit-from-reg:  # (payload primitive)
    30993     0x11/imm32/alloc-id:fake:payload
    30994     # var1/reg <- subtract lit => 81 5/subop/subtract var1/rm32 lit/imm32
    30995     0x11/imm32/alloc-id:fake
    30996     _string-subtract/imm32/name
    30997     0x11/imm32/alloc-id:fake
    30998     Single-lit-var/imm32/inouts
    30999     0x11/imm32/alloc-id:fake
    31000     Single-int-var-in-some-register/imm32/outputs
    31001     0x11/imm32/alloc-id:fake
    31002     _string_81_subop_subtract/imm32/subx-name
    31003     3/imm32/rm32-is-first-output
    31004     0/imm32/no-r32
    31005     1/imm32/imm32-is-first-inout
    31006     0/imm32/no-imm8
    31007     0/imm32/no-disp32
    31008     0/imm32/no-xm32
    31009     0/imm32/no-x32
    31010     0x11/imm32/alloc-id:fake
    31011     _Primitive-subtract-lit-from-mem/imm32/next
    31012 _Primitive-subtract-lit-from-mem:  # (payload primitive)
    31013     0x11/imm32/alloc-id:fake:payload
    31014     # subtract-from var1, lit => 81 5/subop/subtract var1/rm32 lit/imm32
    31015     0x11/imm32/alloc-id:fake
    31016     _string-subtract-from/imm32/name
    31017     0x11/imm32/alloc-id:fake
    31018     Int-var-and-literal/imm32/inouts
    31019     0/imm32/no-outputs
    31020     0/imm32/no-outputs
    31021     0x11/imm32/alloc-id:fake
    31022     _string_81_subop_subtract/imm32/subx-name
    31023     1/imm32/rm32-is-first-inout
    31024     0/imm32/no-r32
    31025     2/imm32/imm32-is-second-inout
    31026     0/imm32/no-imm8
    31027     0/imm32/no-disp32
    31028     0/imm32/no-xm32
    31029     0/imm32/no-x32
    31030     0x11/imm32/alloc-id:fake
    31031     _Primitive-and-with-eax/imm32/next
    31032 # - and
    31033 _Primitive-and-with-eax:  # (payload primitive)
    31034     0x11/imm32/alloc-id:fake:payload
    31035     # var/eax <- and lit => 25/and-with-eax lit/imm32
    31036     0x11/imm32/alloc-id:fake
    31037     _string-and/imm32/name
    31038     0x11/imm32/alloc-id:fake
    31039     Single-lit-var/imm32/inouts
    31040     0x11/imm32/alloc-id:fake
    31041     Single-int-var-in-eax/imm32/outputs
    31042     0x11/imm32/alloc-id:fake
    31043     _string_25_and_with_eax/imm32/subx-name
    31044     0/imm32/no-rm32
    31045     0/imm32/no-r32
    31046     1/imm32/imm32-is-first-inout
    31047     0/imm32/no-imm8
    31048     0/imm32/no-disp32
    31049     0/imm32/no-xm32
    31050     0/imm32/no-x32
    31051     0x11/imm32/alloc-id:fake
    31052     _Primitive-and-reg-with-reg/imm32/next
    31053 _Primitive-and-reg-with-reg:  # (payload primitive)
    31054     0x11/imm32/alloc-id:fake:payload
    31055     # var1/reg <- and var2/reg => 21/and-with var1/rm32 var2/r32
    31056     0x11/imm32/alloc-id:fake
    31057     _string-and/imm32/name
    31058     0x11/imm32/alloc-id:fake
    31059     Single-int-var-in-some-register/imm32/inouts
    31060     0x11/imm32/alloc-id:fake
    31061     Single-int-var-in-some-register/imm32/outputs
    31062     0x11/imm32/alloc-id:fake
    31063     _string_21_and_with/imm32/subx-name
    31064     3/imm32/rm32-is-first-output
    31065     1/imm32/r32-is-first-inout
    31066     0/imm32/no-imm32
    31067     0/imm32/no-imm8
    31068     0/imm32/no-disp32
    31069     0/imm32/no-xm32
    31070     0/imm32/no-x32
    31071     0x11/imm32/alloc-id:fake
    31072     _Primitive-and-reg-with-mem/imm32/next
    31073 _Primitive-and-reg-with-mem:  # (payload primitive)
    31074     0x11/imm32/alloc-id:fake:payload
    31075     # and-with var1 var2/reg => 21/and-with var1 var2/r32
    31076     0x11/imm32/alloc-id:fake
    31077     _string-and-with/imm32/name
    31078     0x11/imm32/alloc-id:fake
    31079     Two-args-int-stack-int-reg/imm32/inouts
    31080     0/imm32/no-outputs
    31081     0/imm32/no-outputs
    31082     0x11/imm32/alloc-id:fake
    31083     _string_21_and_with/imm32/subx-name
    31084     1/imm32/rm32-is-first-inout
    31085     2/imm32/r32-is-second-inout
    31086     0/imm32/no-imm32
    31087     0/imm32/no-imm8
    31088     0/imm32/no-disp32
    31089     0/imm32/no-xm32
    31090     0/imm32/no-x32
    31091     0x11/imm32/alloc-id:fake
    31092     _Primitive-and-mem-with-reg/imm32/next
    31093 _Primitive-and-mem-with-reg:  # (payload primitive)
    31094     0x11/imm32/alloc-id:fake:payload
    31095     # var1/reg <- and var2 => 23/and var2/rm32 var1/r32
    31096     0x11/imm32/alloc-id:fake
    31097     _string-and/imm32/name
    31098     0x11/imm32/alloc-id:fake
    31099     Single-int-var-in-mem/imm32/inouts
    31100     0x11/imm32/alloc-id:fake
    31101     Single-int-var-in-some-register/imm32/outputs
    31102     0x11/imm32/alloc-id:fake
    31103     _string_23_and/imm32/subx-name
    31104     1/imm32/rm32-is-first-inout
    31105     3/imm32/r32-is-first-output
    31106     0/imm32/no-imm32
    31107     0/imm32/no-imm8
    31108     0/imm32/no-disp32
    31109     0/imm32/no-xm32
    31110     0/imm32/no-x32
    31111     0x11/imm32/alloc-id:fake
    31112     _Primitive-and-lit-with-reg/imm32/next
    31113 _Primitive-and-lit-with-reg:  # (payload primitive)
    31114     0x11/imm32/alloc-id:fake:payload
    31115     # var1/reg <- and lit => 81 4/subop/and var1/rm32 lit/imm32
    31116     0x11/imm32/alloc-id:fake
    31117     _string-and/imm32/name
    31118     0x11/imm32/alloc-id:fake
    31119     Single-lit-var/imm32/inouts
    31120     0x11/imm32/alloc-id:fake
    31121     Single-int-var-in-some-register/imm32/outputs
    31122     0x11/imm32/alloc-id:fake
    31123     _string_81_subop_and/imm32/subx-name
    31124     3/imm32/rm32-is-first-output
    31125     0/imm32/no-r32
    31126     1/imm32/imm32-is-first-inout
    31127     0/imm32/no-imm8
    31128     0/imm32/no-disp32
    31129     0/imm32/no-xm32
    31130     0/imm32/no-x32
    31131     0x11/imm32/alloc-id:fake
    31132     _Primitive-and-lit-with-mem/imm32/next
    31133 _Primitive-and-lit-with-mem:  # (payload primitive)
    31134     0x11/imm32/alloc-id:fake:payload
    31135     # and-with var1, lit => 81 4/subop/and var1/rm32 lit/imm32
    31136     0x11/imm32/alloc-id:fake
    31137     _string-and-with/imm32/name
    31138     0x11/imm32/alloc-id:fake
    31139     Int-var-and-literal/imm32/inouts
    31140     0/imm32/no-outputs
    31141     0/imm32/no-outputs
    31142     0x11/imm32/alloc-id:fake
    31143     _string_81_subop_and/imm32/subx-name
    31144     1/imm32/rm32-is-first-inout
    31145     0/imm32/no-r32
    31146     2/imm32/imm32-is-second-inout
    31147     0/imm32/no-imm8
    31148     0/imm32/no-disp32
    31149     0/imm32/no-xm32
    31150     0/imm32/no-x32
    31151     0x11/imm32/alloc-id:fake
    31152     _Primitive-or-with-eax/imm32/next
    31153 # - or
    31154 _Primitive-or-with-eax:  # (payload primitive)
    31155     0x11/imm32/alloc-id:fake:payload
    31156     # var/eax <- or lit => 0d/or-with-eax lit/imm32
    31157     0x11/imm32/alloc-id:fake
    31158     _string-or/imm32/name
    31159     0x11/imm32/alloc-id:fake
    31160     Single-lit-var/imm32/inouts
    31161     0x11/imm32/alloc-id:fake
    31162     Single-int-var-in-eax/imm32/outputs
    31163     0x11/imm32/alloc-id:fake
    31164     _string_0d_or_with_eax/imm32/subx-name
    31165     0/imm32/no-rm32
    31166     0/imm32/no-r32
    31167     1/imm32/imm32-is-first-inout
    31168     0/imm32/no-imm8
    31169     0/imm32/no-disp32
    31170     0/imm32/no-xm32
    31171     0/imm32/no-x32
    31172     0x11/imm32/alloc-id:fake
    31173     _Primitive-or-reg-with-reg/imm32/next
    31174 _Primitive-or-reg-with-reg:  # (payload primitive)
    31175     0x11/imm32/alloc-id:fake:payload
    31176     # var1/reg <- or var2/reg => 09/or-with var1/rm32 var2/r32
    31177     0x11/imm32/alloc-id:fake
    31178     _string-or/imm32/name
    31179     0x11/imm32/alloc-id:fake
    31180     Single-int-var-in-some-register/imm32/inouts
    31181     0x11/imm32/alloc-id:fake
    31182     Single-int-var-in-some-register/imm32/outputs
    31183     0x11/imm32/alloc-id:fake
    31184     _string_09_or_with/imm32/subx-name
    31185     3/imm32/rm32-is-first-output
    31186     1/imm32/r32-is-first-inout
    31187     0/imm32/no-imm32
    31188     0/imm32/no-imm8
    31189     0/imm32/no-disp32
    31190     0/imm32/no-xm32
    31191     0/imm32/no-x32
    31192     0x11/imm32/alloc-id:fake
    31193     _Primitive-or-reg-with-mem/imm32/next
    31194 _Primitive-or-reg-with-mem:  # (payload primitive)
    31195     0x11/imm32/alloc-id:fake:payload
    31196     # or-with var1 var2/reg => 09/or-with var1 var2/r32
    31197     0x11/imm32/alloc-id:fake
    31198     _string-or-with/imm32/name
    31199     0x11/imm32/alloc-id:fake
    31200     Two-args-int-stack-int-reg/imm32/inouts
    31201     0/imm32/no-outputs
    31202     0/imm32/no-outputs
    31203     0x11/imm32/alloc-id:fake
    31204     _string_09_or_with/imm32/subx-name
    31205     1/imm32/rm32-is-first-inout
    31206     2/imm32/r32-is-second-inout
    31207     0/imm32/no-imm32
    31208     0/imm32/no-imm8
    31209     0/imm32/no-disp32
    31210     0/imm32/no-xm32
    31211     0/imm32/no-x32
    31212     0x11/imm32/alloc-id:fake
    31213     _Primitive-or-mem-with-reg/imm32/next
    31214 _Primitive-or-mem-with-reg:  # (payload primitive)
    31215     0x11/imm32/alloc-id:fake:payload
    31216     # var1/reg <- or var2 => 0b/or var2/rm32 var1/r32
    31217     0x11/imm32/alloc-id:fake
    31218     _string-or/imm32/name
    31219     0x11/imm32/alloc-id:fake
    31220     Single-int-var-in-mem/imm32/inouts
    31221     0x11/imm32/alloc-id:fake
    31222     Single-int-var-in-some-register/imm32/outputs
    31223     0x11/imm32/alloc-id:fake
    31224     _string_0b_or/imm32/subx-name
    31225     1/imm32/rm32-is-first-inout
    31226     3/imm32/r32-is-first-output
    31227     0/imm32/no-imm32
    31228     0/imm32/no-imm8
    31229     0/imm32/no-disp32
    31230     0/imm32/no-xm32
    31231     0/imm32/no-x32
    31232     0x11/imm32/alloc-id:fake
    31233     _Primitive-or-lit-with-reg/imm32/next
    31234 _Primitive-or-lit-with-reg:  # (payload primitive)
    31235     0x11/imm32/alloc-id:fake:payload
    31236     # var1/reg <- or lit => 81 1/subop/or var1/rm32 lit/imm32
    31237     0x11/imm32/alloc-id:fake
    31238     _string-or/imm32/name
    31239     0x11/imm32/alloc-id:fake
    31240     Single-lit-var/imm32/inouts
    31241     0x11/imm32/alloc-id:fake
    31242     Single-int-var-in-some-register/imm32/outputs
    31243     0x11/imm32/alloc-id:fake
    31244     _string_81_subop_or/imm32/subx-name
    31245     3/imm32/rm32-is-first-output
    31246     0/imm32/no-r32
    31247     1/imm32/imm32-is-first-inout
    31248     0/imm32/no-imm8
    31249     0/imm32/no-disp32
    31250     0/imm32/no-xm32
    31251     0/imm32/no-x32
    31252     0x11/imm32/alloc-id:fake
    31253     _Primitive-or-lit-with-mem/imm32/next
    31254 _Primitive-or-lit-with-mem:  # (payload primitive)
    31255     0x11/imm32/alloc-id:fake:payload
    31256     # or-with var1, lit => 81 1/subop/or var1/rm32 lit/imm32
    31257     0x11/imm32/alloc-id:fake
    31258     _string-or-with/imm32/name
    31259     0x11/imm32/alloc-id:fake
    31260     Int-var-and-literal/imm32/inouts
    31261     0/imm32/no-outputs
    31262     0/imm32/no-outputs
    31263     0x11/imm32/alloc-id:fake
    31264     _string_81_subop_or/imm32/subx-name
    31265     1/imm32/rm32-is-first-inout
    31266     0/imm32/no-r32
    31267     2/imm32/imm32-is-second-inout
    31268     0/imm32/no-imm8
    31269     0/imm32/no-disp32
    31270     0/imm32/no-xm32
    31271     0/imm32/no-x32
    31272     0x11/imm32/alloc-id:fake
    31273     _Primitive-not-reg/imm32/next
    31274 # - not
    31275 _Primitive-not-reg:  # (payload primitive)
    31276     0x11/imm32/alloc-id:fake:payload
    31277     # var1/reg <- not => f7 2/subop/not var1/rm32
    31278     0x11/imm32/alloc-id:fake
    31279     _string-not/imm32/name
    31280     0/imm32/no-inouts
    31281     0/imm32/no-inouts
    31282     0x11/imm32/alloc-id:fake
    31283     Single-int-var-in-some-register/imm32/outputs
    31284     0x11/imm32/alloc-id:fake
    31285     _string_f7_subop_not/imm32/subx-name
    31286     3/imm32/rm32-is-first-output
    31287     0/imm32/no-r32
    31288     0/imm32/no-imm32
    31289     0/imm32/no-imm8
    31290     0/imm32/no-disp32
    31291     0/imm32/no-xm32
    31292     0/imm32/no-x32
    31293     0x11/imm32/alloc-id:fake
    31294     _Primitive-not-mem/imm32/next
    31295 _Primitive-not-mem:  # (payload primitive)
    31296     0x11/imm32/alloc-id:fake:payload
    31297     # not var1 => f7 2/subop/not var1/rm32
    31298     0x11/imm32/alloc-id:fake
    31299     _string-not/imm32/name
    31300     0x11/imm32/alloc-id:fake
    31301     Single-int-var-in-mem/imm32/inouts
    31302     0/imm32/no-outputs
    31303     0/imm32/no-outputs
    31304     0x11/imm32/alloc-id:fake
    31305     _string_f7_subop_not/imm32/subx-name
    31306     1/imm32/rm32-is-first-inout
    31307     0/imm32/no-r32
    31308     0/imm32/no-imm32
    31309     0/imm32/no-imm8
    31310     0/imm32/no-disp32
    31311     0/imm32/no-xm32
    31312     0/imm32/no-x32
    31313     0x11/imm32/alloc-id:fake
    31314     _Primitive-xor-with-eax/imm32/next
    31315 # - xor
    31316 _Primitive-xor-with-eax:  # (payload primitive)
    31317     0x11/imm32/alloc-id:fake:payload
    31318     # var/eax <- xor lit => 35/xor-with-eax lit/imm32
    31319     0x11/imm32/alloc-id:fake
    31320     _string-xor/imm32/name
    31321     0x11/imm32/alloc-id:fake
    31322     Single-lit-var/imm32/inouts
    31323     0x11/imm32/alloc-id:fake
    31324     Single-int-var-in-eax/imm32/outputs
    31325     0x11/imm32/alloc-id:fake
    31326     _string_35_xor_with_eax/imm32/subx-name
    31327     0/imm32/no-rm32
    31328     0/imm32/no-r32
    31329     1/imm32/imm32-is-first-inout
    31330     0/imm32/no-imm8
    31331     0/imm32/no-disp32
    31332     0/imm32/no-xm32
    31333     0/imm32/no-x32
    31334     0x11/imm32/alloc-id:fake
    31335     _Primitive-xor-reg-with-reg/imm32/next
    31336 _Primitive-xor-reg-with-reg:  # (payload primitive)
    31337     0x11/imm32/alloc-id:fake:payload
    31338     # var1/reg <- xor var2/reg => 31/xor-with var1/rm32 var2/r32
    31339     0x11/imm32/alloc-id:fake
    31340     _string-xor/imm32/name
    31341     0x11/imm32/alloc-id:fake
    31342     Single-int-var-in-some-register/imm32/inouts
    31343     0x11/imm32/alloc-id:fake
    31344     Single-int-var-in-some-register/imm32/outputs
    31345     0x11/imm32/alloc-id:fake
    31346     _string_31_xor_with/imm32/subx-name
    31347     3/imm32/rm32-is-first-output
    31348     1/imm32/r32-is-first-inout
    31349     0/imm32/no-imm32
    31350     0/imm32/no-imm8
    31351     0/imm32/no-disp32
    31352     0/imm32/no-xm32
    31353     0/imm32/no-x32
    31354     0x11/imm32/alloc-id:fake
    31355     _Primitive-xor-reg-with-mem/imm32/next
    31356 _Primitive-xor-reg-with-mem:  # (payload primitive)
    31357     0x11/imm32/alloc-id:fake:payload
    31358     # xor-with var1 var2/reg => 31/xor-with var1 var2/r32
    31359     0x11/imm32/alloc-id:fake
    31360     _string-xor-with/imm32/name
    31361     0x11/imm32/alloc-id:fake
    31362     Two-args-int-stack-int-reg/imm32/inouts
    31363     0/imm32/no-outputs
    31364     0/imm32/no-outputs
    31365     0x11/imm32/alloc-id:fake
    31366     _string_31_xor_with/imm32/subx-name
    31367     1/imm32/rm32-is-first-inout
    31368     2/imm32/r32-is-second-inout
    31369     0/imm32/no-imm32
    31370     0/imm32/no-imm8
    31371     0/imm32/no-disp32
    31372     0/imm32/no-xm32
    31373     0/imm32/no-x32
    31374     0x11/imm32/alloc-id:fake
    31375     _Primitive-xor-mem-with-reg/imm32/next
    31376 _Primitive-xor-mem-with-reg:  # (payload primitive)
    31377     0x11/imm32/alloc-id:fake:payload
    31378     # var1/reg <- xor var2 => 33/xor var2/rm32 var1/r32
    31379     0x11/imm32/alloc-id:fake
    31380     _string-xor/imm32/name
    31381     0x11/imm32/alloc-id:fake
    31382     Single-int-var-in-mem/imm32/inouts
    31383     0x11/imm32/alloc-id:fake
    31384     Single-int-var-in-some-register/imm32/outputs
    31385     0x11/imm32/alloc-id:fake
    31386     _string_33_xor/imm32/subx-name
    31387     1/imm32/rm32-is-first-inout
    31388     3/imm32/r32-is-first-output
    31389     0/imm32/no-imm32
    31390     0/imm32/no-imm8
    31391     0/imm32/no-disp32
    31392     0/imm32/no-xm32
    31393     0/imm32/no-x32
    31394     0x11/imm32/alloc-id:fake
    31395     _Primitive-xor-lit-with-reg/imm32/next
    31396 _Primitive-xor-lit-with-reg:  # (payload primitive)
    31397     0x11/imm32/alloc-id:fake:payload
    31398     # var1/reg <- xor lit => 81 6/subop/xor var1/rm32 lit/imm32
    31399     0x11/imm32/alloc-id:fake
    31400     _string-xor/imm32/name
    31401     0x11/imm32/alloc-id:fake
    31402     Single-lit-var/imm32/inouts
    31403     0x11/imm32/alloc-id:fake
    31404     Single-int-var-in-some-register/imm32/outputs
    31405     0x11/imm32/alloc-id:fake
    31406     _string_81_subop_xor/imm32/subx-name
    31407     3/imm32/rm32-is-first-output
    31408     0/imm32/no-r32
    31409     1/imm32/imm32-is-first-inout
    31410     0/imm32/no-imm8
    31411     0/imm32/no-disp32
    31412     0/imm32/no-xm32
    31413     0/imm32/no-x32
    31414     0x11/imm32/alloc-id:fake
    31415     _Primitive-xor-lit-with-mem/imm32/next
    31416 _Primitive-xor-lit-with-mem:  # (payload primitive)
    31417     0x11/imm32/alloc-id:fake:payload
    31418     # xor-with var1, lit => 81 6/subop/xor var1/rm32 lit/imm32
    31419     0x11/imm32/alloc-id:fake
    31420     _string-xor-with/imm32/name
    31421     0x11/imm32/alloc-id:fake
    31422     Int-var-and-literal/imm32/inouts
    31423     0/imm32/no-outputs
    31424     0/imm32/no-outputs
    31425     0x11/imm32/alloc-id:fake
    31426     _string_81_subop_xor/imm32/subx-name
    31427     1/imm32/rm32-is-first-inout
    31428     0/imm32/no-r32
    31429     2/imm32/imm32-is-second-inout
    31430     0/imm32/no-imm8
    31431     0/imm32/no-disp32
    31432     0/imm32/no-xm32
    31433     0/imm32/no-x32
    31434     0x11/imm32/alloc-id:fake
    31435     _Primitive-shift-reg-left-by-lit/imm32/next
    31436 _Primitive-shift-reg-left-by-lit:  # (payload primitive)
    31437     0x11/imm32/alloc-id:fake:payload
    31438     # var1/reg <- shift-left lit => c1/shift 4/subop/left var1/rm32 lit/imm32
    31439     0x11/imm32/alloc-id:fake
    31440     _string-shift-left/imm32/name
    31441     0x11/imm32/alloc-id:fake
    31442     Single-lit-var/imm32/inouts
    31443     0x11/imm32/alloc-id:fake
    31444     Single-int-var-in-some-register/imm32/outputs
    31445     0x11/imm32/alloc-id:fake
    31446     _string_c1_subop_shift_left/imm32/subx-name
    31447     3/imm32/rm32-is-first-output
    31448     0/imm32/no-r32
    31449     0/imm32/no-imm32
    31450     1/imm32/imm8-is-first-inout
    31451     0/imm32/no-disp32
    31452     0/imm32/no-xm32
    31453     0/imm32/no-x32
    31454     0x11/imm32/alloc-id:fake
    31455     _Primitive-shift-reg-right-by-lit/imm32/next
    31456 _Primitive-shift-reg-right-by-lit:  # (payload primitive)
    31457     0x11/imm32/alloc-id:fake:payload
    31458     # var1/reg <- shift-right lit => c1/shift 5/subop/right var1/rm32 lit/imm32
    31459     0x11/imm32/alloc-id:fake
    31460     _string-shift-right/imm32/name
    31461     0x11/imm32/alloc-id:fake
    31462     Single-lit-var/imm32/inouts
    31463     0x11/imm32/alloc-id:fake
    31464     Single-int-var-in-some-register/imm32/outputs
    31465     0x11/imm32/alloc-id:fake
    31466     _string_c1_subop_shift_right_padding_zeroes/imm32/subx-name
    31467     3/imm32/rm32-is-first-output
    31468     0/imm32/no-r32
    31469     0/imm32/no-imm32
    31470     1/imm32/imm8-is-first-inout
    31471     0/imm32/no-disp32
    31472     0/imm32/no-xm32
    31473     0/imm32/no-x32
    31474     0x11/imm32/alloc-id:fake
    31475     _Primitive-shift-reg-right-signed-by-lit/imm32/next
    31476 _Primitive-shift-reg-right-signed-by-lit:  # (payload primitive)
    31477     0x11/imm32/alloc-id:fake:payload
    31478     # var1/reg <- shift-right-signed lit => c1/shift 7/subop/right-preserving-sign var1/rm32 lit/imm32
    31479     0x11/imm32/alloc-id:fake
    31480     _string-shift-right-signed/imm32/name
    31481     0x11/imm32/alloc-id:fake
    31482     Single-lit-var/imm32/inouts
    31483     0x11/imm32/alloc-id:fake
    31484     Single-int-var-in-some-register/imm32/outputs
    31485     0x11/imm32/alloc-id:fake
    31486     _string_c1_subop_shift_right_preserving_sign/imm32/subx-name
    31487     3/imm32/rm32-is-first-output
    31488     0/imm32/no-r32
    31489     0/imm32/no-imm32
    31490     1/imm32/imm8-is-first-inout
    31491     0/imm32/no-disp32
    31492     0/imm32/no-xm32
    31493     0/imm32/no-x32
    31494     0x11/imm32/alloc-id:fake
    31495     _Primitive-shift-mem-left-by-lit/imm32/next
    31496 _Primitive-shift-mem-left-by-lit:  # (payload primitive)
    31497     0x11/imm32/alloc-id:fake:payload
    31498     # shift-left var1, lit => c1/shift 4/subop/left var1/rm32 lit/imm32
    31499     0x11/imm32/alloc-id:fake
    31500     _string-shift-left/imm32/name
    31501     0x11/imm32/alloc-id:fake
    31502     Int-var-and-literal/imm32/inouts
    31503     0/imm32/no-outputs
    31504     0/imm32/no-outputs
    31505     0x11/imm32/alloc-id:fake
    31506     _string_c1_subop_shift_left/imm32/subx-name
    31507     1/imm32/rm32-is-first-inout
    31508     0/imm32/no-r32
    31509     0/imm32/no-imm32
    31510     2/imm32/imm8-is-second-inout
    31511     0/imm32/no-disp32
    31512     0/imm32/no-xm32
    31513     0/imm32/no-x32
    31514     0x11/imm32/alloc-id:fake
    31515     _Primitive-shift-mem-right-by-lit/imm32/next
    31516 _Primitive-shift-mem-right-by-lit:  # (payload primitive)
    31517     0x11/imm32/alloc-id:fake:payload
    31518     # shift-right var1, lit => c1/shift 5/subop/right var1/rm32 lit/imm32
    31519     0x11/imm32/alloc-id:fake
    31520     _string-shift-right/imm32/name
    31521     0x11/imm32/alloc-id:fake
    31522     Int-var-and-literal/imm32/inouts
    31523     0/imm32/no-outputs
    31524     0/imm32/no-outputs
    31525     0x11/imm32/alloc-id:fake
    31526     _string_c1_subop_shift_right_padding_zeroes/imm32/subx-name
    31527     1/imm32/rm32-is-first-inout
    31528     0/imm32/no-r32
    31529     0/imm32/no-imm32
    31530     2/imm32/imm8-is-second-inout
    31531     0/imm32/no-disp32
    31532     0/imm32/no-xm32
    31533     0/imm32/no-x32
    31534     0x11/imm32/alloc-id:fake
    31535     _Primitive-shift-mem-right-signed-by-lit/imm32/next
    31536 _Primitive-shift-mem-right-signed-by-lit:  # (payload primitive)
    31537     0x11/imm32/alloc-id:fake:payload
    31538     # shift-right-signed var1, lit => c1/shift 7/subop/right-preserving-sign var1/rm32 lit/imm32
    31539     0x11/imm32/alloc-id:fake
    31540     _string-shift-right-signed/imm32/name
    31541     0x11/imm32/alloc-id:fake
    31542     Int-var-and-literal/imm32/inouts
    31543     0/imm32/no-outputs
    31544     0/imm32/no-outputs
    31545     0x11/imm32/alloc-id:fake
    31546     _string_c1_subop_shift_right_preserving_sign/imm32/subx-name
    31547     1/imm32/rm32-is-first-inout
    31548     0/imm32/no-r32
    31549     0/imm32/no-imm32
    31550     2/imm32/imm8-is-second-inout
    31551     0/imm32/no-disp32
    31552     0/imm32/no-xm32
    31553     0/imm32/no-x32
    31554     0x11/imm32/alloc-id:fake
    31555     _Primitive-copy-to-eax/imm32/next
    31556 # - copy
    31557 _Primitive-copy-to-eax:  # (payload primitive)
    31558     0x11/imm32/alloc-id:fake:payload
    31559     # var/eax <- copy lit => b8/copy-to-eax lit/imm32
    31560     0x11/imm32/alloc-id:fake
    31561     _string-copy/imm32/name
    31562     0x11/imm32/alloc-id:fake
    31563     Single-lit-var/imm32/inouts
    31564     0x11/imm32/alloc-id:fake
    31565     Single-int-var-in-eax/imm32/outputs
    31566     0x11/imm32/alloc-id:fake
    31567     _string_b8_copy_to_eax/imm32/subx-name
    31568     0/imm32/no-rm32
    31569     0/imm32/no-r32
    31570     1/imm32/imm32-is-first-inout
    31571     0/imm32/no-imm8
    31572     0/imm32/no-disp32
    31573     0/imm32/no-xm32
    31574     0/imm32/no-x32
    31575     0x11/imm32/alloc-id:fake
    31576     _Primitive-copy-to-ecx/imm32/next
    31577 _Primitive-copy-to-ecx:  # (payload primitive)
    31578     0x11/imm32/alloc-id:fake:payload
    31579     # var/ecx <- copy lit => b9/copy-to-ecx lit/imm32
    31580     0x11/imm32/alloc-id:fake
    31581     _string-copy/imm32/name
    31582     0x11/imm32/alloc-id:fake
    31583     Single-lit-var/imm32/inouts
    31584     0x11/imm32/alloc-id:fake
    31585     Single-int-var-in-ecx/imm32/outputs
    31586     0x11/imm32/alloc-id:fake
    31587     _string_b9_copy_to_ecx/imm32/subx-name
    31588     0/imm32/no-rm32
    31589     0/imm32/no-r32
    31590     1/imm32/imm32-is-first-inout
    31591     0/imm32/no-imm8
    31592     0/imm32/no-disp32
    31593     0/imm32/no-xm32
    31594     0/imm32/no-x32
    31595     0x11/imm32/alloc-id:fake
    31596     _Primitive-copy-to-edx/imm32/next
    31597 _Primitive-copy-to-edx:  # (payload primitive)
    31598     0x11/imm32/alloc-id:fake:payload
    31599     # var/edx <- copy lit => ba/copy-to-edx lit/imm32
    31600     0x11/imm32/alloc-id:fake
    31601     _string-copy/imm32/name
    31602     0x11/imm32/alloc-id:fake
    31603     Single-lit-var/imm32/inouts
    31604     0x11/imm32/alloc-id:fake
    31605     Single-int-var-in-edx/imm32/outputs
    31606     0x11/imm32/alloc-id:fake
    31607     _string_ba_copy_to_edx/imm32/subx-name
    31608     0/imm32/no-rm32
    31609     0/imm32/no-r32
    31610     1/imm32/imm32-is-first-inout
    31611     0/imm32/no-imm8
    31612     0/imm32/no-disp32
    31613     0/imm32/no-xm32
    31614     0/imm32/no-x32
    31615     0x11/imm32/alloc-id:fake
    31616     _Primitive-copy-to-ebx/imm32/next
    31617 _Primitive-copy-to-ebx:  # (payload primitive)
    31618     0x11/imm32/alloc-id:fake:payload
    31619     # var/ebx <- copy lit => bb/copy-to-ebx lit/imm32
    31620     0x11/imm32/alloc-id:fake
    31621     _string-copy/imm32/name
    31622     0x11/imm32/alloc-id:fake
    31623     Single-lit-var/imm32/inouts
    31624     0x11/imm32/alloc-id:fake
    31625     Single-int-var-in-ebx/imm32/outputs
    31626     0x11/imm32/alloc-id:fake
    31627     _string_bb_copy_to_ebx/imm32/subx-name
    31628     0/imm32/no-rm32
    31629     0/imm32/no-r32
    31630     1/imm32/imm32-is-first-inout
    31631     0/imm32/no-imm8
    31632     0/imm32/no-disp32
    31633     0/imm32/no-xm32
    31634     0/imm32/no-x32
    31635     0x11/imm32/alloc-id:fake
    31636     _Primitive-copy-to-esi/imm32/next
    31637 _Primitive-copy-to-esi:  # (payload primitive)
    31638     0x11/imm32/alloc-id:fake:payload
    31639     # var/esi <- copy lit => be/copy-to-esi lit/imm32
    31640     0x11/imm32/alloc-id:fake
    31641     _string-copy/imm32/name
    31642     0x11/imm32/alloc-id:fake
    31643     Single-lit-var/imm32/inouts
    31644     0x11/imm32/alloc-id:fake
    31645     Single-int-var-in-esi/imm32/outputs
    31646     0x11/imm32/alloc-id:fake
    31647     _string_be_copy_to_esi/imm32/subx-name
    31648     0/imm32/no-rm32
    31649     0/imm32/no-r32
    31650     1/imm32/imm32-is-first-inout
    31651     0/imm32/no-imm8
    31652     0/imm32/no-disp32
    31653     0/imm32/no-xm32
    31654     0/imm32/no-x32
    31655     0x11/imm32/alloc-id:fake
    31656     _Primitive-copy-to-edi/imm32/next
    31657 _Primitive-copy-to-edi:  # (payload primitive)
    31658     0x11/imm32/alloc-id:fake:payload
    31659     # var/edi <- copy lit => bf/copy-to-edi lit/imm32
    31660     0x11/imm32/alloc-id:fake
    31661     _string-copy/imm32/name
    31662     0x11/imm32/alloc-id:fake
    31663     Single-lit-var/imm32/inouts
    31664     0x11/imm32/alloc-id:fake
    31665     Single-int-var-in-edi/imm32/outputs
    31666     0x11/imm32/alloc-id:fake
    31667     _string_bf_copy_to_edi/imm32/subx-name
    31668     0/imm32/no-rm32
    31669     0/imm32/no-r32
    31670     1/imm32/imm32-is-first-inout
    31671     0/imm32/no-imm8
    31672     0/imm32/no-disp32
    31673     0/imm32/no-xm32
    31674     0/imm32/no-x32
    31675     0x11/imm32/alloc-id:fake
    31676     _Primitive-copy-reg-to-reg/imm32/next
    31677 _Primitive-copy-reg-to-reg:  # (payload primitive)
    31678     0x11/imm32/alloc-id:fake:payload
    31679     # var1/reg <- copy var2/reg => 89/<- var1/rm32 var2/r32
    31680     0x11/imm32/alloc-id:fake
    31681     _string-copy/imm32/name
    31682     0x11/imm32/alloc-id:fake
    31683     Single-int-var-in-some-register/imm32/inouts
    31684     0x11/imm32/alloc-id:fake
    31685     Single-int-var-in-some-register/imm32/outputs
    31686     0x11/imm32/alloc-id:fake
    31687     _string_89_<-/imm32/subx-name
    31688     3/imm32/rm32-is-first-output
    31689     1/imm32/r32-is-first-inout
    31690     0/imm32/no-imm32
    31691     0/imm32/no-imm8
    31692     0/imm32/no-disp32
    31693     0/imm32/no-xm32
    31694     0/imm32/no-x32
    31695     0x11/imm32/alloc-id:fake
    31696     _Primitive-copy-reg-to-mem/imm32/next
    31697 _Primitive-copy-reg-to-mem:  # (payload primitive)
    31698     0x11/imm32/alloc-id:fake:payload
    31699     # copy-to var1 var2/reg => 89/<- var1 var2/r32
    31700     0x11/imm32/alloc-id:fake
    31701     _string-copy-to/imm32/name
    31702     0x11/imm32/alloc-id:fake
    31703     Two-args-int-stack-int-reg/imm32/inouts
    31704     0/imm32/no-outputs
    31705     0/imm32/no-outputs
    31706     0x11/imm32/alloc-id:fake
    31707     _string_89_<-/imm32/subx-name
    31708     1/imm32/rm32-is-first-inout
    31709     2/imm32/r32-is-second-inout
    31710     0/imm32/no-imm32
    31711     0/imm32/no-imm8
    31712     0/imm32/no-disp32
    31713     0/imm32/no-xm32
    31714     0/imm32/no-x32
    31715     0x11/imm32/alloc-id:fake
    31716     _Primitive-copy-mem-to-reg/imm32/next
    31717 _Primitive-copy-mem-to-reg:  # (payload primitive)
    31718     0x11/imm32/alloc-id:fake:payload
    31719     # var1/reg <- copy var2 => 8b/-> var2/rm32 var1/r32
    31720     0x11/imm32/alloc-id:fake
    31721     _string-copy/imm32/name
    31722     0x11/imm32/alloc-id:fake
    31723     Single-int-var-in-mem/imm32/inouts
    31724     0x11/imm32/alloc-id:fake
    31725     Single-int-var-in-some-register/imm32/outputs
    31726     0x11/imm32/alloc-id:fake
    31727     _string_8b_->/imm32/subx-name
    31728     1/imm32/rm32-is-first-inout
    31729     3/imm32/r32-is-first-output
    31730     0/imm32/no-imm32
    31731     0/imm32/no-imm8
    31732     0/imm32/no-disp32
    31733     0/imm32/no-xm32
    31734     0/imm32/no-x32
    31735     0x11/imm32/alloc-id:fake
    31736     _Primitive-copy-lit-to-reg/imm32/next
    31737 _Primitive-copy-lit-to-reg:  # (payload primitive)
    31738     0x11/imm32/alloc-id:fake:payload
    31739     # var1/reg <- copy lit => c7 0/subop/copy var1/rm32 lit/imm32
    31740     0x11/imm32/alloc-id:fake
    31741     _string-copy/imm32/name
    31742     0x11/imm32/alloc-id:fake
    31743     Single-lit-var/imm32/inouts
    31744     0x11/imm32/alloc-id:fake
    31745     Single-int-var-in-some-register/imm32/outputs
    31746     0x11/imm32/alloc-id:fake
    31747     _string_c7_subop_copy/imm32/subx-name
    31748     3/imm32/rm32-is-first-output
    31749     0/imm32/no-r32
    31750     1/imm32/imm32-is-first-inout
    31751     0/imm32/no-imm8
    31752     0/imm32/no-disp32
    31753     0/imm32/no-xm32
    31754     0/imm32/no-x32
    31755     0x11/imm32/alloc-id:fake
    31756     _Primitive-copy-lit-to-mem/imm32/next
    31757 _Primitive-copy-lit-to-mem:  # (payload primitive)
    31758     0x11/imm32/alloc-id:fake:payload
    31759     # copy-to var1, lit => c7 0/subop/copy var1/rm32 lit/imm32
    31760     0x11/imm32/alloc-id:fake
    31761     _string-copy-to/imm32/name
    31762     0x11/imm32/alloc-id:fake
    31763     Int-var-and-literal/imm32/inouts
    31764     0/imm32/no-outputs
    31765     0/imm32/no-outputs
    31766     0x11/imm32/alloc-id:fake
    31767     _string_c7_subop_copy/imm32/subx-name
    31768     1/imm32/rm32-is-first-inout
    31769     0/imm32/no-r32
    31770     2/imm32/imm32-is-second-inout
    31771     0/imm32/no-imm8
    31772     0/imm32/no-disp32
    31773     0/imm32/no-xm32
    31774     0/imm32/no-x32
    31775     0x11/imm32/alloc-id:fake
    31776     _Primitive-copy-byte-from-reg/imm32/next
    31777 # - copy byte
    31778 _Primitive-copy-byte-from-reg:
    31779     0x11/imm32/alloc-id:fake:payload
    31780     # var/reg <- copy-byte var2/reg2 => 8a/byte-> %var2 var/r32
    31781     0x11/imm32/alloc-id:fake
    31782     _string-copy-byte/imm32/name
    31783     0x11/imm32/alloc-id:fake
    31784     Single-byte-var-in-some-register/imm32/inouts
    31785     0x11/imm32/alloc-id:fake
    31786     Single-byte-var-in-some-register/imm32/outputs
    31787     0x11/imm32/alloc-id:fake
    31788     _string_8a_copy_byte/imm32/subx-name
    31789     1/imm32/rm32-is-first-inout
    31790     3/imm32/r32-is-first-output
    31791     0/imm32/no-imm32
    31792     0/imm32/no-imm8
    31793     0/imm32/no-disp32
    31794     0/imm32/no-xm32
    31795     0/imm32/no-x32
    31796     0x11/imm32/alloc-id:fake
    31797     _Primitive-copy-byte-from-mem/imm32/next
    31798 _Primitive-copy-byte-from-mem:
    31799     0x11/imm32/alloc-id:fake:payload
    31800     # var/reg <- copy-byte *var2/reg2 => 8a/byte-> *var2 var/r32
    31801     0x11/imm32/alloc-id:fake
    31802     _string-copy-byte/imm32/name
    31803     0x11/imm32/alloc-id:fake
    31804     Single-byte-var-in-mem/imm32/inouts
    31805     0x11/imm32/alloc-id:fake
    31806     Single-byte-var-in-some-register/imm32/outputs
    31807     0x11/imm32/alloc-id:fake
    31808     _string_8a_copy_byte/imm32/subx-name
    31809     1/imm32/rm32-is-first-inout
    31810     3/imm32/r32-is-first-output
    31811     0/imm32/no-imm32
    31812     0/imm32/no-imm8
    31813     0/imm32/no-disp32
    31814     0/imm32/no-xm32
    31815     0/imm32/no-x32
    31816     0x11/imm32/alloc-id:fake
    31817     _Primitive-copy-byte-to-mem/imm32/next
    31818 _Primitive-copy-byte-to-mem:
    31819     0x11/imm32/alloc-id:fake:payload
    31820     # copy-byte-to *var1/reg1, var2/reg2 => 88/byte<- *reg1 reg2/r32
    31821     0x11/imm32/alloc-id:fake
    31822     _string-copy-byte-to/imm32/name
    31823     0x11/imm32/alloc-id:fake
    31824     Two-args-byte-stack-byte-reg/imm32/inouts
    31825     0/imm32/no-outputs
    31826     0/imm32/no-outputs
    31827     0x11/imm32/alloc-id:fake
    31828     _string_88_copy_byte/imm32/subx-name
    31829     1/imm32/rm32-is-first-inout
    31830     2/imm32/r32-is-second-inout
    31831     0/imm32/no-imm32
    31832     0/imm32/no-imm8
    31833     0/imm32/no-disp32
    31834     0/imm32/no-xm32
    31835     0/imm32/no-x32
    31836     0x11/imm32/alloc-id:fake
    31837     _Primitive-address/imm32/next
    31838 # - address
    31839 _Primitive-address:  # (payload primitive)
    31840     0x11/imm32/alloc-id:fake:payload
    31841     # var1/reg <- address var2 => 8d/copy-address var2/rm32 var1/r32
    31842     0x11/imm32/alloc-id:fake
    31843     _string-address/imm32/name
    31844     0x11/imm32/alloc-id:fake
    31845     Single-int-var-in-mem/imm32/inouts
    31846     0x11/imm32/alloc-id:fake
    31847     Single-addr-var-in-some-register/imm32/outputs
    31848     0x11/imm32/alloc-id:fake
    31849     _string_8d_copy_address/imm32/subx-name
    31850     1/imm32/rm32-is-first-inout
    31851     3/imm32/r32-is-first-output
    31852     0/imm32/no-imm32
    31853     0/imm32/no-imm8
    31854     0/imm32/no-disp32
    31855     0/imm32/no-xm32
    31856     0/imm32/no-x32
    31857     0x11/imm32/alloc-id:fake
    31858     _Primitive-compare-reg-with-reg/imm32/next
    31859 # - compare
    31860 _Primitive-compare-reg-with-reg:  # (payload primitive)
    31861     0x11/imm32/alloc-id:fake:payload
    31862     # compare var1/reg1 var2/reg2 => 39/compare var1/rm32 var2/r32
    31863     0x11/imm32/alloc-id:fake
    31864     _string-compare/imm32/name
    31865     0x11/imm32/alloc-id:fake
    31866     Two-int-args-in-regs/imm32/inouts
    31867     0/imm32/no-outputs
    31868     0/imm32/no-outputs
    31869     0x11/imm32/alloc-id:fake
    31870     _string_39_compare->/imm32/subx-name
    31871     1/imm32/rm32-is-first-inout
    31872     2/imm32/r32-is-second-inout
    31873     0/imm32/no-imm32
    31874     0/imm32/no-imm8
    31875     0/imm32/no-disp32
    31876     0/imm32/no-xm32
    31877     0/imm32/no-x32
    31878     0x11/imm32/alloc-id:fake
    31879     _Primitive-compare-mem-with-reg/imm32/next
    31880 _Primitive-compare-mem-with-reg:  # (payload primitive)
    31881     0x11/imm32/alloc-id:fake:payload
    31882     # compare var1 var2/reg => 39/compare var1/rm32 var2/r32
    31883     0x11/imm32/alloc-id:fake
    31884     _string-compare/imm32/name
    31885     0x11/imm32/alloc-id:fake
    31886     Two-args-int-stack-int-reg/imm32/inouts
    31887     0/imm32/no-outputs
    31888     0/imm32/no-outputs
    31889     0x11/imm32/alloc-id:fake
    31890     _string_39_compare->/imm32/subx-name
    31891     1/imm32/rm32-is-first-inout
    31892     2/imm32/r32-is-second-inout
    31893     0/imm32/no-imm32
    31894     0/imm32/no-imm8
    31895     0/imm32/no-disp32
    31896     0/imm32/no-xm32
    31897     0/imm32/no-x32
    31898     0x11/imm32/alloc-id:fake
    31899     _Primitive-compare-reg-with-mem/imm32/next
    31900 _Primitive-compare-reg-with-mem:  # (payload primitive)
    31901     0x11/imm32/alloc-id:fake:payload
    31902     # compare var1/reg var2 => 3b/compare<- var2/rm32 var1/r32
    31903     0x11/imm32/alloc-id:fake
    31904     _string-compare/imm32/name
    31905     0x11/imm32/alloc-id:fake
    31906     Two-args-int-reg-int-stack/imm32/inouts
    31907     0/imm32/no-outputs
    31908     0/imm32/no-outputs
    31909     0x11/imm32/alloc-id:fake
    31910     _string_3b_compare<-/imm32/subx-name
    31911     2/imm32/rm32-is-second-inout
    31912     1/imm32/r32-is-first-inout
    31913     0/imm32/no-imm32
    31914     0/imm32/no-imm8
    31915     0/imm32/no-disp32
    31916     0/imm32/no-xm32
    31917     0/imm32/no-x32
    31918     0x11/imm32/alloc-id:fake
    31919     _Primitive-compare-eax-with-literal/imm32/next
    31920 _Primitive-compare-eax-with-literal:  # (payload primitive)
    31921     0x11/imm32/alloc-id:fake:payload
    31922     # compare var1/eax n => 3d/compare-eax-with n/imm32
    31923     0x11/imm32/alloc-id:fake
    31924     _string-compare/imm32/name
    31925     0x11/imm32/alloc-id:fake
    31926     Two-args-int-eax-int-literal/imm32/inouts
    31927     0/imm32/no-outputs
    31928     0/imm32/no-outputs
    31929     0x11/imm32/alloc-id:fake
    31930     _string_3d_compare_eax_with/imm32/subx-name
    31931     0/imm32/no-rm32
    31932     0/imm32/no-r32
    31933     2/imm32/imm32-is-second-inout
    31934     0/imm32/no-imm8
    31935     0/imm32/no-disp32
    31936     0/imm32/no-xm32
    31937     0/imm32/no-x32
    31938     0x11/imm32/alloc-id:fake
    31939     _Primitive-compare-reg-with-literal/imm32/next
    31940 _Primitive-compare-reg-with-literal:  # (payload primitive)
    31941     0x11/imm32/alloc-id:fake:payload
    31942     # compare var1/reg n => 81 7/subop/compare %reg n/imm32
    31943     0x11/imm32/alloc-id:fake
    31944     _string-compare/imm32/name
    31945     0x11/imm32/alloc-id:fake
    31946     Int-var-in-register-and-literal/imm32/inouts
    31947     0/imm32/no-outputs
    31948     0/imm32/no-outputs
    31949     0x11/imm32/alloc-id:fake
    31950     _string_81_subop_compare/imm32/subx-name
    31951     1/imm32/rm32-is-first-inout
    31952     0/imm32/no-r32
    31953     2/imm32/imm32-is-second-inout
    31954     0/imm32/no-imm8
    31955     0/imm32/no-disp32
    31956     0/imm32/no-xm32
    31957     0/imm32/no-x32
    31958     0x11/imm32/alloc-id:fake
    31959     _Primitive-compare-mem-with-literal/imm32/next
    31960 _Primitive-compare-mem-with-literal:  # (payload primitive)
    31961     0x11/imm32/alloc-id:fake:payload
    31962     # compare var1 n => 81 7/subop/compare *(ebp+___) n/imm32
    31963     0x11/imm32/alloc-id:fake
    31964     _string-compare/imm32/name
    31965     0x11/imm32/alloc-id:fake
    31966     Int-var-and-literal/imm32/inouts
    31967     0/imm32/no-outputs
    31968     0/imm32/no-outputs
    31969     0x11/imm32/alloc-id:fake
    31970     _string_81_subop_compare/imm32/subx-name
    31971     1/imm32/rm32-is-first-inout
    31972     0/imm32/no-r32
    31973     2/imm32/imm32-is-second-inout
    31974     0/imm32/no-imm8
    31975     0/imm32/no-disp32
    31976     0/imm32/no-xm32
    31977     0/imm32/no-x32
    31978     0x11/imm32/alloc-id:fake
    31979     _Primitive-negate-reg/imm32/next
    31980 # - negate
    31981 _Primitive-negate-reg:  # (payload primitive)
    31982     0x11/imm32/alloc-id:fake:payload
    31983     # var1/reg <- negate => f7 3/subop/negate var1/rm32
    31984     0x11/imm32/alloc-id:fake
    31985     _string-negate/imm32/name
    31986     0/imm32/no-inouts
    31987     0/imm32/no-inouts
    31988     0x11/imm32/alloc-id:fake
    31989     Single-int-var-in-some-register/imm32/outputs
    31990     0x11/imm32/alloc-id:fake
    31991     _string_f7_subop_negate/imm32/subx-name
    31992     3/imm32/rm32-is-first-output
    31993     0/imm32/no-r32
    31994     0/imm32/no-imm32
    31995     0/imm32/no-imm8
    31996     0/imm32/no-disp32
    31997     0/imm32/no-xm32
    31998     0/imm32/no-x32
    31999     0x11/imm32/alloc-id:fake
    32000     _Primitive-negate-mem/imm32/next
    32001 _Primitive-negate-mem:  # (payload primitive)
    32002     0x11/imm32/alloc-id:fake:payload
    32003     # negate var1 => f7 3/subop/negate var1/rm32
    32004     0x11/imm32/alloc-id:fake
    32005     _string-negate/imm32/name
    32006     0x11/imm32/alloc-id:fake
    32007     Single-int-var-in-mem/imm32/inouts
    32008     0/imm32/no-outputs
    32009     0/imm32/no-outputs
    32010     0x11/imm32/alloc-id:fake
    32011     _string_f7_subop_negate/imm32/subx-name
    32012     1/imm32/rm32-is-first-inout
    32013     0/imm32/no-r32
    32014     0/imm32/no-imm32
    32015     0/imm32/no-imm8
    32016     0/imm32/no-disp32
    32017     0/imm32/no-xm32
    32018     0/imm32/no-x32
    32019     0x11/imm32/alloc-id:fake
    32020     _Primitive-multiply-reg-by-reg/imm32/next
    32021 # - multiply
    32022 _Primitive-multiply-reg-by-reg:  # (payload primitive)
    32023     0x11/imm32/alloc-id:fake:payload
    32024     # var1/reg <- multiply var2 => 0f af/multiply var2/rm32 var1/r32
    32025     0x11/imm32/alloc-id:fake
    32026     _string-multiply/imm32/name
    32027     0x11/imm32/alloc-id:fake
    32028     Single-int-var-in-some-register/imm32/inouts
    32029     0x11/imm32/alloc-id:fake
    32030     Single-int-var-in-some-register/imm32/outputs
    32031     0x11/imm32/alloc-id:fake
    32032     _string_0f_af_multiply/imm32/subx-name
    32033     1/imm32/rm32-is-first-inout
    32034     3/imm32/r32-is-first-output
    32035     0/imm32/no-imm32
    32036     0/imm32/no-imm8
    32037     0/imm32/no-disp32
    32038     0/imm32/no-xm32
    32039     0/imm32/no-x32
    32040     0x11/imm32/alloc-id:fake
    32041     _Primitive-multiply-reg-by-mem/imm32/next
    32042 _Primitive-multiply-reg-by-mem:  # (payload primitive)
    32043     0x11/imm32/alloc-id:fake:payload
    32044     # var1/reg <- multiply var2 => 0f af/multiply var2/rm32 var1/r32
    32045     0x11/imm32/alloc-id:fake
    32046     _string-multiply/imm32/name
    32047     0x11/imm32/alloc-id:fake
    32048     Single-int-var-in-mem/imm32/inouts
    32049     0x11/imm32/alloc-id:fake
    32050     Single-int-var-in-some-register/imm32/outputs
    32051     0x11/imm32/alloc-id:fake
    32052     _string_0f_af_multiply/imm32/subx-name
    32053     1/imm32/rm32-is-first-inout
    32054     3/imm32/r32-is-first-output
    32055     0/imm32/no-imm32
    32056     0/imm32/no-imm8
    32057     0/imm32/no-disp32
    32058     0/imm32/no-xm32
    32059     0/imm32/no-x32
    32060     0x11/imm32/alloc-id:fake
    32061     _Primitive-convert-mem-to-xreg/imm32/next
    32062 # - convert int to floating point
    32063 _Primitive-convert-mem-to-xreg:  # (payload primitive)
    32064     0x11/imm32/alloc-id:fake:payload
    32065     # var1/xreg <- convert var2 => f3 0f 2a/convert-to-float var2/rm32 var1/x32
    32066     0x11/imm32/alloc-id:fake
    32067     _string-convert/imm32/name
    32068     0x11/imm32/alloc-id:fake
    32069     Single-int-var-in-mem/imm32/inouts
    32070     0x11/imm32/alloc-id:fake
    32071     Single-float-var-in-some-register/imm32/outputs
    32072     0x11/imm32/alloc-id:fake
    32073     _string_f3_0f_2a_convert_to_float/imm32/subx-name
    32074     1/imm32/rm32-is-first-inout
    32075     0/imm32/no-r32
    32076     0/imm32/no-imm32
    32077     0/imm32/no-imm8
    32078     0/imm32/no-disp32
    32079     0/imm32/no-xm32
    32080     3/imm32/x32-is-first-output
    32081     0x11/imm32/alloc-id:fake
    32082     _Primitive-convert-reg-to-xreg/imm32/next
    32083 _Primitive-convert-reg-to-xreg:  # (payload primitive)
    32084     0x11/imm32/alloc-id:fake:payload
    32085     # var1/xreg <- convert var2/reg => f3 0f 2a/convert-to-float var2/rm32 var1/x32
    32086     0x11/imm32/alloc-id:fake
    32087     _string-convert/imm32/name
    32088     0x11/imm32/alloc-id:fake
    32089     Single-int-var-in-some-register/imm32/inouts
    32090     0x11/imm32/alloc-id:fake
    32091     Single-float-var-in-some-register/imm32/outputs
    32092     0x11/imm32/alloc-id:fake
    32093     _string_f3_0f_2a_convert_to_float/imm32/subx-name
    32094     1/imm32/rm32-is-first-inout
    32095     0/imm32/no-r32
    32096     0/imm32/no-imm32
    32097     0/imm32/no-imm8
    32098     0/imm32/no-disp32
    32099     0/imm32/no-xm32
    32100     3/imm32/x32-is-first-output
    32101     0x11/imm32/alloc-id:fake
    32102     _Primitive-convert-xmem-to-reg/imm32/next
    32103 # - convert floating point to int
    32104 _Primitive-convert-xmem-to-reg:  # (payload primitive)
    32105     0x11/imm32/alloc-id:fake:payload
    32106     # var1/reg <- convert var2 => f3 0f 2d/convert-to-int var2/xm32 var1/r32
    32107     0x11/imm32/alloc-id:fake
    32108     _string-convert/imm32/name
    32109     0x11/imm32/alloc-id:fake
    32110     Single-float-var-in-mem/imm32/inouts
    32111     0x11/imm32/alloc-id:fake
    32112     Single-int-var-in-some-register/imm32/outputs
    32113     0x11/imm32/alloc-id:fake
    32114     _string_f3_0f_2d_convert_to_int/imm32/subx-name
    32115     0/imm32/no-rm32
    32116     3/imm32/r32-is-first-output
    32117     0/imm32/no-imm32
    32118     0/imm32/no-imm8
    32119     0/imm32/no-disp32
    32120     1/imm32/xm32-is-first-inout
    32121     0/imm32/no-x32
    32122     0x11/imm32/alloc-id:fake
    32123     _Primitive-convert-xreg-to-reg/imm32/next
    32124 _Primitive-convert-xreg-to-reg:  # (payload primitive)
    32125     0x11/imm32/alloc-id:fake:payload
    32126     # var1/reg <- convert var2/xreg => f3 0f 2d/convert-to-int var2/xm32 var1/r32
    32127     0x11/imm32/alloc-id:fake
    32128     _string-convert/imm32/name
    32129     0x11/imm32/alloc-id:fake
    32130     Single-float-var-in-some-register/imm32/inouts
    32131     0x11/imm32/alloc-id:fake
    32132     Single-int-var-in-some-register/imm32/outputs
    32133     0x11/imm32/alloc-id:fake
    32134     _string_f3_0f_2d_convert_to_int/imm32/subx-name
    32135     0/imm32/no-rm32
    32136     3/imm32/r32-is-first-output
    32137     0/imm32/no-imm32
    32138     0/imm32/no-imm8
    32139     0/imm32/no-disp32
    32140     1/imm32/xm32-is-first-inout
    32141     0/imm32/no-x32
    32142     0x11/imm32/alloc-id:fake
    32143     _Primitive-truncate-xmem-to-reg/imm32/next
    32144 _Primitive-truncate-xmem-to-reg:  # (payload primitive)
    32145     0x11/imm32/alloc-id:fake:payload
    32146     # var1/reg <- truncate var2 => f3 0f 2c/truncate-to-int var2/xm32 var1/r32
    32147     0x11/imm32/alloc-id:fake
    32148     _string-truncate/imm32/name
    32149     0x11/imm32/alloc-id:fake
    32150     Single-float-var-in-mem/imm32/inouts
    32151     0x11/imm32/alloc-id:fake
    32152     Single-int-var-in-some-register/imm32/outputs
    32153     0x11/imm32/alloc-id:fake
    32154     _string_f3_0f_2c_truncate_to_int/imm32/subx-name
    32155     0/imm32/no-rm32
    32156     3/imm32/r32-is-first-output
    32157     0/imm32/no-imm32
    32158     0/imm32/no-imm8
    32159     0/imm32/no-disp32
    32160     1/imm32/xm32-is-first-inout
    32161     0/imm32/no-x32
    32162     0x11/imm32/alloc-id:fake
    32163     _Primitive-truncate-xreg-to-reg/imm32/next
    32164 _Primitive-truncate-xreg-to-reg:  # (payload primitive)
    32165     0x11/imm32/alloc-id:fake:payload
    32166     # var1/reg <- truncate var2/xreg => f3 0f 2c/truncate-to-int var2/xm32 var1/r32
    32167     0x11/imm32/alloc-id:fake
    32168     _string-truncate/imm32/name
    32169     0x11/imm32/alloc-id:fake
    32170     Single-float-var-in-some-register/imm32/inouts
    32171     0x11/imm32/alloc-id:fake
    32172     Single-int-var-in-some-register/imm32/outputs
    32173     0x11/imm32/alloc-id:fake
    32174     _string_f3_0f_2c_truncate_to_int/imm32/subx-name
    32175     0/imm32/no-rm32
    32176     3/imm32/r32-is-first-output
    32177     0/imm32/no-imm32
    32178     0/imm32/no-imm8
    32179     0/imm32/no-disp32
    32180     1/imm32/xm32-is-first-inout
    32181     0/imm32/no-x32
    32182     0x11/imm32/alloc-id:fake
    32183     _Primitive-reinterpret-xmem-as-reg/imm32/next
    32184 # - reinterpret bytes (just for debugging)
    32185 _Primitive-reinterpret-xmem-as-reg:  # (payload primitive)
    32186     0x11/imm32/alloc-id:fake:payload
    32187     # var1/reg <- reinterpret var2 => 8b/-> var2/xm32 var1/r32
    32188     0x11/imm32/alloc-id:fake
    32189     _string-reinterpret/imm32/name
    32190     0x11/imm32/alloc-id:fake
    32191     Single-float-var-in-mem/imm32/inouts
    32192     0x11/imm32/alloc-id:fake
    32193     Single-int-var-in-some-register/imm32/outputs
    32194     0x11/imm32/alloc-id:fake
    32195     _string_8b_->/imm32/subx-name
    32196     0/imm32/no-rm32
    32197     3/imm32/r32-is-first-output
    32198     0/imm32/no-imm32
    32199     0/imm32/no-imm8
    32200     0/imm32/no-disp32
    32201     1/imm32/xm32-is-first-inout
    32202     0/imm32/no-x32
    32203     0x11/imm32/alloc-id:fake
    32204     _Primitive-reinterpret-mem-as-xreg/imm32/next
    32205 _Primitive-reinterpret-mem-as-xreg:  # (payload primitive)
    32206     0x11/imm32/alloc-id:fake:payload
    32207     # var1/xreg <- reinterpret var2 => f3 0f 10/-> var2/rm32 var1/x32
    32208     0x11/imm32/alloc-id:fake
    32209     _string-reinterpret/imm32/name
    32210     0x11/imm32/alloc-id:fake
    32211     Single-int-var-in-mem/imm32/inouts
    32212     0x11/imm32/alloc-id:fake
    32213     Single-float-var-in-some-register/imm32/outputs
    32214     0x11/imm32/alloc-id:fake
    32215     _string_f3_0f_10_copy/imm32/subx-name
    32216     1/imm32/rm32-is-first-inout
    32217     0/imm32/no-r32
    32218     0/imm32/no-imm32
    32219     0/imm32/no-imm8
    32220     0/imm32/no-disp32
    32221     0/imm32/no-xm32
    32222     3/imm32/x32-is-first-output
    32223     0x11/imm32/alloc-id:fake
    32224     _Primitive-copy-xreg-to-xreg/imm32/next
    32225 # - floating-point copy
    32226 _Primitive-copy-xreg-to-xreg:  # (payload primitive)
    32227     0x11/imm32/alloc-id:fake:payload
    32228     # var1/xreg <- copy var2/xreg => f3 0f 11/<- var1/xm32 var2/x32
    32229     0x11/imm32/alloc-id:fake
    32230     _string-copy/imm32/name
    32231     0x11/imm32/alloc-id:fake
    32232     Single-float-var-in-some-register/imm32/inouts
    32233     0x11/imm32/alloc-id:fake
    32234     Single-float-var-in-some-register/imm32/outputs
    32235     0x11/imm32/alloc-id:fake
    32236     _string_f3_0f_11_copy/imm32/subx-name
    32237     0/imm32/no-rm32
    32238     0/imm32/no-r32
    32239     0/imm32/no-imm32
    32240     0/imm32/no-imm8
    32241     0/imm32/no-disp32
    32242     3/imm32/xm32-is-first-output
    32243     1/imm32/x32-is-first-inout
    32244     0x11/imm32/alloc-id:fake
    32245     _Primitive-copy-xreg-to-mem/imm32/next
    32246 _Primitive-copy-xreg-to-mem:  # (payload primitive)
    32247     0x11/imm32/alloc-id:fake:payload
    32248     # copy-to var1 var2/xreg => f3 0f 11/<- var1 var2/x32
    32249     0x11/imm32/alloc-id:fake
    32250     _string-copy-to/imm32/name
    32251     0x11/imm32/alloc-id:fake
    32252     Two-args-float-stack-float-reg/imm32/inouts
    32253     0/imm32/no-outputs
    32254     0/imm32/no-outputs
    32255     0x11/imm32/alloc-id:fake
    32256     _string_f3_0f_11_copy/imm32/subx-name
    32257     0/imm32/no-rm32
    32258     0/imm32/no-r32
    32259     0/imm32/no-imm32
    32260     0/imm32/no-imm8
    32261     0/imm32/no-disp32
    32262     1/imm32/xm32-is-first-inout
    32263     2/imm32/x32-is-second-inout
    32264     0x11/imm32/alloc-id:fake
    32265     _Primitive-copy-mem-to-xreg/imm32/next
    32266 _Primitive-copy-mem-to-xreg:  # (payload primitive)
    32267     0x11/imm32/alloc-id:fake:payload
    32268     # var1/xreg <- copy var2 => f3 0f 10/-> var2/rm32 var1/x32
    32269     0x11/imm32/alloc-id:fake
    32270     _string-copy/imm32/name
    32271     0x11/imm32/alloc-id:fake
    32272     Single-float-var-in-mem/imm32/inouts
    32273     0x11/imm32/alloc-id:fake
    32274     Single-float-var-in-some-register/imm32/outputs
    32275     0x11/imm32/alloc-id:fake
    32276     _string_f3_0f_10_copy/imm32/subx-name
    32277     0/imm32/no-rm32
    32278     0/imm32/no-r32
    32279     0/imm32/no-imm32
    32280     0/imm32/no-imm8
    32281     0/imm32/no-disp32
    32282     1/imm32/xm32-is-first-inout
    32283     3/imm32/x32-is-first-output
    32284     0x11/imm32/alloc-id:fake
    32285     _Primitive-address-of-xmem/imm32/next
    32286 # - floating-point-address
    32287 _Primitive-address-of-xmem:  # (payload primitive)
    32288     0x11/imm32/alloc-id:fake:payload
    32289     # var1/reg <- address var2 => 8d/copy-address var2/rm32 var1/r32
    32290     0x11/imm32/alloc-id:fake
    32291     _string-address/imm32/name
    32292     0x11/imm32/alloc-id:fake
    32293     Single-float-var-in-mem/imm32/inouts
    32294     0x11/imm32/alloc-id:fake
    32295     Single-addr-var-in-some-register/imm32/outputs
    32296     0x11/imm32/alloc-id:fake
    32297     _string_8d_copy_address/imm32/subx-name
    32298     1/imm32/rm32-is-first-inout
    32299     3/imm32/r32-is-first-output
    32300     0/imm32/no-imm32
    32301     0/imm32/no-imm8
    32302     0/imm32/no-disp32
    32303     0/imm32/no-xm32
    32304     0/imm32/no-x32
    32305     0x11/imm32/alloc-id:fake
    32306     _Primitive-add-xreg-to-xreg/imm32/next
    32307 # - floating-point add
    32308 _Primitive-add-xreg-to-xreg:  # (payload primitive)
    32309     0x11/imm32/alloc-id:fake:payload
    32310     # var1/xreg <- add var2/xreg => f3 0f 58/add var1/xm32 var2/x32
    32311     0x11/imm32/alloc-id:fake
    32312     _string-add/imm32/name
    32313     0x11/imm32/alloc-id:fake
    32314     Single-float-var-in-some-register/imm32/inouts
    32315     0x11/imm32/alloc-id:fake
    32316     Single-float-var-in-some-register/imm32/outputs
    32317     0x11/imm32/alloc-id:fake
    32318     _string_f3_0f_58_add/imm32/subx-name
    32319     0/imm32/no-rm32
    32320     0/imm32/no-r32
    32321     0/imm32/no-imm32
    32322     0/imm32/no-imm8
    32323     0/imm32/no-disp32
    32324     1/imm32/xm32-is-first-inout
    32325     3/imm32/x32-is-first-output
    32326     0x11/imm32/alloc-id:fake
    32327     _Primitive-add-mem-to-xreg/imm32/next
    32328 _Primitive-add-mem-to-xreg:  # (payload primitive)
    32329     0x11/imm32/alloc-id:fake:payload
    32330     # var1/xreg <- add var2 => f3 0f 58/add var2/xm32 var1/x32
    32331     0x11/imm32/alloc-id:fake
    32332     _string-add/imm32/name
    32333     0x11/imm32/alloc-id:fake
    32334     Single-float-var-in-mem/imm32/inouts
    32335     0x11/imm32/alloc-id:fake
    32336     Single-float-var-in-some-register/imm32/outputs
    32337     0x11/imm32/alloc-id:fake
    32338     _string_f3_0f_58_add/imm32/subx-name
    32339     0/imm32/no-rm32
    32340     0/imm32/no-r32
    32341     0/imm32/no-imm32
    32342     0/imm32/no-imm8
    32343     0/imm32/no-disp32
    32344     1/imm32/xm32-is-first-inout
    32345     3/imm32/x32-is-first-output
    32346     0x11/imm32/alloc-id:fake
    32347     _Primitive-subtract-xreg-from-xreg/imm32/next
    32348 # - floating-point subtract
    32349 _Primitive-subtract-xreg-from-xreg:  # (payload primitive)
    32350     0x11/imm32/alloc-id:fake:payload
    32351     # var1/xreg <- subtract var2/xreg => f3 0f 5c/subtract var1/xm32 var2/x32
    32352     0x11/imm32/alloc-id:fake
    32353     _string-subtract/imm32/name
    32354     0x11/imm32/alloc-id:fake
    32355     Single-float-var-in-some-register/imm32/inouts
    32356     0x11/imm32/alloc-id:fake
    32357     Single-float-var-in-some-register/imm32/outputs
    32358     0x11/imm32/alloc-id:fake
    32359     _string_f3_0f_5c_subtract/imm32/subx-name
    32360     0/imm32/no-rm32
    32361     0/imm32/no-r32
    32362     0/imm32/no-imm32
    32363     0/imm32/no-imm8
    32364     0/imm32/no-disp32
    32365     1/imm32/xm32-is-first-inout
    32366     3/imm32/x32-is-first-output
    32367     0x11/imm32/alloc-id:fake
    32368     _Primitive-subtract-mem-from-xreg/imm32/next
    32369 _Primitive-subtract-mem-from-xreg:  # (payload primitive)
    32370     0x11/imm32/alloc-id:fake:payload
    32371     # var1/xreg <- subtract var2 => f3 0f 5c/subtract var2/xm32 var1/x32
    32372     0x11/imm32/alloc-id:fake
    32373     _string-subtract/imm32/name
    32374     0x11/imm32/alloc-id:fake
    32375     Single-float-var-in-mem/imm32/inouts
    32376     0x11/imm32/alloc-id:fake
    32377     Single-float-var-in-some-register/imm32/outputs
    32378     0x11/imm32/alloc-id:fake
    32379     _string_f3_0f_5c_subtract/imm32/subx-name
    32380     0/imm32/no-rm32
    32381     0/imm32/no-r32
    32382     0/imm32/no-imm32
    32383     0/imm32/no-imm8
    32384     0/imm32/no-disp32
    32385     1/imm32/xm32-is-first-inout
    32386     3/imm32/x32-is-first-output
    32387     0x11/imm32/alloc-id:fake
    32388     _Primitive-multiply-xreg-by-xreg/imm32/next
    32389 # - floating-point multiply
    32390 _Primitive-multiply-xreg-by-xreg:  # (payload primitive)
    32391     0x11/imm32/alloc-id:fake:payload
    32392     # var1/xreg <- multiply var2 => f3 0f 59/multiply var2/xm32 var1/x32
    32393     0x11/imm32/alloc-id:fake
    32394     _string-multiply/imm32/name
    32395     0x11/imm32/alloc-id:fake
    32396     Single-float-var-in-some-register/imm32/inouts
    32397     0x11/imm32/alloc-id:fake
    32398     Single-float-var-in-some-register/imm32/outputs
    32399     0x11/imm32/alloc-id:fake
    32400     _string_f3_0f_59_multiply/imm32/subx-name
    32401     0/imm32/no-rm32
    32402     0/imm32/no-r32
    32403     0/imm32/no-imm32
    32404     0/imm32/no-imm8
    32405     0/imm32/no-disp32
    32406     1/imm32/xm32-is-first-inout
    32407     3/imm32/x32-is-first-output
    32408     0x11/imm32/alloc-id:fake
    32409     _Primitive-multiply-xreg-by-mem/imm32/next
    32410 _Primitive-multiply-xreg-by-mem:  # (payload primitive)
    32411     0x11/imm32/alloc-id:fake:payload
    32412     # var1/xreg <- multiply var2 => 53 0f 59/multiply var2/xm32 var1/x32
    32413     0x11/imm32/alloc-id:fake
    32414     _string-multiply/imm32/name
    32415     0x11/imm32/alloc-id:fake
    32416     Single-float-var-in-mem/imm32/inouts
    32417     0x11/imm32/alloc-id:fake
    32418     Single-float-var-in-some-register/imm32/outputs
    32419     0x11/imm32/alloc-id:fake
    32420     _string_f3_0f_59_multiply/imm32/subx-name
    32421     0/imm32/no-rm32
    32422     0/imm32/no-r32
    32423     0/imm32/no-imm32
    32424     0/imm32/no-imm8
    32425     0/imm32/no-disp32
    32426     1/imm32/xm32-is-first-inout
    32427     3/imm32/x32-is-first-output
    32428     0x11/imm32/alloc-id:fake
    32429     _Primitive-divide-xreg-by-xreg/imm32/next
    32430 # - floating-point divide
    32431 _Primitive-divide-xreg-by-xreg:  # (payload primitive)
    32432     0x11/imm32/alloc-id:fake:payload
    32433     # var1/xreg <- divide var2 => f3 0f 5e/divide var2/xm32 var1/x32
    32434     0x11/imm32/alloc-id:fake
    32435     _string-divide/imm32/name
    32436     0x11/imm32/alloc-id:fake
    32437     Single-float-var-in-some-register/imm32/inouts
    32438     0x11/imm32/alloc-id:fake
    32439     Single-float-var-in-some-register/imm32/outputs
    32440     0x11/imm32/alloc-id:fake
    32441     _string_f3_0f_5e_divide/imm32/subx-name
    32442     0/imm32/no-rm32
    32443     0/imm32/no-r32
    32444     0/imm32/no-imm32
    32445     0/imm32/no-imm8
    32446     0/imm32/no-disp32
    32447     1/imm32/xm32-is-first-inout
    32448     3/imm32/x32-is-first-output
    32449     0x11/imm32/alloc-id:fake
    32450     _Primitive-divide-xreg-by-mem/imm32/next
    32451 _Primitive-divide-xreg-by-mem:  # (payload primitive)
    32452     0x11/imm32/alloc-id:fake:payload
    32453     # var1/xreg <- divide var2 => f3 0f 5e/divide var2/xm32 var1/x32
    32454     0x11/imm32/alloc-id:fake
    32455     _string-divide/imm32/name
    32456     0x11/imm32/alloc-id:fake
    32457     Single-float-var-in-mem/imm32/inouts
    32458     0x11/imm32/alloc-id:fake
    32459     Single-float-var-in-some-register/imm32/outputs
    32460     0x11/imm32/alloc-id:fake
    32461     _string_f3_0f_5e_divide/imm32/subx-name
    32462     0/imm32/no-rm32
    32463     0/imm32/no-r32
    32464     0/imm32/no-imm32
    32465     0/imm32/no-imm8
    32466     0/imm32/no-disp32
    32467     1/imm32/xm32-is-first-inout
    32468     3/imm32/x32-is-first-output
    32469     0x11/imm32/alloc-id:fake
    32470     _Primitive-max-xreg-with-xreg/imm32/next
    32471 # - floating-point maximum
    32472 _Primitive-max-xreg-with-xreg:  # (payload primitive)
    32473     0x11/imm32/alloc-id:fake:payload
    32474     # var1/xreg <- max var2 => f3 0f 5f/max var2/xm32 var1/x32
    32475     0x11/imm32/alloc-id:fake
    32476     _string-max/imm32/name
    32477     0x11/imm32/alloc-id:fake
    32478     Single-float-var-in-some-register/imm32/inouts
    32479     0x11/imm32/alloc-id:fake
    32480     Single-float-var-in-some-register/imm32/outputs
    32481     0x11/imm32/alloc-id:fake
    32482     _string_f3_0f_5f_max/imm32/subx-name
    32483     0/imm32/no-rm32
    32484     0/imm32/no-r32
    32485     0/imm32/no-imm32
    32486     0/imm32/no-imm8
    32487     0/imm32/no-disp32
    32488     1/imm32/xm32-is-first-inout
    32489     3/imm32/x32-is-first-output
    32490     0x11/imm32/alloc-id:fake
    32491     _Primitive-max-xreg-with-mem/imm32/next
    32492 _Primitive-max-xreg-with-mem:  # (payload primitive)
    32493     0x11/imm32/alloc-id:fake:payload
    32494     # var1/xreg <- divide var2 => f3 0f 5f/max var2/xm32 var1/x32
    32495     0x11/imm32/alloc-id:fake
    32496     _string-max/imm32/name
    32497     0x11/imm32/alloc-id:fake
    32498     Single-float-var-in-mem/imm32/inouts
    32499     0x11/imm32/alloc-id:fake
    32500     Single-float-var-in-some-register/imm32/outputs
    32501     0x11/imm32/alloc-id:fake
    32502     _string_f3_0f_5f_max/imm32/subx-name
    32503     0/imm32/no-rm32
    32504     0/imm32/no-r32
    32505     0/imm32/no-imm32
    32506     0/imm32/no-imm8
    32507     0/imm32/no-disp32
    32508     1/imm32/xm32-is-first-inout
    32509     3/imm32/x32-is-first-output
    32510     0x11/imm32/alloc-id:fake
    32511     _Primitive-min-xreg-with-xreg/imm32/next
    32512 # - floating-point minimum
    32513 _Primitive-min-xreg-with-xreg:  # (payload primitive)
    32514     0x11/imm32/alloc-id:fake:payload
    32515     # var1/xreg <- divide var2 => f3 0f 5d/min var2/xm32 var1/x32
    32516     0x11/imm32/alloc-id:fake
    32517     _string-min/imm32/name
    32518     0x11/imm32/alloc-id:fake
    32519     Single-float-var-in-some-register/imm32/inouts
    32520     0x11/imm32/alloc-id:fake
    32521     Single-float-var-in-some-register/imm32/outputs
    32522     0x11/imm32/alloc-id:fake
    32523     _string_f3_0f_5d_min/imm32/subx-name
    32524     0/imm32/no-rm32
    32525     0/imm32/no-r32
    32526     0/imm32/no-imm32
    32527     0/imm32/no-imm8
    32528     0/imm32/no-disp32
    32529     1/imm32/xm32-is-first-inout
    32530     3/imm32/x32-is-first-output
    32531     0x11/imm32/alloc-id:fake
    32532     _Primitive-min-xreg-with-mem/imm32/next
    32533 _Primitive-min-xreg-with-mem:  # (payload primitive)
    32534     0x11/imm32/alloc-id:fake:payload
    32535     # var1/xreg <- divide var2 => f3 0f 5d/min var2/xm32 var1/x32
    32536     0x11/imm32/alloc-id:fake
    32537     _string-min/imm32/name
    32538     0x11/imm32/alloc-id:fake
    32539     Single-float-var-in-mem/imm32/inouts
    32540     0x11/imm32/alloc-id:fake
    32541     Single-float-var-in-some-register/imm32/outputs
    32542     0x11/imm32/alloc-id:fake
    32543     _string_f3_0f_5d_min/imm32/subx-name
    32544     0/imm32/no-rm32
    32545     0/imm32/no-r32
    32546     0/imm32/no-imm32
    32547     0/imm32/no-imm8
    32548     0/imm32/no-disp32
    32549     1/imm32/xm32-is-first-inout
    32550     3/imm32/x32-is-first-output
    32551     0x11/imm32/alloc-id:fake
    32552     _Primitive-reciprocal-xreg-to-xreg/imm32/next
    32553 # - floating-point reciprocal
    32554 _Primitive-reciprocal-xreg-to-xreg:  # (payload primitive)
    32555     0x11/imm32/alloc-id:fake:payload
    32556     # var1/xreg <- reciprocal var2 => f3 0f 53/reciprocal var2/xm32 var1/x32
    32557     0x11/imm32/alloc-id:fake
    32558     _string-reciprocal/imm32/name
    32559     0x11/imm32/alloc-id:fake
    32560     Single-float-var-in-some-register/imm32/inouts
    32561     0x11/imm32/alloc-id:fake
    32562     Single-float-var-in-some-register/imm32/outputs
    32563     0x11/imm32/alloc-id:fake
    32564     _string_f3_0f_53_reciprocal/imm32/subx-name
    32565     0/imm32/no-rm32
    32566     0/imm32/no-r32
    32567     0/imm32/no-imm32
    32568     0/imm32/no-imm8
    32569     0/imm32/no-disp32
    32570     1/imm32/xm32-is-first-inout
    32571     3/imm32/x32-is-first-output
    32572     0x11/imm32/alloc-id:fake
    32573     _Primitive-reciprocal-mem-to-xreg/imm32/next
    32574 _Primitive-reciprocal-mem-to-xreg:  # (payload primitive)
    32575     0x11/imm32/alloc-id:fake:payload
    32576     # var1/xreg <- divide var2 => f3 0f 53/reciprocal var2/xm32 var1/x32
    32577     0x11/imm32/alloc-id:fake
    32578     _string-reciprocal/imm32/name
    32579     0x11/imm32/alloc-id:fake
    32580     Single-float-var-in-mem/imm32/inouts
    32581     0x11/imm32/alloc-id:fake
    32582     Single-float-var-in-some-register/imm32/outputs
    32583     0x11/imm32/alloc-id:fake
    32584     _string_f3_0f_53_reciprocal/imm32/subx-name
    32585     0/imm32/no-rm32
    32586     0/imm32/no-r32
    32587     0/imm32/no-imm32
    32588     0/imm32/no-imm8
    32589     0/imm32/no-disp32
    32590     1/imm32/xm32-is-first-inout
    32591     3/imm32/x32-is-first-output
    32592     0x11/imm32/alloc-id:fake
    32593     _Primitive-square-root-xreg-to-xreg/imm32/next
    32594 # - floating-point square root
    32595 _Primitive-square-root-xreg-to-xreg:  # (payload primitive)
    32596     0x11/imm32/alloc-id:fake:payload
    32597     # var1/xreg <- square-root var2 => f3 0f 51/square-root var2/xm32 var1/x32
    32598     0x11/imm32/alloc-id:fake
    32599     _string-square-root/imm32/name
    32600     0x11/imm32/alloc-id:fake
    32601     Single-float-var-in-some-register/imm32/inouts
    32602     0x11/imm32/alloc-id:fake
    32603     Single-float-var-in-some-register/imm32/outputs
    32604     0x11/imm32/alloc-id:fake
    32605     _string_f3_0f_51_square_root/imm32/subx-name
    32606     0/imm32/no-rm32
    32607     0/imm32/no-r32
    32608     0/imm32/no-imm32
    32609     0/imm32/no-imm8
    32610     0/imm32/no-disp32
    32611     1/imm32/xm32-is-first-inout
    32612     3/imm32/x32-is-first-output
    32613     0x11/imm32/alloc-id:fake
    32614     _Primitive-square-root-mem-to-xreg/imm32/next
    32615 _Primitive-square-root-mem-to-xreg:  # (payload primitive)
    32616     0x11/imm32/alloc-id:fake:payload
    32617     # var1/xreg <- divide var2 => f3 0f 51/square-root var2/xm32 var1/x32
    32618     0x11/imm32/alloc-id:fake
    32619     _string-square-root/imm32/name
    32620     0x11/imm32/alloc-id:fake
    32621     Single-float-var-in-mem/imm32/inouts
    32622     0x11/imm32/alloc-id:fake
    32623     Single-float-var-in-some-register/imm32/outputs
    32624     0x11/imm32/alloc-id:fake
    32625     _string_f3_0f_51_square_root/imm32/subx-name
    32626     0/imm32/no-rm32
    32627     0/imm32/no-r32
    32628     0/imm32/no-imm32
    32629     0/imm32/no-imm8
    32630     0/imm32/no-disp32
    32631     1/imm32/xm32-is-first-inout
    32632     3/imm32/x32-is-first-output
    32633     0x11/imm32/alloc-id:fake
    32634     _Primitive-inverse-square-root-xreg-to-xreg/imm32/next
    32635 # - floating-point inverse square root 1/sqrt(x)
    32636 _Primitive-inverse-square-root-xreg-to-xreg:  # (payload primitive)
    32637     0x11/imm32/alloc-id:fake:payload
    32638     # var1/xreg <- reciprocal var2 => f3 0f 52/inverse-square-root var2/xm32 var1/x32
    32639     0x11/imm32/alloc-id:fake
    32640     _string-inverse-square-root/imm32/name
    32641     0x11/imm32/alloc-id:fake
    32642     Single-float-var-in-some-register/imm32/inouts
    32643     0x11/imm32/alloc-id:fake
    32644     Single-float-var-in-some-register/imm32/outputs
    32645     0x11/imm32/alloc-id:fake
    32646     _string_f3_0f_52_inverse_square_root/imm32/subx-name
    32647     0/imm32/no-rm32
    32648     0/imm32/no-r32
    32649     0/imm32/no-imm32
    32650     0/imm32/no-imm8
    32651     0/imm32/no-disp32
    32652     1/imm32/xm32-is-first-inout
    32653     3/imm32/x32-is-first-output
    32654     0x11/imm32/alloc-id:fake
    32655     _Primitive-inverse-square-root-mem-to-xreg/imm32/next
    32656 _Primitive-inverse-square-root-mem-to-xreg:  # (payload primitive)
    32657     0x11/imm32/alloc-id:fake:payload
    32658     # var1/xreg <- divide var2 => f3 0f 52/inverse-square-root var2/xm32 var1/x32
    32659     0x11/imm32/alloc-id:fake
    32660     _string-inverse-square-root/imm32/name
    32661     0x11/imm32/alloc-id:fake
    32662     Single-float-var-in-mem/imm32/inouts
    32663     0x11/imm32/alloc-id:fake
    32664     Single-float-var-in-some-register/imm32/outputs
    32665     0x11/imm32/alloc-id:fake
    32666     _string_f3_0f_52_inverse_square_root/imm32/subx-name
    32667     0/imm32/no-rm32
    32668     0/imm32/no-r32
    32669     0/imm32/no-imm32
    32670     0/imm32/no-imm8
    32671     0/imm32/no-disp32
    32672     1/imm32/xm32-is-first-inout
    32673     3/imm32/x32-is-first-output
    32674     0x11/imm32/alloc-id:fake
    32675     _Primitive-compare-xreg-with-xreg/imm32/next
    32676 # - floating-point compare
    32677 _Primitive-compare-xreg-with-xreg:  # (payload primitive)
    32678     0x11/imm32/alloc-id:fake:payload
    32679     # compare var1/reg1 var2/reg2 => 0f 2f/compare var2/x32 var1/xm32
    32680     0x11/imm32/alloc-id:fake
    32681     _string-compare/imm32/name
    32682     0x11/imm32/alloc-id:fake
    32683     Two-float-args-in-regs/imm32/inouts
    32684     0/imm32/no-outputs
    32685     0/imm32/no-outputs
    32686     0x11/imm32/alloc-id:fake
    32687     _string_0f_2f_compare/imm32/subx-name
    32688     0/imm32/no-rm32
    32689     0/imm32/no-r32
    32690     0/imm32/no-imm32
    32691     0/imm32/no-imm8
    32692     0/imm32/no-disp32
    32693     2/imm32/xm32-is-second-inout
    32694     1/imm32/x32-is-first-inout
    32695     0x11/imm32/alloc-id:fake
    32696     _Primitive-compare-xreg-with-mem/imm32/next
    32697 _Primitive-compare-xreg-with-mem:  # (payload primitive)
    32698     0x11/imm32/alloc-id:fake:payload
    32699     # compare var1/xreg var2 => 0f 2f/compare var1/x32 var2/xm32
    32700     0x11/imm32/alloc-id:fake
    32701     _string-compare/imm32/name
    32702     0x11/imm32/alloc-id:fake
    32703     Two-args-float-reg-float-stack/imm32/inouts
    32704     0/imm32/no-outputs
    32705     0/imm32/no-outputs
    32706     0x11/imm32/alloc-id:fake
    32707     _string_0f_2f_compare/imm32/subx-name
    32708     0/imm32/no-rm32
    32709     0/imm32/no-r32
    32710     0/imm32/no-imm32
    32711     0/imm32/no-imm8
    32712     0/imm32/no-disp32
    32713     2/imm32/xm32-is-second-inout
    32714     1/imm32/x32-is-first-inout
    32715     0x11/imm32/alloc-id:fake
    32716     _Primitive-break-if-addr</imm32/next
    32717 # - branches
    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_82_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-addr>=/imm32/next
    32737 _Primitive-break-if-addr>=:  # (payload primitive)
    32738     0x11/imm32/alloc-id:fake:payload
    32739     0x11/imm32/alloc-id:fake
    32740     _string-break-if-addr>=/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_83_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_84_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-!=/imm32/next
    32775 _Primitive-break-if-!=:  # (payload primitive)
    32776     0x11/imm32/alloc-id:fake:payload
    32777     0x11/imm32/alloc-id:fake
    32778     _string-break-if-!=/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_85_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_86_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-addr>/imm32/next
    32813 _Primitive-break-if-addr>:  # (payload primitive)
    32814     0x11/imm32/alloc-id:fake:payload
    32815     0x11/imm32/alloc-id:fake
    32816     _string-break-if-addr>/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_87_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_8c_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_8d_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_8e_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->/imm32/next
    32889 _Primitive-break-if->:  # (payload primitive)
    32890     0x11/imm32/alloc-id:fake:payload
    32891     0x11/imm32/alloc-id:fake
    32892     _string-break-if->/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_8f_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-carry/imm32/next
    32908 _Primitive-break-if-carry:  # (payload primitive)
    32909     0x11/imm32/alloc-id:fake:payload
    32910     0x11/imm32/alloc-id:fake
    32911     _string-break-if-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_82_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-not-carry/imm32/next
    32927 _Primitive-break-if-not-carry:  # (payload primitive)
    32928     0x11/imm32/alloc-id:fake:payload
    32929     0x11/imm32/alloc-id:fake
    32930     _string-break-if-not-carry/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_83_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-overflow/imm32/next
    32946 _Primitive-break-if-overflow:  # (payload primitive)
    32947     0x11/imm32/alloc-id:fake:payload
    32948     0x11/imm32/alloc-id:fake
    32949     _string-break-if-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_80_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-if-not-overflow/imm32/next
    32965 _Primitive-break-if-not-overflow:  # (payload primitive)
    32966     0x11/imm32/alloc-id:fake:payload
    32967     0x11/imm32/alloc-id:fake
    32968     _string-break-if-not-overflow/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_0f_81_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-break/imm32/next
    32984 _Primitive-break:  # (payload primitive)
    32985     0x11/imm32/alloc-id:fake:payload
    32986     0x11/imm32/alloc-id:fake
    32987     _string-break/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_e9_jump_break/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_82_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-addr>=/imm32/next
    33022 _Primitive-loop-if-addr>=:  # (payload primitive)
    33023     0x11/imm32/alloc-id:fake:payload
    33024     0x11/imm32/alloc-id:fake
    33025     _string-loop-if-addr>=/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_83_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_84_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-!=/imm32/next
    33060 _Primitive-loop-if-!=:  # (payload primitive)
    33061     0x11/imm32/alloc-id:fake:payload
    33062     0x11/imm32/alloc-id:fake
    33063     _string-loop-if-!=/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_85_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_86_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-addr>/imm32/next
    33098 _Primitive-loop-if-addr>:  # (payload primitive)
    33099     0x11/imm32/alloc-id:fake:payload
    33100     0x11/imm32/alloc-id:fake
    33101     _string-loop-if-addr>/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_87_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_8c_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_8d_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_8e_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->/imm32/next
    33174 _Primitive-loop-if->:  # (payload primitive)
    33175     0x11/imm32/alloc-id:fake:payload
    33176     0x11/imm32/alloc-id:fake
    33177     _string-loop-if->/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_8f_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-carry/imm32/next
    33193 _Primitive-loop-if-carry:  # (payload primitive)
    33194     0x11/imm32/alloc-id:fake:payload
    33195     0x11/imm32/alloc-id:fake
    33196     _string-loop-if-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_82_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-not-carry/imm32/next
    33212 _Primitive-loop-if-not-carry:  # (payload primitive)
    33213     0x11/imm32/alloc-id:fake:payload
    33214     0x11/imm32/alloc-id:fake
    33215     _string-loop-if-not-carry/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_83_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-overflow/imm32/next
    33231 _Primitive-loop-if-overflow:  # (payload primitive)
    33232     0x11/imm32/alloc-id:fake:payload
    33233     0x11/imm32/alloc-id:fake
    33234     _string-loop-if-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_80_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-if-not-overflow/imm32/next
    33250 _Primitive-loop-if-not-overflow:  # (payload primitive)
    33251     0x11/imm32/alloc-id:fake:payload
    33252     0x11/imm32/alloc-id:fake
    33253     _string-loop-if-not-overflow/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_0f_81_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-loop/imm32/next  # we probably don't need an unconditional break
    33269 _Primitive-loop:  # (payload primitive)
    33270     0x11/imm32/alloc-id:fake:payload
    33271     0x11/imm32/alloc-id:fake
    33272     _string-loop/imm32/name
    33273     0/imm32/no-inouts
    33274     0/imm32/no-inouts
    33275     0/imm32/no-outputs
    33276     0/imm32/no-outputs
    33277     0x11/imm32/alloc-id:fake
    33278     _string_e9_jump_loop/imm32/subx-name
    33279     0/imm32/no-rm32
    33280     0/imm32/no-r32
    33281     0/imm32/no-imm32
    33282     0/imm32/no-imm8
    33283     0/imm32/no-disp32
    33284     0/imm32/no-xm32
    33285     0/imm32/no-x32
    33286     0x11/imm32/alloc-id:fake
    33287     _Primitive-break-if-addr<-named/imm32/next
    33288 # - branches to named blocks
    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_82_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-addr>=-named/imm32/next
    33308 _Primitive-break-if-addr>=-named:  # (payload primitive)
    33309     0x11/imm32/alloc-id:fake:payload
    33310     0x11/imm32/alloc-id:fake
    33311     _string-break-if-addr>=/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_83_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_84_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-!=-named/imm32/next
    33346 _Primitive-break-if-!=-named:  # (payload primitive)
    33347     0x11/imm32/alloc-id:fake:payload
    33348     0x11/imm32/alloc-id:fake
    33349     _string-break-if-!=/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_85_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_86_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-addr>-named/imm32/next
    33384 _Primitive-break-if-addr>-named:  # (payload primitive)
    33385     0x11/imm32/alloc-id:fake:payload
    33386     0x11/imm32/alloc-id:fake
    33387     _string-break-if-addr>/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_87_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_8c_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_8d_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_8e_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-if->-named/imm32/next
    33460 _Primitive-break-if->-named:  # (payload primitive)
    33461     0x11/imm32/alloc-id:fake:payload
    33462     0x11/imm32/alloc-id:fake
    33463     _string-break-if->/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_0f_8f_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-break-named/imm32/next
    33479 _Primitive-break-named:  # (payload primitive)
    33480     0x11/imm32/alloc-id:fake:payload
    33481     0x11/imm32/alloc-id:fake
    33482     _string-break/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_e9_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_82_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-addr>=-named/imm32/next
    33517 _Primitive-loop-if-addr>=-named:  # (payload primitive)
    33518     0x11/imm32/alloc-id:fake:payload
    33519     0x11/imm32/alloc-id:fake
    33520     _string-loop-if-addr>=/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_83_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_84_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-!=-named/imm32/next
    33555 _Primitive-loop-if-!=-named:  # (payload primitive)
    33556     0x11/imm32/alloc-id:fake:payload
    33557     0x11/imm32/alloc-id:fake
    33558     _string-loop-if-!=/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_85_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_86_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-addr>-named/imm32/next
    33593 _Primitive-loop-if-addr>-named:  # (payload primitive)
    33594     0x11/imm32/alloc-id:fake:payload
    33595     0x11/imm32/alloc-id:fake
    33596     _string-loop-if-addr>/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_87_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_8c_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_8d_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_8e_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-if->-named/imm32/next
    33669 _Primitive-loop-if->-named:  # (payload primitive)
    33670     0x11/imm32/alloc-id:fake:payload
    33671     0x11/imm32/alloc-id:fake
    33672     _string-loop-if->/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_0f_8f_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-loop-named/imm32/next  # we probably don't need an unconditional break
    33688 _Primitive-loop-named:  # (payload primitive)
    33689     0x11/imm32/alloc-id:fake:payload
    33690     0x11/imm32/alloc-id:fake
    33691     _string-loop/imm32/name
    33692     0x11/imm32/alloc-id:fake
    33693     Single-lit-var/imm32/inouts
    33694     0/imm32/no-outputs
    33695     0/imm32/no-outputs
    33696     0x11/imm32/alloc-id:fake
    33697     _string_e9_jump_label/imm32/subx-name
    33698     0/imm32/no-rm32
    33699     0/imm32/no-r32
    33700     0/imm32/no-imm32
    33701     0/imm32/no-imm8
    33702     1/imm32/disp32-is-first-inout
    33703     0/imm32/no-xm32
    33704     0/imm32/no-x32
    33705     0x11/imm32/alloc-id:fake
    33706     _Primitive-break-if-float</imm32/next
    33707 # - branches based on floating-point comparisons
    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_82_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_83_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_86_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-break-if-float>/imm32/next
    33765 _Primitive-break-if-float>:  # (payload primitive)
    33766     0x11/imm32/alloc-id:fake:payload
    33767     0x11/imm32/alloc-id:fake
    33768     _string-break-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_87_jump_break/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_82_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_83_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_86_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-loop-if-float>/imm32/next
    33841 _Primitive-loop-if-float>:  # (payload primitive)
    33842     0x11/imm32/alloc-id:fake:payload
    33843     0x11/imm32/alloc-id:fake
    33844     _string-loop-if-float>/imm32/name
    33845     0/imm32/no-inouts
    33846     0/imm32/no-inouts
    33847     0/imm32/no-outputs
    33848     0/imm32/no-outputs
    33849     0x11/imm32/alloc-id:fake
    33850     _string_0f_87_jump_loop/imm32/subx-name
    33851     0/imm32/no-rm32
    33852     0/imm32/no-r32
    33853     0/imm32/no-imm32
    33854     0/imm32/no-imm8
    33855     0/imm32/no-disp32
    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_82_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_83_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_86_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-break-if-float>-named/imm32/next
    33917 _Primitive-break-if-float>-named:  # (payload primitive)
    33918     0x11/imm32/alloc-id:fake:payload
    33919     0x11/imm32/alloc-id:fake
    33920     _string-break-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_87_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_82_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_83_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_86_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     0x11/imm32/alloc-id:fake
    33992     _Primitive-loop-if-float>-named/imm32/next
    33993 _Primitive-loop-if-float>-named:  # (payload primitive)
    33994     0x11/imm32/alloc-id:fake:payload
    33995     0x11/imm32/alloc-id:fake
    33996     _string-loop-if-float>/imm32/name
    33997     0x11/imm32/alloc-id:fake
    33998     Single-lit-var/imm32/inouts
    33999     0/imm32/no-outputs
    34000     0/imm32/no-outputs
    34001     0x11/imm32/alloc-id:fake
    34002     _string_0f_87_jump_label/imm32/subx-name
    34003     0/imm32/no-rm32
    34004     0/imm32/no-r32
    34005     0/imm32/no-imm32
    34006     0/imm32/no-imm8
    34007     1/imm32/disp32-is-first-inout
    34008     0/imm32/no-xm32
    34009     0/imm32/no-x32
    34010     0/imm32/next
    34011     0/imm32/next
    34012
    34013 # string literals for Mu instructions
    34014 _string-add:  # (payload array byte)
    34015     0x11/imm32/alloc-id:fake:payload
    34016     # "add"
    34017     0x3/imm32/size
    34018     0x61/a 0x64/d 0x64/d
    34019 _string-address:  # (payload array byte)
    34020     0x11/imm32/alloc-id:fake:payload
    34021     # "address"
    34022     0x7/imm32/size
    34023     0x61/a 0x64/d 0x64/d 0x72/r 0x65/e 0x73/s 0x73/s
    34024 _string-add-to:  # (payload array byte)
    34025     0x11/imm32/alloc-id:fake:payload
    34026     # "add-to"
    34027     0x6/imm32/size
    34028     0x61/a 0x64/d 0x64/d 0x2d/dash 0x74/t 0x6f/o
    34029 _string-and:  # (payload array byte)
    34030     0x11/imm32/alloc-id:fake:payload
    34031     # "and"
    34032     0x3/imm32/size
    34033     0x61/a 0x6e/n 0x64/d
    34034 _string-and-with:  # (payload array byte)
    34035     0x11/imm32/alloc-id:fake:payload
    34036     # "and-with"
    34037     0x8/imm32/size
    34038     0x61/a 0x6e/n 0x64/d 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h
    34039 _string-break:  # (payload array byte)
    34040     0x11/imm32/alloc-id:fake:payload
    34041     # "break"
    34042     0x5/imm32/size
    34043     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k
    34044 _string-break-if-<:  # (payload array byte)
    34045     0x11/imm32/alloc-id:fake:payload
    34046     # "break-if-<"
    34047     0xa/imm32/size
    34048     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3c/<
    34049 _string-break-if-<=:  # (payload array byte)
    34050     0x11/imm32/alloc-id:fake:payload
    34051     # "break-if-<="
    34052     0xb/imm32/size
    34053     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3c/< 0x3d/=
    34054 _string-break-if-=:  # (payload array byte)
    34055     0x11/imm32/alloc-id:fake:payload
    34056     # "break-if-="
    34057     0xa/imm32/size
    34058     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3d/=
    34059 _string-break-if->:  # (payload array byte)
    34060     0x11/imm32/alloc-id:fake:payload
    34061     # "break-if->"
    34062     0xa/imm32/size
    34063     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3e/>
    34064 _string-break-if->=:  # (payload array byte)
    34065     0x11/imm32/alloc-id:fake:payload
    34066     # "break-if->="
    34067     0xb/imm32/size
    34068     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3e/> 0x3d/=
    34069 _string-break-if-!=:  # (payload array byte)
    34070     0x11/imm32/alloc-id:fake:payload
    34071     # "break-if-!="
    34072     0xb/imm32/size
    34073     0x62/b 0x72/r 0x65/e 0x61/a 0x6b/k 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x21/! 0x3d/=
    34074 _string-break-if-addr<:  # (payload array byte)
    34075     0x11/imm32/alloc-id:fake:payload
    34076     # "break-if-addr<"
    34077     0xe/imm32/size
    34078     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/<
    34079 _string-break-if-addr<=:  # (payload array byte)
    34080     0x11/imm32/alloc-id:fake:payload
    34081     # "break-if-addr<="
    34082     0xf/imm32/size
    34083     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/=
    34084 _string-break-if-addr>:  # (payload array byte)
    34085     0x11/imm32/alloc-id:fake:payload
    34086     # "break-if-addr>"
    34087     0xe/imm32/size
    34088     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/>
    34089 _string-break-if-addr>=:  # (payload array byte)
    34090     0x11/imm32/alloc-id:fake:payload
    34091     # "break-if-addr>="
    34092     0xf/imm32/size
    34093     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/=
    34094 _string-break-if-float<:  # (payload array byte)
    34095     0x11/imm32/alloc-id:fake:payload
    34096     # "break-if-float<"
    34097     0xf/imm32/size
    34098     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/<
    34099 _string-break-if-float<=:  # (payload array byte)
    34100     0x11/imm32/alloc-id:fake:payload
    34101     # "break-if-float<="
    34102     0x10/imm32/size
    34103     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/=
    34104 _string-break-if-float>:  # (payload array byte)
    34105     0x11/imm32/alloc-id:fake:payload
    34106     # "break-if-float>"
    34107     0xf/imm32/size
    34108     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/>
    34109 _string-break-if-float>=:  # (payload array byte)
    34110     0x11/imm32/alloc-id:fake:payload
    34111     # "break-if-float>="
    34112     0x10/imm32/size
    34113     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/=
    34114 _string-break-if-carry:  # (payload array byte)
    34115     0x11/imm32/alloc-id:fake:payload
    34116     # "break-if-carry"
    34117     0xe/imm32/size
    34118     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
    34119 _string-break-if-not-carry:  # (payload array byte)
    34120     0x11/imm32/alloc-id:fake:payload
    34121     # "break-if-not-carry"
    34122     0x12/imm32/size
    34123     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
    34124 _string-break-if-overflow:  # (payload array byte)
    34125     0x11/imm32/alloc-id:fake:payload
    34126     # "break-if-overflow"
    34127     0x11/imm32/size
    34128     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
    34129 _string-break-if-not-overflow:  # (payload array byte)
    34130     0x11/imm32/alloc-id:fake:payload
    34131     # "break-if-not-overflow"
    34132     0x15/imm32/size
    34133     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
    34134 _string-compare:  # (payload array byte)
    34135     0x11/imm32/alloc-id:fake:payload
    34136     # "compare"
    34137     0x7/imm32/size
    34138     0x63/c 0x6f/o 0x6d/m 0x70/p 0x61/a 0x72/r 0x65/e
    34139 _string-copy:  # (payload array byte)
    34140     0x11/imm32/alloc-id:fake:payload
    34141     # "copy"
    34142     0x4/imm32/size
    34143     0x63/c 0x6f/o 0x70/p 0x79/y
    34144 _string-copy-to:  # (payload array byte)
    34145     0x11/imm32/alloc-id:fake:payload
    34146     # "copy-to"
    34147     0x7/imm32/size
    34148     0x63/c 0x6f/o 0x70/p 0x79/y 0x2d/dash 0x74/t 0x6f/o
    34149 _string-copy-byte:
    34150     0x11/imm32/alloc-id:fake:payload
    34151     # "copy-byte"
    34152     0x9/imm32/size
    34153     0x63/c 0x6f/o 0x70/p 0x79/y 0x2d/dash 0x62/b 0x79/y 0x74/t 0x65/e
    34154 _string-copy-byte-to:
    34155     0x11/imm32/alloc-id:fake:payload
    34156     # "copy-byte-to"
    34157     0xc/imm32/size
    34158     0x63/c 0x6f/o 0x70/p 0x79/y 0x2d/dash 0x62/b 0x79/y 0x74/t 0x65/e 0x2d/dash 0x74/t 0x6f/o
    34159 _string-decrement:  # (payload array byte)
    34160     0x11/imm32/alloc-id:fake:payload
    34161     # "decrement"
    34162     0x9/imm32/size
    34163     0x64/d 0x65/e 0x63/c 0x72/r 0x65/e 0x6d/m 0x65/e 0x6e/n 0x74/t
    34164 _string-increment:  # (payload array byte)
    34165     0x11/imm32/alloc-id:fake:payload
    34166     # "increment"
    34167     0x9/imm32/size
    34168     0x69/i 0x6e/n 0x63/c 0x72/r 0x65/e 0x6d/m 0x65/e 0x6e/n 0x74/t
    34169 _string-loop:  # (payload array byte)
    34170     0x11/imm32/alloc-id:fake:payload
    34171     # "loop"
    34172     0x4/imm32/size
    34173     0x6c/l 0x6f/o 0x6f/o 0x70/p
    34174 _string-loop-if-<:  # (payload array byte)
    34175     0x11/imm32/alloc-id:fake:payload
    34176     # "loop-if-<"
    34177     0x9/imm32/size
    34178     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3c/<
    34179 _string-loop-if-<=:  # (payload array byte)
    34180     0x11/imm32/alloc-id:fake:payload
    34181     # "loop-if-<="
    34182     0xa/imm32/size
    34183     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3c/< 0x3d/=
    34184 _string-loop-if-=:  # (payload array byte)
    34185     0x11/imm32/alloc-id:fake:payload
    34186     # "loop-if-="
    34187     0x9/imm32/size
    34188     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3d/=
    34189 _string-loop-if->:  # (payload array byte)
    34190     0x11/imm32/alloc-id:fake:payload
    34191     # "loop-if->"
    34192     0x9/imm32/size
    34193     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3e/>
    34194 _string-loop-if->=:  # (payload array byte)
    34195     0x11/imm32/alloc-id:fake:payload
    34196     # "loop-if->="
    34197     0xa/imm32/size
    34198     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x3e/> 0x3d/=
    34199 _string-loop-if-!=:  # (payload array byte)
    34200     0x11/imm32/alloc-id:fake:payload
    34201     # "loop-if-!="
    34202     0xa/imm32/size
    34203     0x6c/l 0x6f/o 0x6f/o 0x70/p 0x2d/dash 0x69/i 0x66/f 0x2d/dash 0x21/! 0x3d/=
    34204 _string-loop-if-addr<:  # (payload array byte)
    34205     0x11/imm32/alloc-id:fake:payload
    34206     # "loop-if-addr<"
    34207     0xd/imm32/size
    34208     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/<
    34209 _string-loop-if-addr<=:  # (payload array byte)
    34210     0x11/imm32/alloc-id:fake:payload
    34211     # "loop-if-addr<="
    34212     0xe/imm32/size
    34213     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/=
    34214 _string-loop-if-addr>:  # (payload array byte)
    34215     0x11/imm32/alloc-id:fake:payload
    34216     # "loop-if-addr>"
    34217     0xd/imm32/size
    34218     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/>
    34219 _string-loop-if-addr>=:  # (payload array byte)
    34220     0x11/imm32/alloc-id:fake:payload
    34221     # "loop-if-addr>="
    34222     0xe/imm32/size
    34223     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/=
    34224 _string-loop-if-float<:  # (payload array byte)
    34225     0x11/imm32/alloc-id:fake:payload
    34226     # "loop-if-float<"
    34227     0xe/imm32/size
    34228     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/<
    34229 _string-loop-if-float<=:  # (payload array byte)
    34230     0x11/imm32/alloc-id:fake:payload
    34231     # "loop-if-float<="
    34232     0xf/imm32/size
    34233     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/=
    34234 _string-loop-if-float>:  # (payload array byte)
    34235     0x11/imm32/alloc-id:fake:payload
    34236     # "loop-if-float>"
    34237     0xe/imm32/size
    34238     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/>
    34239 _string-loop-if-float>=:  # (payload array byte)
    34240     0x11/imm32/alloc-id:fake:payload
    34241     # "loop-if-float>="
    34242     0xf/imm32/size
    34243     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/=
    34244 _string-loop-if-carry:  # (payload array byte)
    34245     0x11/imm32/alloc-id:fake:payload
    34246     # "loop-if-carry"
    34247     0xd/imm32/size
    34248     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
    34249 _string-loop-if-not-carry:  # (payload array byte)
    34250     0x11/imm32/alloc-id:fake:payload
    34251     # "loop-if-not-carry"
    34252     0x11/imm32/size
    34253     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
    34254 _string-loop-if-overflow:  # (payload array byte)
    34255     0x11/imm32/alloc-id:fake:payload
    34256     # "loop-if-overflow"
    34257     0x10/imm32/size
    34258     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
    34259 _string-loop-if-not-overflow:  # (payload array byte)
    34260     0x11/imm32/alloc-id:fake:payload
    34261     # "loop-if-not-overflow"
    34262     0x14/imm32/size
    34263     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
    34264 _string-multiply:  # (payload array byte)
    34265     0x11/imm32/alloc-id:fake:payload
    34266     # "multiply"
    34267     0x8/imm32/size
    34268     0x6d/m 0x75/u 0x6c/l 0x74/t 0x69/i 0x70/p 0x6c/l 0x79/y
    34269 _string-convert:  # (payload array byte)
    34270     0x11/imm32/alloc-id:fake:payload
    34271     # "convert"
    34272     0x7/imm32/size
    34273     0x63/c 0x6f/o 0x6e/n 0x76/v 0x65/e 0x72/r 0x74/t
    34274 _string-truncate:  # (payload array byte)
    34275     0x11/imm32/alloc-id:fake:payload
    34276     # "truncate"
    34277     0x8/imm32/size
    34278     0x74/t 0x72/r 0x75/u 0x6e/n 0x63/c 0x61/a 0x74/t 0x65/e
    34279 _string-reinterpret:  # (payload array byte)
    34280     0x11/imm32/alloc-id:fake:payload
    34281     # "reinterpret"
    34282     0xb/imm32/size
    34283     0x72/r 0x65/e 0x69/i 0x6e/n 0x74/t 0x65/e 0x72/r 0x70/p 0x72/r 0x65/e 0x74/t
    34284 _string-divide:
    34285     0x11/imm32/alloc-id:fake:payload
    34286     # "divide"
    34287     0x6/imm32/size
    34288     0x64/d 0x69/i 0x76/v 0x69/i 0x64/d 0x65/e
    34289 _string-max:
    34290     0x11/imm32/alloc-id:fake:payload
    34291     # "max"
    34292     0x3/imm32/size
    34293     0x6d/m 0x61/a 0x78/x
    34294 _string-min:
    34295     0x11/imm32/alloc-id:fake:payload
    34296     # "min"
    34297     0x3/imm32/size
    34298     0x6d/m 0x69/i 0x6e/n
    34299 _string-reciprocal:
    34300     0x11/imm32/alloc-id:fake:payload
    34301     # "reciprocal"
    34302     0xa/imm32/size
    34303     0x72/r 0x65/e 0x63/c 0x69/i 0x70/p 0x72/r 0x6f/o 0x63/c 0x61/a 0x6c/l
    34304 _string-square-root:
    34305     0x11/imm32/alloc-id:fake:payload
    34306     # "square-root"
    34307     0xb/imm32/size
    34308     0x73/s 0x71/q 0x75/u 0x61/a 0x72/r 0x65/e 0x2d/dash 0x72/r 0x6f/o 0x6f/o 0x74/t
    34309 _string-inverse-square-root:
    34310     0x11/imm32/alloc-id:fake:payload
    34311     # "inverse-square-root"
    34312     0x13/imm32/size
    34313     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
    34314 _string-negate:  # (payload array byte)
    34315     0x11/imm32/alloc-id:fake:payload
    34316     # "negate"
    34317     0x6/imm32/size
    34318     0x6e/n 0x65/e 0x67/g 0x61/a 0x74/t 0x65/e
    34319 _string-not:  # (payload array byte)
    34320     0x11/imm32/alloc-id:fake:payload
    34321     # "not"
    34322     0x3/imm32/size
    34323     0x6e/n 0x6f/o 0x74/t
    34324 _string-or:  # (payload array byte)
    34325     0x11/imm32/alloc-id:fake:payload
    34326     # "or"
    34327     0x2/imm32/size
    34328     0x6f/o 0x72/r
    34329 _string-or-with:  # (payload array byte)
    34330     0x11/imm32/alloc-id:fake:payload
    34331     # "or-with"
    34332     0x7/imm32/size
    34333     0x6f/o 0x72/r 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h
    34334 _string-subtract:  # (payload array byte)
    34335     0x11/imm32/alloc-id:fake:payload
    34336     # "subtract"
    34337     0x8/imm32/size
    34338     0x73/s 0x75/u 0x62/b 0x74/t 0x72/r 0x61/a 0x63/c 0x74/t
    34339 _string-subtract-from:  # (payload array byte)
    34340     0x11/imm32/alloc-id:fake:payload
    34341     # "subtract-from"
    34342     0xd/imm32/size
    34343     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
    34344 _string-xor:  # (payload array byte)
    34345     0x11/imm32/alloc-id:fake:payload
    34346     # "xor"
    34347     0x3/imm32/size
    34348     0x78/x 0x6f/o 0x72/r
    34349 _string-xor-with:  # (payload array byte)
    34350     0x11/imm32/alloc-id:fake:payload
    34351     # "xor-with"
    34352     0x8/imm32/size
    34353     0x78/x 0x6f/o 0x72/r 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h
    34354 _string-shift-left:  # (payload array byte)
    34355     0x11/imm32/alloc-id:fake:payload
    34356     # "shift-left"
    34357     0xa/imm32/size
    34358     0x73/s 0x68/h 0x69/i 0x66/f 0x74/t 0x2d/dash 0x6c/l 0x65/e 0x66/f 0x74/t
    34359 _string-shift-right:  # (payload array byte)
    34360     0x11/imm32/alloc-id:fake:payload
    34361     # "shift-right"
    34362     0xb/imm32/size
    34363     0x73/s 0x68/h 0x69/i 0x66/f 0x74/t 0x2d/dash 0x72/r 0x69/i 0x67/g 0x68/h 0x74/t
    34364 _string-shift-right-signed:  # (payload array byte)
    34365     0x11/imm32/alloc-id:fake:payload
    34366     # "shift-right-signed"
    34367     0x12/imm32/size
    34368     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
    34369
    34370 # string literals for SubX instructions
    34371 _string_01_add_to:  # (payload array byte)
    34372     0x11/imm32/alloc-id:fake:payload
    34373     # "01/add-to"
    34374     0x9/imm32/size
    34375     0x30/0 0x31/1 0x2f/slash 0x61/a 0x64/d 0x64/d 0x2d/dash 0x74/t 0x6f/o
    34376 _string_03_add:  # (payload array byte)
    34377     0x11/imm32/alloc-id:fake:payload
    34378     # "03/add"
    34379     0x6/imm32/size
    34380     0x30/0 0x33/3 0x2f/slash 0x61/a 0x64/d 0x64/d
    34381 _string_05_add_to_eax:  # (payload array byte)
    34382     0x11/imm32/alloc-id:fake:payload
    34383     # "05/add-to-eax"
    34384     0xd/imm32/size
    34385     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
    34386 _string_09_or_with:  # (payload array byte)
    34387     0x11/imm32/alloc-id:fake:payload
    34388     # "09/or-with"
    34389     0xa/imm32/size
    34390     0x30/0 0x39/9 0x2f/slash 0x6f/o 0x72/r 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h
    34391 _string_0b_or:  # (payload array byte)
    34392     0x11/imm32/alloc-id:fake:payload
    34393     # "0b/or"
    34394     0x5/imm32/size
    34395     0x30/0 0x62/b 0x2f/slash 0x6f/o 0x72/r
    34396 _string_0d_or_with_eax:  # (payload array byte)
    34397     0x11/imm32/alloc-id:fake:payload
    34398     # "0d/or-with-eax"
    34399     0xe/imm32/size
    34400     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
    34401 _string_0f_80_jump_label:  # (payload array byte)
    34402     0x11/imm32/alloc-id:fake:payload
    34403     # "0f 80/jump-if-overflow"
    34404     0x16/imm32/size
    34405     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
    34406 _string_0f_80_jump_break:  # (payload array byte)
    34407     0x11/imm32/alloc-id:fake:payload
    34408     # "0f 80/jump-if-overflow break/disp32"
    34409     0x23/imm32/size
    34410     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
    34411 _string_0f_80_jump_loop:  # (payload array byte)
    34412     0x11/imm32/alloc-id:fake:payload
    34413     # "0f 80/jump-if-overflow loop/disp32"
    34414     0x22/imm32/size
    34415     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
    34416 _string_0f_81_jump_label:  # (payload array byte)
    34417     0x11/imm32/alloc-id:fake:payload
    34418     # "0f 81/jump-if-not-overflow"
    34419     0x1a/imm32/size
    34420     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
    34421 _string_0f_81_jump_break:  # (payload array byte)
    34422     0x11/imm32/alloc-id:fake:payload
    34423     # "0f 81/jump-if-not-overflow break/disp32"
    34424     0x27/imm32/size
    34425     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
    34426 _string_0f_81_jump_loop:  # (payload array byte)
    34427     0x11/imm32/alloc-id:fake:payload
    34428     # "0f 81/jump-if-not-overflow loop/disp32"
    34429     0x26/imm32/size
    34430     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
    34431 _string_0f_82_jump_label:  # (payload array byte)
    34432     0x11/imm32/alloc-id:fake:payload
    34433     # "0f 82/jump-if-addr<"
    34434     0x13/imm32/size
    34435     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/<
    34436 _string_0f_82_jump_break:  # (payload array byte)
    34437     0x11/imm32/alloc-id:fake:payload
    34438     # "0f 82/jump-if-addr< break/disp32"
    34439     0x20/imm32/size
    34440     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
    34441 _string_0f_82_jump_loop:  # (payload array byte)
    34442     0x11/imm32/alloc-id:fake:payload
    34443     # "0f 82/jump-if-addr< loop/disp32"
    34444     0x1f/imm32/size
    34445     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
    34446 _string_0f_83_jump_label:  # (payload array byte)
    34447     0x11/imm32/alloc-id:fake:payload
    34448     # "0f 83/jump-if-addr>="
    34449     0x14/imm32/size
    34450     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/=
    34451 _string_0f_83_jump_break:  # (payload array byte)
    34452     0x11/imm32/alloc-id:fake:payload
    34453     # "0f 83/jump-if-addr>= break/disp32"
    34454     0x21/imm32/size
    34455     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
    34456 _string_0f_83_jump_loop:  # (payload array byte)
    34457     0x11/imm32/alloc-id:fake:payload
    34458     # "0f 83/jump-if-addr>= loop/disp32"
    34459     0x20/imm32/size
    34460     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
    34461 _string_0f_84_jump_label:  # (payload array byte)
    34462     0x11/imm32/alloc-id:fake:payload
    34463     # "0f 84/jump-if-="
    34464     0xf/imm32/size
    34465     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/=
    34466 _string_0f_84_jump_break:  # (payload array byte)
    34467     0x11/imm32/alloc-id:fake:payload
    34468     # "0f 84/jump-if-= break/disp32"
    34469     0x1c/imm32/size
    34470     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
    34471 _string_0f_84_jump_loop:  # (payload array byte)
    34472     0x11/imm32/alloc-id:fake:payload
    34473     # "0f 84/jump-if-= loop/disp32"
    34474     0x1a/imm32/size
    34475     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
    34476 _string_0f_85_jump_label:  # (payload array byte)
    34477     0x11/imm32/alloc-id:fake:payload
    34478     # "0f 85/jump-if-!="
    34479     0x10/imm32/size
    34480     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/=
    34481 _string_0f_85_jump_break:  # (payload array byte)
    34482     0x11/imm32/alloc-id:fake:payload
    34483     # "0f 85/jump-if-!= break/disp32"
    34484     0x1d/imm32/size
    34485     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
    34486 _string_0f_85_jump_loop:  # (payload array byte)
    34487     0x11/imm32/alloc-id:fake:payload
    34488     # "0f 85/jump-if-!= loop/disp32"
    34489     0x1c/imm32/size
    34490     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
    34491 _string_0f_86_jump_label:  # (payload array byte)
    34492     0x11/imm32/alloc-id:fake:payload
    34493     # "0f 86/jump-if-addr<="
    34494     0x14/imm32/size
    34495     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/=
    34496 _string_0f_86_jump_break:  # (payload array byte)
    34497     0x11/imm32/alloc-id:fake:payload
    34498     # "0f 86/jump-if-addr<= break/disp32"
    34499     0x21/imm32/size
    34500     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
    34501 _string_0f_86_jump_loop:  # (payload array byte)
    34502     0x11/imm32/alloc-id:fake:payload
    34503     # "0f 86/jump-if-addr<= loop/disp32"
    34504     0x20/imm32/size
    34505     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
    34506 _string_0f_87_jump_label:  # (payload array byte)
    34507     0x11/imm32/alloc-id:fake:payload
    34508     # "0f 87/jump-if-addr>"
    34509     0x13/imm32/size
    34510     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/>
    34511 _string_0f_87_jump_break:  # (payload array byte)
    34512     0x11/imm32/alloc-id:fake:payload
    34513     # "0f 87/jump-if-addr> break/disp32"
    34514     0x20/imm32/size
    34515     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
    34516 _string_0f_87_jump_loop:  # (payload array byte)
    34517     0x11/imm32/alloc-id:fake:payload
    34518     # "0f 87/jump-if-addr> loop/disp32"
    34519     0x1f/imm32/size
    34520     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
    34521 _string_0f_8c_jump_label:  # (payload array byte)
    34522     0x11/imm32/alloc-id:fake:payload
    34523     # "0f 8c/jump-if-<"
    34524     0xf/imm32/size
    34525     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/<
    34526 _string_0f_8c_jump_break:  # (payload array byte)
    34527     0x11/imm32/alloc-id:fake:payload
    34528     # "0f 8c/jump-if-< break/disp32"
    34529     0x1c/imm32/size
    34530     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
    34531 _string_0f_8c_jump_loop:  # (payload array byte)
    34532     0x11/imm32/alloc-id:fake:payload
    34533     # "0f 8c/jump-if-< loop/disp32"
    34534     0x1b/imm32/size
    34535     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
    34536 _string_0f_8d_jump_label:  # (payload array byte)
    34537     0x11/imm32/alloc-id:fake:payload
    34538     # "0f 8d/jump-if->="
    34539     0x10/imm32/size
    34540     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/=
    34541 _string_0f_8d_jump_break:  # (payload array byte)
    34542     0x11/imm32/alloc-id:fake:payload
    34543     # "0f 8d/jump-if->= break/disp32"
    34544     0x1d/imm32/size
    34545     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
    34546 _string_0f_8d_jump_loop:  # (payload array byte)
    34547     0x11/imm32/alloc-id:fake:payload
    34548     # "0f 8d/jump-if->= loop/disp32"
    34549     0x1c/imm32/size
    34550     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
    34551 _string_0f_8e_jump_label:  # (payload array byte)
    34552     0x11/imm32/alloc-id:fake:payload
    34553     # "0f 8e/jump-if-<="
    34554     0x10/imm32/size
    34555     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/=
    34556 _string_0f_8e_jump_break:  # (payload array byte)
    34557     0x11/imm32/alloc-id:fake:payload
    34558     # "0f 8e/jump-if-<= break/disp32"
    34559     0x1d/imm32/size
    34560     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
    34561 _string_0f_8e_jump_loop:  # (payload array byte)
    34562     0x11/imm32/alloc-id:fake:payload
    34563     # "0f 8e/jump-if-<= loop/disp32"
    34564     0x1c/imm32/size
    34565     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
    34566 _string_0f_8f_jump_label:  # (payload array byte)
    34567     0x11/imm32/alloc-id:fake:payload
    34568     # "0f 8f/jump-if->"
    34569     0xf/imm32/size
    34570     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/>
    34571 _string_0f_8f_jump_break:  # (payload array byte)
    34572     0x11/imm32/alloc-id:fake:payload
    34573     # "0f 8f/jump-if-> break/disp32"
    34574     0x1c/imm32/size
    34575     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
    34576 _string_0f_8f_jump_loop:  # (payload array byte)
    34577     0x11/imm32/alloc-id:fake:payload
    34578     # "0f 8f/jump-if-> loop/disp32"
    34579     0x1b/imm32/size
    34580     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
    34581 _string_0f_af_multiply:  # (payload array byte)
    34582     0x11/imm32/alloc-id:fake:payload
    34583     # "0f af/multiply"
    34584     0xe/imm32/size
    34585     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
    34586 _string_f3_0f_2a_convert_to_float:
    34587     0x11/imm32/alloc-id:fake:payload
    34588     # "f3 0f 2a/convert-to-float"
    34589     0x19/imm32/size
    34590     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
    34591 _string_f3_0f_2d_convert_to_int:
    34592     0x11/imm32/alloc-id:fake:payload
    34593     # "f3 0f 2d/convert-to-int"
    34594     0x17/imm32/size
    34595     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
    34596 _string_f3_0f_2c_truncate_to_int:
    34597     0x11/imm32/alloc-id:fake:payload
    34598     # "f3 0f 2c/truncate-to-int"
    34599     0x18/imm32/size
    34600     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
    34601 _string_f3_0f_58_add:
    34602     0x11/imm32/alloc-id:fake:payload
    34603     # "f3 0f 58/add"
    34604     0xc/imm32/size
    34605     0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x35/5 0x38/8 0x2f/slash 0x61/a 0x64/d 0x64/d
    34606 _string_f3_0f_5c_subtract:
    34607     0x11/imm32/alloc-id:fake:payload
    34608     # "f3 0f 5c/subtract"
    34609     0x11/imm32/size
    34610     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
    34611 _string_f3_0f_59_multiply:
    34612     0x11/imm32/alloc-id:fake:payload
    34613     # "f3 0f 59/multiply"
    34614     0x11/imm32/size
    34615     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
    34616 _string_f3_0f_5e_divide:
    34617     0x11/imm32/alloc-id:fake:payload
    34618     # "f3 0f 5e/divide"
    34619     0xf/imm32/size
    34620     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
    34621 _string_f3_0f_53_reciprocal:
    34622     0x11/imm32/alloc-id:fake:payload
    34623     # "f3 0f 53/reciprocal"
    34624     0x13/imm32/size
    34625     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
    34626 _string_f3_0f_51_square_root:
    34627     0x11/imm32/alloc-id:fake:payload
    34628     # "f3 0f 51/square-root"
    34629     0x14/imm32/size
    34630     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
    34631 _string_f3_0f_52_inverse_square_root:
    34632     0x11/imm32/alloc-id:fake:payload
    34633     # "f3 0f 52/inverse-square-root"
    34634     0x1c/imm32/size
    34635     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
    34636 _string_f3_0f_5d_min:
    34637     0x11/imm32/alloc-id:fake:payload
    34638     # "f3 0f 5d/min"
    34639     0xc/imm32/size
    34640     0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x35/5 0x64/d 0x2f/slash 0x6d/m 0x69/i 0x6e/n
    34641 _string_f3_0f_5f_max:
    34642     0x11/imm32/alloc-id:fake:payload
    34643     # "f3 0f 5f/max"
    34644     0xc/imm32/size
    34645     0x66/f 0x33/3 0x20/space 0x30/0 0x66/f 0x20/space 0x35/5 0x66/f 0x2f/slash 0x6d/m 0x61/a 0x78/x
    34646 _string_f3_0f_10_copy:
    34647     0x11/imm32/alloc-id:fake:payload
    34648     # "f3 0f 10/copy"
    34649     0xd/imm32/size
    34650     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
    34651 _string_f3_0f_11_copy:
    34652     0x11/imm32/alloc-id:fake:payload
    34653     # "f3 0f 11/copy"
    34654     0xd/imm32/size
    34655     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
    34656 _string_0f_2f_compare:
    34657     0x11/imm32/alloc-id:fake:payload
    34658     # "0f 2f/compare"
    34659     0xd/imm32/size
    34660     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
    34661 _string_21_and_with:  # (payload array byte)
    34662     0x11/imm32/alloc-id:fake:payload
    34663     # "21/and-with"
    34664     0xb/imm32/size
    34665     0x32/2 0x31/1 0x2f/slash 0x61/a 0x6e/n 0x64/d 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h
    34666 _string_23_and:  # (payload array byte)
    34667     0x11/imm32/alloc-id:fake:payload
    34668     # "23/and"
    34669     0x6/imm32/size
    34670     0x32/2 0x33/3 0x2f/slash 0x61/a 0x6e/n 0x64/d
    34671 _string_25_and_with_eax:  # (payload array byte)
    34672     0x11/imm32/alloc-id:fake:payload
    34673     # "25/and-with-eax"
    34674     0xf/imm32/size
    34675     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
    34676 _string_29_subtract_from:  # (payload array byte)
    34677     0x11/imm32/alloc-id:fake:payload
    34678     # "29/subtract-from"
    34679     0x10/imm32/size
    34680     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
    34681 _string_2b_subtract:  # (payload array byte)
    34682     0x11/imm32/alloc-id:fake:payload
    34683     # "2b/subtract"
    34684     0xb/imm32/size
    34685     0x32/2 0x62/b 0x2f/slash 0x73/s 0x75/u 0x62/b 0x74/t 0x72/r 0x61/a 0x63/c 0x74/t
    34686 _string_2d_subtract_from_eax:  # (payload array byte)
    34687     0x11/imm32/alloc-id:fake:payload
    34688     # "2d/subtract-from-eax"
    34689     0x14/imm32/size
    34690     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
    34691 _string_31_xor_with:  # (payload array byte)
    34692     0x11/imm32/alloc-id:fake:payload
    34693     # "31/xor-with"
    34694     0xb/imm32/size
    34695     0x33/3 0x31/1 0x2f/slash 0x78/x 0x6f/o 0x72/r 0x2d/dash 0x77/w 0x69/i 0x74/t 0x68/h
    34696 _string_33_xor:  # (payload array byte)
    34697     0x11/imm32/alloc-id:fake:payload
    34698     # "33/xor"
    34699     0x6/imm32/size
    34700     0x33/3 0x33/3 0x2f/slash 0x78/x 0x6f/o 0x72/r
    34701 _string_35_xor_with_eax:  # (payload array byte)
    34702     0x11/imm32/alloc-id:fake:payload
    34703     # "35/xor-with-eax"
    34704     0xf/imm32/size
    34705     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
    34706 _string_39_compare->:  # (payload array byte)
    34707     0x11/imm32/alloc-id:fake:payload
    34708     # "39/compare->"
    34709     0xc/imm32/size
    34710     0x33/3 0x39/9 0x2f/slash 0x63/c 0x6f/o 0x6d/m 0x70/p 0x61/a 0x72/r 0x65/e 0x2d/dash 0x3e/>
    34711 _string_3b_compare<-:  # (payload array byte)
    34712     0x11/imm32/alloc-id:fake:payload
    34713     # "3b/compare<-"
    34714     0xc/imm32/size
    34715     0x33/3 0x62/b 0x2f/slash 0x63/c 0x6f/o 0x6d/m 0x70/p 0x61/a 0x72/r 0x65/e 0x3c/< 0x2d/dash
    34716 _string_3d_compare_eax_with:  # (payload array byte)
    34717     0x11/imm32/alloc-id:fake:payload
    34718     # "3d/compare-eax-with"
    34719     0x13/imm32/size
    34720     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
    34721 _string_40_increment_eax:  # (payload array byte)
    34722     0x11/imm32/alloc-id:fake:payload
    34723     # "40/increment-eax"
    34724     0x10/imm32/size
    34725     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
    34726 _string_41_increment_ecx:  # (payload array byte)
    34727     0x11/imm32/alloc-id:fake:payload
    34728     # "41/increment-ecx"
    34729     0x10/imm32/size
    34730     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
    34731 _string_42_increment_edx:  # (payload array byte)
    34732     0x11/imm32/alloc-id:fake:payload
    34733     # "42/increment-edx"
    34734     0x10/imm32/size
    34735     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
    34736 _string_43_increment_ebx:  # (payload array byte)
    34737     0x11/imm32/alloc-id:fake:payload
    34738     # "43/increment-ebx"
    34739     0x10/imm32/size
    34740     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
    34741 _string_46_increment_esi:  # (payload array byte)
    34742     0x11/imm32/alloc-id:fake:payload
    34743     # "46/increment-esi"
    34744     0x10/imm32/size
    34745     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
    34746 _string_47_increment_edi:  # (payload array byte)
    34747     0x11/imm32/alloc-id:fake:payload
    34748     # "47/increment-edi"
    34749     0x10/imm32/size
    34750     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
    34751 _string_48_decrement_eax:  # (payload array byte)
    34752     0x11/imm32/alloc-id:fake:payload
    34753     # "48/decrement-eax"
    34754     0x10/imm32/size
    34755     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
    34756 _string_49_decrement_ecx:  # (payload array byte)
    34757     0x11/imm32/alloc-id:fake:payload
    34758     # "49/decrement-ecx"
    34759     0x10/imm32/size
    34760     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
    34761 _string_4a_decrement_edx:  # (payload array byte)
    34762     0x11/imm32/alloc-id:fake:payload
    34763     # "4a/decrement-edx"
    34764     0x10/imm32/size
    34765     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
    34766 _string_4b_decrement_ebx:  # (payload array byte)
    34767     0x11/imm32/alloc-id:fake:payload
    34768     # "4b/decrement-ebx"
    34769     0x10/imm32/size
    34770     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
    34771 _string_4e_decrement_esi:  # (payload array byte)
    34772     0x11/imm32/alloc-id:fake:payload
    34773     # "4e/decrement-esi"
    34774     0x10/imm32/size
    34775     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
    34776 _string_4f_decrement_edi:  # (payload array byte)
    34777     0x11/imm32/alloc-id:fake:payload
    34778     # "4f/decrement-edi"
    34779     0x10/imm32/size
    34780     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
    34781 _string_81_subop_add:  # (payload array byte)
    34782     0x11/imm32/alloc-id:fake:payload
    34783     # "81 0/subop/add"
    34784     0xe/imm32/size
    34785     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
    34786 _string_81_subop_or:  # (payload array byte)
    34787     0x11/imm32/alloc-id:fake:payload
    34788     # "81 1/subop/or"
    34789     0xd/imm32/size
    34790     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
    34791 _string_81_subop_and:  # (payload array byte)
    34792     0x11/imm32/alloc-id:fake:payload
    34793     # "81 4/subop/and"
    34794     0xe/imm32/size
    34795     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
    34796 _string_81_subop_subtract:  # (payload array byte)
    34797     0x11/imm32/alloc-id:fake:payload
    34798     # "81 5/subop/subtract"
    34799     0x13/imm32/size
    34800     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
    34801 _string_81_subop_xor:  # (payload array byte)
    34802     0x11/imm32/alloc-id:fake:payload
    34803     # "81 6/subop/xor"
    34804     0xe/imm32/size
    34805     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
    34806 _string_81_subop_compare:  # (payload array byte)
    34807     0x11/imm32/alloc-id:fake:payload
    34808     # "81 7/subop/compare"
    34809     0x12/imm32/size
    34810     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
    34811 _string_89_<-:  # (payload array byte)
    34812     0x11/imm32/alloc-id:fake:payload
    34813     # "89/<-"
    34814     0x5/imm32/size
    34815     0x38/8 0x39/9 0x2f/slash 0x3c/< 0x2d/dash
    34816 _string_8b_->:  # (payload array byte)
    34817     0x11/imm32/alloc-id:fake:payload
    34818     # "8b/->"
    34819     0x5/imm32/size
    34820     0x38/8 0x62/b 0x2f/slash 0x2d/dash 0x3e/>
    34821 _string_8a_copy_byte:
    34822     0x11/imm32/alloc-id:fake:payload
    34823     # "8a/byte->"
    34824     0x9/imm32/size
    34825     0x38/8 0x61/a 0x2f/slash 0x62/b 0x79/y 0x74/t 0x65/e 0x2d/dash 0x3e/>
    34826 _string_88_copy_byte:
    34827     0x11/imm32/alloc-id:fake:payload
    34828     # "88/byte<-"
    34829     0x9/imm32/size
    34830     0x38/8 0x38/8 0x2f/slash 0x62/b 0x79/y 0x74/t 0x65/e 0x3c/< 0x2d/-
    34831 _string_8d_copy_address:  # (payload array byte)
    34832     0x11/imm32/alloc-id:fake:payload
    34833     # "8d/copy-address"
    34834     0xf/imm32/size
    34835     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
    34836 _string_b8_copy_to_eax:  # (payload array byte)
    34837     0x11/imm32/alloc-id:fake:payload
    34838     # "b8/copy-to-eax"
    34839     0xe/imm32/size
    34840     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
    34841 _string_b9_copy_to_ecx:  # (payload array byte)
    34842     0x11/imm32/alloc-id:fake:payload
    34843     # "b9/copy-to-ecx"
    34844     0xe/imm32/size
    34845     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
    34846 _string_ba_copy_to_edx:  # (payload array byte)
    34847     0x11/imm32/alloc-id:fake:payload
    34848     # "ba/copy-to-edx"
    34849     0xe/imm32/size
    34850     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
    34851 _string_bb_copy_to_ebx:  # (payload array byte)
    34852     0x11/imm32/alloc-id:fake:payload
    34853     # "bb/copy-to-ebx"
    34854     0xe/imm32/size
    34855     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
    34856 _string_be_copy_to_esi:  # (payload array byte)
    34857     0x11/imm32/alloc-id:fake:payload
    34858     # "be/copy-to-esi"
    34859     0xe/imm32/size
    34860     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
    34861 _string_bf_copy_to_edi:  # (payload array byte)
    34862     0x11/imm32/alloc-id:fake:payload
    34863     # "bf/copy-to-edi"
    34864     0xe/imm32/size
    34865     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
    34866 _string_c7_subop_copy:  # (payload array byte)
    34867     0x11/imm32/alloc-id:fake:payload
    34868     # "c7 0/subop/copy"
    34869     0xf/imm32/size
    34870     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
    34871 _string_e9_jump_label:  # (payload array byte)
    34872     0x11/imm32/alloc-id:fake:payload
    34873     # "e9/jump"
    34874     0x7/imm32/size
    34875     0x65/e 0x39/9 0x2f/slash 0x6a/j 0x75/u 0x6d/m 0x70/p
    34876 _string_e9_jump_break:  # (payload array byte)
    34877     0x11/imm32/alloc-id:fake:payload
    34878     # "e9/jump break/disp32"
    34879     0x14/imm32/size
    34880     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
    34881 _string_e9_jump_loop:  # (payload array byte)
    34882     0x11/imm32/alloc-id:fake:payload
    34883     # "e9/jump loop/disp32"
    34884     0x13/imm32/size
    34885     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
    34886 _string_f7_subop_negate:
    34887     0x11/imm32/alloc-id:fake:payload
    34888     # "f7 3/subop/negate"
    34889     0x11/imm32/size
    34890     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
    34891 _string_f7_subop_not:
    34892     0x11/imm32/alloc-id:fake:payload
    34893     # "f7 2/subop/not"
    34894     0xe/imm32/size
    34895     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
    34896 _string_ff_subop_increment:  # (payload array byte)
    34897     0x11/imm32/alloc-id:fake:payload
    34898     # "ff 0/subop/increment"
    34899     0x14/imm32/size
    34900     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
    34901 _string_ff_subop_decrement:  # (payload array byte)
    34902     0x11/imm32/alloc-id:fake:payload
    34903     # "ff 1/subop/decrement"
    34904     0x14/imm32/size
    34905     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
    34906 _string_c1_subop_shift_left:  # (payload array byte)
    34907     0x11/imm32/alloc-id:fake:payload
    34908     # "c1/shift 4/subop/left"
    34909     0x15/imm32/size
    34910     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
    34911 _string_c1_subop_shift_right_padding_zeroes:  # (payload array byte)
    34912     0x11/imm32/alloc-id:fake:payload
    34913     # "c1/shift 5/subop/right-padding-zeroes"
    34914     0x25/imm32/size
    34915     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
    34916 _string_c1_subop_shift_right_preserving_sign:  # (payload array byte)
    34917     0x11/imm32/alloc-id:fake:payload
    34918     # "c1/shift 7/subop/right-preserving-sign"
    34919     0x26/imm32/size
    34920     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
    34921
    34922 Single-int-var-in-mem:  # (payload list var)
    34923     0x11/imm32/alloc-id:fake:payload
    34924     0x11/imm32/alloc-id:fake
    34925     Int-var-in-mem/imm32
    34926     0/imm32/next
    34927     0/imm32/next
    34928
    34929 Int-var-in-mem:  # (payload var)
    34930     0x11/imm32/alloc-id:fake:payload
    34931     0/imm32/name
    34932     0/imm32/name
    34933     0x11/imm32/alloc-id:fake
    34934     Type-int/imm32
    34935     1/imm32/some-block-depth
    34936     1/imm32/some-stack-offset
    34937     0/imm32/no-register
    34938     0/imm32/no-register
    34939
    34940 # Not really legal, but closest we can currently represent a dereference of an (addr byte)
    34941 Single-byte-var-in-mem:  # (payload list var)
    34942     0x11/imm32/alloc-id:fake:payload
    34943     0x11/imm32/alloc-id:fake
    34944     Byte-var-in-mem/imm32
    34945     0/imm32/next
    34946     0/imm32/next
    34947
    34948 # Not really legal, but closest we can currently represent a dereference of an (addr byte)
    34949 Byte-var-in-mem:  # (payload var)
    34950     0x11/imm32/alloc-id:fake:payload
    34951     0/imm32/name
    34952     0/imm32/name
    34953     0x11/imm32/alloc-id:fake
    34954     Type-byte/imm32
    34955     1/imm32/some-block-depth
    34956     1/imm32/some-stack-offset
    34957     0/imm32/no-register
    34958     0/imm32/no-register
    34959
    34960 Two-args-int-stack-int-reg:  # (payload list var)
    34961     0x11/imm32/alloc-id:fake:payload
    34962     0x11/imm32/alloc-id:fake
    34963     Int-var-in-mem/imm32
    34964     0x11/imm32/alloc-id:fake
    34965     Single-int-var-in-some-register/imm32/next
    34966
    34967 Two-int-args-in-regs:  # (payload list var)
    34968     0x11/imm32/alloc-id:fake:payload
    34969     0x11/imm32/alloc-id:fake
    34970     Int-var-in-some-register/imm32
    34971     0x11/imm32/alloc-id:fake
    34972     Single-int-var-in-some-register/imm32/next
    34973
    34974 # Not really legal, but closest we can currently represent a dereference of an (addr byte)
    34975 Two-args-byte-stack-byte-reg:  # (payload list var)
    34976     0x11/imm32/alloc-id:fake:payload
    34977     0x11/imm32/alloc-id:fake
    34978     Byte-var-in-mem/imm32
    34979     0x11/imm32/alloc-id:fake
    34980     Single-byte-var-in-some-register/imm32/next
    34981
    34982 Two-args-int-reg-int-stack:  # (payload list var)
    34983     0x11/imm32/alloc-id:fake:payload
    34984     0x11/imm32/alloc-id:fake
    34985     Int-var-in-some-register/imm32
    34986     0x11/imm32/alloc-id:fake
    34987     Single-int-var-in-mem/imm32/next
    34988
    34989 Two-args-int-eax-int-literal:  # (payload list var)
    34990     0x11/imm32/alloc-id:fake:payload
    34991     0x11/imm32/alloc-id:fake
    34992     Int-var-in-eax/imm32
    34993     0x11/imm32/alloc-id:fake
    34994     Single-lit-var/imm32/next
    34995
    34996 Int-var-and-literal:  # (payload list var)
    34997     0x11/imm32/alloc-id:fake:payload
    34998     0x11/imm32/alloc-id:fake
    34999     Int-var-in-mem/imm32
    35000     0x11/imm32/alloc-id:fake
    35001     Single-lit-var/imm32/next
    35002
    35003 Int-var-in-register-and-literal:  # (payload list var)
    35004     0x11/imm32/alloc-id:fake:payload
    35005     0x11/imm32/alloc-id:fake
    35006     Int-var-in-some-register/imm32
    35007     0x11/imm32/alloc-id:fake
    35008     Single-lit-var/imm32/next
    35009
    35010 Two-float-args-in-regs:  # (payload list var)
    35011     0x11/imm32/alloc-id:fake:payload
    35012     0x11/imm32/alloc-id:fake
    35013     Float-var-in-some-register/imm32
    35014     0x11/imm32/alloc-id:fake
    35015     Single-float-var-in-some-register/imm32/next
    35016
    35017 Two-args-float-reg-float-stack:  # (payload list var)
    35018     0x11/imm32/alloc-id:fake:payload
    35019     0x11/imm32/alloc-id:fake
    35020     Float-var-in-some-register/imm32
    35021     0x11/imm32/alloc-id:fake
    35022     Single-float-var-in-mem/imm32/next
    35023
    35024 Two-args-float-stack-float-reg:  # (payload list var)
    35025     0x11/imm32/alloc-id:fake:payload
    35026     0x11/imm32/alloc-id:fake
    35027     Float-var-in-mem/imm32
    35028     0x11/imm32/alloc-id:fake
    35029     Single-float-var-in-some-register/imm32/next
    35030
    35031 Single-int-var-in-some-register:  # (payload list var)
    35032     0x11/imm32/alloc-id:fake:payload
    35033     0x11/imm32/alloc-id:fake
    35034     Int-var-in-some-register/imm32
    35035     0/imm32/next
    35036     0/imm32/next
    35037
    35038 Single-addr-var-in-some-register:  # (payload list var)
    35039     0x11/imm32/alloc-id:fake:payload
    35040     0x11/imm32/alloc-id:fake
    35041     Addr-var-in-some-register/imm32
    35042     0/imm32/next
    35043     0/imm32/next
    35044
    35045 Single-byte-var-in-some-register:  # (payload list var)
    35046     0x11/imm32/alloc-id:fake:payload
    35047     0x11/imm32/alloc-id:fake
    35048     Byte-var-in-some-register/imm32
    35049     0/imm32/next
    35050     0/imm32/next
    35051
    35052 Int-var-in-some-register:  # (payload var)
    35053     0x11/imm32/alloc-id:fake:payload
    35054     0/imm32/name
    35055     0/imm32/name
    35056     0x11/imm32/alloc-id:fake
    35057     Type-int/imm32
    35058     1/imm32/some-block-depth
    35059     0/imm32/no-stack-offset
    35060     0x11/imm32/alloc-id:fake
    35061     Any-register/imm32
    35062
    35063 Any-register:  # (payload array byte)
    35064     0x11/imm32/alloc-id:fake:payload
    35065     1/imm32/size
    35066     # data
    35067     2a/asterisk
    35068
    35069 Addr-var-in-some-register:  # (payload var)
    35070     0x11/imm32/alloc-id:fake:payload
    35071     0/imm32/name
    35072     0/imm32/name
    35073     0x11/imm32/alloc-id:fake
    35074     Type-addr/imm32
    35075     1/imm32/some-block-depth
    35076     0/imm32/no-stack-offset
    35077     0x11/imm32/alloc-id:fake
    35078     Any-register/imm32
    35079
    35080 Byte-var-in-some-register:  # (payload var)
    35081     0x11/imm32/alloc-id:fake:payload
    35082     0/imm32/name
    35083     0/imm32/name
    35084     0x11/imm32/alloc-id:fake
    35085     Type-byte/imm32
    35086     1/imm32/some-block-depth
    35087     0/imm32/no-stack-offset
    35088     0x11/imm32/alloc-id:fake
    35089     Any-register/imm32
    35090
    35091 Single-int-var-in-eax:  # (payload list var)
    35092     0x11/imm32/alloc-id:fake:payload
    35093     0x11/imm32/alloc-id:fake
    35094     Int-var-in-eax/imm32
    35095     0/imm32/next
    35096     0/imm32/next
    35097
    35098 Int-var-in-eax:
    35099     0x11/imm32/alloc-id:fake:payload
    35100     0/imm32/name
    35101     0/imm32/name
    35102     0x11/imm32/alloc-id:fake
    35103     Type-int/imm32
    35104     1/imm32/some-block-depth
    35105     0/imm32/no-stack-offset
    35106     0x11/imm32/alloc-id:fake
    35107     $Mu-register-eax/imm32  # can't use Register-eax only to keep our buggy tools/treeshake.cc happy (TODO)
    35108
    35109 Single-int-var-in-ecx:  # (payload list var)
    35110     0x11/imm32/alloc-id:fake:payload
    35111     0x11/imm32/alloc-id:fake
    35112     Int-var-in-ecx/imm32
    35113     0/imm32/next
    35114     0/imm32/next
    35115
    35116 Int-var-in-ecx:
    35117     0x11/imm32/alloc-id:fake:payload
    35118     0/imm32/name
    35119     0/imm32/name
    35120     0x11/imm32/alloc-id:fake
    35121     Type-int/imm32
    35122     1/imm32/some-block-depth
    35123     0/imm32/no-stack-offset
    35124     0x11/imm32/alloc-id:fake
    35125     $Register-ecx/imm32/register
    35126
    35127 Single-int-var-in-edx:  # (payload list var)
    35128     0x11/imm32/alloc-id:fake:payload
    35129     0x11/imm32/alloc-id:fake
    35130     Int-var-in-edx/imm32
    35131     0/imm32/next
    35132     0/imm32/next
    35133
    35134 Int-var-in-edx:  # (payload list var)
    35135     0x11/imm32/alloc-id:fake:payload
    35136     0/imm32/name
    35137     0/imm32/name
    35138     0x11/imm32/alloc-id:fake
    35139     Type-int/imm32
    35140     1/imm32/some-block-depth
    35141     0/imm32/no-stack-offset
    35142     0x11/imm32/alloc-id:fake
    35143     $Register-edx/imm32/register
    35144
    35145 Single-int-var-in-ebx:  # (payload list var)
    35146     0x11/imm32/alloc-id:fake:payload
    35147     0x11/imm32/alloc-id:fake
    35148     Int-var-in-ebx/imm32
    35149     0/imm32/next
    35150     0/imm32/next
    35151
    35152 Int-var-in-ebx:  # (payload list var)
    35153     0x11/imm32/alloc-id:fake:payload
    35154     0/imm32/name
    35155     0/imm32/name
    35156     0x11/imm32/alloc-id:fake
    35157     Type-int/imm32
    35158     1/imm32/some-block-depth
    35159     0/imm32/no-stack-offset
    35160     0x11/imm32/alloc-id:fake
    35161     $Register-ebx/imm32/register
    35162
    35163 Single-int-var-in-esi:  # (payload list var)
    35164     0x11/imm32/alloc-id:fake:payload
    35165     0x11/imm32/alloc-id:fake
    35166     Int-var-in-esi/imm32
    35167     0/imm32/next
    35168     0/imm32/next
    35169
    35170 Int-var-in-esi:  # (payload list var)
    35171     0x11/imm32/alloc-id:fake:payload
    35172     0/imm32/name
    35173     0/imm32/name
    35174     0x11/imm32/alloc-id:fake
    35175     Type-int/imm32
    35176     1/imm32/some-block-depth
    35177     0/imm32/no-stack-offset
    35178     0x11/imm32/alloc-id:fake
    35179     $Register-esi/imm32/register
    35180
    35181 Single-int-var-in-edi:  # (payload list var)
    35182     0x11/imm32/alloc-id:fake:payload
    35183     0x11/imm32/alloc-id:fake
    35184     Int-var-in-edi/imm32
    35185     0/imm32/next
    35186     0/imm32/next
    35187
    35188 Int-var-in-edi:  # (payload list var)
    35189     0x11/imm32/alloc-id:fake:payload
    35190     0/imm32/name
    35191     0/imm32/name
    35192     0x11/imm32/alloc-id:fake
    35193     Type-int/imm32
    35194     1/imm32/some-block-depth
    35195     0/imm32/no-stack-offset
    35196     0x11/imm32/alloc-id:fake
    35197     $Register-edi/imm32/register
    35198
    35199 Single-lit-var:  # (payload list var)
    35200     0x11/imm32/alloc-id:fake:payload
    35201     0x11/imm32/alloc-id:fake
    35202     Lit-var/imm32
    35203     0/imm32/next
    35204     0/imm32/next
    35205
    35206 Lit-var:  # (payload var)
    35207     0x11/imm32/alloc-id:fake:payload
    35208     0/imm32/name
    35209     0/imm32/name
    35210     0x11/imm32/alloc-id:fake
    35211     Type-literal/imm32
    35212     1/imm32/some-block-depth
    35213     0/imm32/no-stack-offset
    35214     0/imm32/no-register
    35215     0/imm32/no-register
    35216
    35217 Single-float-var-in-mem:  # (payload list var)
    35218     0x11/imm32/alloc-id:fake:payload
    35219     0x11/imm32/alloc-id:fake
    35220     Float-var-in-mem/imm32
    35221     0/imm32/next
    35222     0/imm32/next
    35223
    35224 Float-var-in-mem:  # (payload var)
    35225     0x11/imm32/alloc-id:fake:payload
    35226     0/imm32/name
    35227     0/imm32/name
    35228     0x11/imm32/alloc-id:fake
    35229     Type-float/imm32
    35230     1/imm32/some-block-depth
    35231     1/imm32/some-stack-offset
    35232     0/imm32/no-register
    35233     0/imm32/no-register
    35234
    35235 Single-float-var-in-some-register:  # (payload list var)
    35236     0x11/imm32/alloc-id:fake:payload
    35237     0x11/imm32/alloc-id:fake
    35238     Float-var-in-some-register/imm32
    35239     0/imm32/next
    35240     0/imm32/next
    35241
    35242 Float-var-in-some-register:  # (payload var)
    35243     0x11/imm32/alloc-id:fake:payload
    35244     0/imm32/name
    35245     0/imm32/name
    35246     0x11/imm32/alloc-id:fake
    35247     Type-float/imm32
    35248     1/imm32/some-block-depth
    35249     0/imm32/no-stack-offset
    35250     0x11/imm32/alloc-id:fake
    35251     Any-register/imm32
    35252
    35253 Type-int:  # (payload type-tree)
    35254     0x11/imm32/alloc-id:fake:payload
    35255     1/imm32/is-atom
    35256     1/imm32/value:int
    35257     0/imm32/left:unused
    35258     0/imm32/right:null
    35259     0/imm32/right:null
    35260
    35261 Type-literal:  # (payload type-tree)
    35262     0x11/imm32/alloc-id:fake:payload
    35263     1/imm32/is-atom
    35264     0/imm32/value:literal
    35265     0/imm32/left:unused
    35266     0/imm32/right:null
    35267     0/imm32/right:null
    35268
    35269 Type-addr:  # (payload type-tree)
    35270     0x11/imm32/alloc-id:fake:payload
    35271     1/imm32/is-atom
    35272     2/imm32/value:addr
    35273     0/imm32/left:unused
    35274     0/imm32/right:null
    35275     0/imm32/right:null
    35276
    35277 Type-array:  # (payload type-tree)
    35278     0x11/imm32/alloc-id:fake:payload
    35279     1/imm32/is-atom
    35280     3/imm32/value:array
    35281     0/imm32/left:unused
    35282     0/imm32/right:null
    35283     0/imm32/right:null
    35284
    35285 Type-byte:  # (payload type-tree)
    35286     0x11/imm32/alloc-id:fake:payload
    35287     1/imm32/is-atom
    35288     8/imm32/value:byte
    35289     0/imm32/left:unused
    35290     0/imm32/right:null
    35291     0/imm32/right:null
    35292
    35293 Type-float:  # (payload type-tree)
    35294     0x11/imm32/alloc-id:fake:payload
    35295     1/imm32/is-atom
    35296     0xf/imm32/value:float
    35297     0/imm32/left:unused
    35298     0/imm32/right:null
    35299     0/imm32/right:null
    35300
    35301 Addr-type-string:  # (addr type-tree)
    35302   0/imm32/not-atom
    35303   0x11/imm32/alloc-id:fake
    35304   Type-addr/imm32/left
    35305   0x11/imm32/alloc-id:fake
    35306   _Addr-type-string:array/imm32/right
    35307 _Addr-type-string:array:  # (payload type-tree)
    35308   0x11/imm32/alloc-id:fake:payload
    35309   0/imm32/not-atom
    35310   0x11/imm32/alloc-id:fake
    35311   Type-array/imm32/left
    35312   0x11/imm32/alloc-id:fake
    35313   _Addr-type-string:byte/imm32/right
    35314 _Addr-type-string:byte:  # (payload type-tree)
    35315   0x11/imm32/alloc-id:fake:payload
    35316   0/imm32/not-atom
    35317   0x11/imm32/alloc-id:fake
    35318   Type-byte/imm32/left
    35319   0/imm32/right:null
    35320   0/imm32/right:null
    35321
    35322 == code
    35323 emit-subx-primitive:  # out: (addr buffered-file), stmt: (addr stmt), primitive: (addr primitive), err: (addr buffered-file), ed: (addr exit-descriptor)
    35324     # . prologue
    35325     55/push-ebp
    35326     89/<- %ebp 4/r32/esp
    35327     # . save registers
    35328     50/push-eax
    35329     51/push-ecx
    35330     # ecx = primitive
    35331     8b/-> *(ebp+0x10) 1/r32/ecx
    35332     # emit primitive name
    35333     (emit-indent *(ebp+8) *Curr-block-depth)
    35334     (lookup *(ecx+0x18) *(ecx+0x1c))  # Primitive-subx-name Primitive-subx-name => eax
    35335     (write-buffered *(ebp+8) %eax)
    35336     # emit rm32 if necessary
    35337     (emit-subx-rm32 *(ebp+8) *(ecx+0x20) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))  # Primitive-subx-rm32
    35338     # emit xm32 if necessary
    35339     (emit-subx-rm32 *(ebp+8) *(ecx+0x34) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))  # Primitive-subx-xm32
    35340     # emit r32 if necessary
    35341     (emit-subx-r32 *(ebp+8) *(ecx+0x24) *(ebp+0xc))  # Primitive-subx-r32
    35342     # emit x32 if necessary
    35343     (emit-subx-x32 *(ebp+8) *(ecx+0x38) *(ebp+0xc))  # Primitive-subx-x32
    35344     # emit imm32 if necessary
    35345     (emit-subx-imm32 *(ebp+8) *(ecx+0x28) *(ebp+0xc))  # Primitive-subx-imm32
    35346     # emit imm8 if necessary
    35347     (emit-subx-imm8 *(ebp+8) *(ecx+0x2c) *(ebp+0xc))  # Primitive-subx-imm8
    35348     # emit disp32 if necessary
    35349     (emit-subx-disp32 *(ebp+8) *(ecx+0x30) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))  # Primitive-subx-disp32
    35350     (write-buffered *(ebp+8) Newline)
    35351 $emit-subx-primitive:end:
    35352     # . restore registers
    35353     59/pop-to-ecx
    35354     58/pop-to-eax
    35355     # . epilogue
    35356     89/<- %esp 5/r32/ebp
    35357     5d/pop-to-ebp
    35358     c3/return
    35359
    35360 emit-subx-rm32:  # out: (addr buffered-file), l: arg-location, stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
    35361     # . prologue
    35362     55/push-ebp
    35363     89/<- %ebp 4/r32/esp
    35364     # . save registers
    35365     50/push-eax
    35366     # if (l == 0) return
    35367     81 7/subop/compare *(ebp+0xc) 0/imm32
    35368     74/jump-if-= $emit-subx-rm32:end/disp8
    35369     # var v/eax: (addr stmt-var)
    35370     (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))  # => eax
    35371     (emit-subx-var-as-rm32 *(ebp+8) %eax)
    35372 $emit-subx-rm32:end:
    35373     # . restore registers
    35374     58/pop-to-eax
    35375     # . epilogue
    35376     89/<- %esp 5/r32/ebp
    35377     5d/pop-to-ebp
    35378     c3/return
    35379
    35380 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)
    35381     # . prologue
    35382     55/push-ebp
    35383     89/<- %ebp 4/r32/esp
    35384     # . save registers
    35385     51/push-ecx
    35386     # eax = l
    35387     8b/-> *(ebp+0xc) 0/r32/eax
    35388     # ecx = stmt
    35389     8b/-> *(ebp+8) 1/r32/ecx
    35390     # if (l == 1) return stmt->inouts
    35391     {
    35392       3d/compare-eax-and 1/imm32
    35393       75/jump-if-!= break/disp8
    35394 $get-stmt-operand-from-arg-location:1:
    35395       (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    35396       eb/jump $get-stmt-operand-from-arg-location:end/disp8
    35397     }
    35398     # if (l == 2) return stmt->inouts->next
    35399     {
    35400       3d/compare-eax-and 2/imm32
    35401       75/jump-if-!= break/disp8
    35402 $get-stmt-operand-from-arg-location:2:
    35403       (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    35404       (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    35405       eb/jump $get-stmt-operand-from-arg-location:end/disp8
    35406     }
    35407     # if (l == 3) return stmt->outputs
    35408     {
    35409       3d/compare-eax-and 3/imm32
    35410       75/jump-if-!= break/disp8
    35411 $get-stmt-operand-from-arg-location:3:
    35412       (lookup *(ecx+0x14) *(ecx+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    35413       eb/jump $get-stmt-operand-from-arg-location:end/disp8
    35414     }
    35415     # abort
    35416     e9/jump $get-stmt-operand-from-arg-location:abort/disp32
    35417 $get-stmt-operand-from-arg-location:end:
    35418     # . restore registers
    35419     59/pop-to-ecx
    35420     # . epilogue
    35421     89/<- %esp 5/r32/ebp
    35422     5d/pop-to-ebp
    35423     c3/return
    35424
    35425 $get-stmt-operand-from-arg-location:abort:
    35426     # error("invalid arg-location " eax)
    35427     (write-buffered *(ebp+0x10) "invalid arg-location ")
    35428     (write-int32-hex-buffered *(ebp+0x10) %eax)
    35429     (write-buffered *(ebp+0x10) Newline)
    35430     (flush *(ebp+0x10))
    35431     (stop *(ebp+0x14) 1)
    35432     # never gets here
    35433
    35434 emit-subx-r32:  # out: (addr buffered-file), l: arg-location, stmt: (addr stmt)
    35435     # . prologue
    35436     55/push-ebp
    35437     89/<- %ebp 4/r32/esp
    35438     # . save registers
    35439     50/push-eax
    35440     51/push-ecx
    35441     # if (l == 0) return
    35442     81 7/subop/compare *(ebp+0xc) 0/imm32
    35443     0f 84/jump-if-= $emit-subx-r32:end/disp32
    35444     # var v/eax: (addr stmt-var)
    35445     (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc))  # => eax
    35446     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    35447     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    35448 #?     (write-buffered Stderr "looking up ")
    35449 #?     (write-buffered Stderr %eax)
    35450 #?     (write-buffered Stderr Newline)
    35451 #?     (flush Stderr)
    35452     (maybe-get Mu-registers %eax 0xc)  # => eax: (addr register-index)
    35453     (write-buffered *(ebp+8) Space)
    35454     (write-int32-hex-buffered *(ebp+8) *eax)
    35455     (write-buffered *(ebp+8) "/r32")
    35456 $emit-subx-r32:end:
    35457     # . restore registers
    35458     59/pop-to-ecx
    35459     58/pop-to-eax
    35460     # . epilogue
    35461     89/<- %esp 5/r32/ebp
    35462     5d/pop-to-ebp
    35463     c3/return
    35464
    35465 emit-subx-x32:  # out: (addr buffered-file), l: arg-location, stmt: (addr stmt)
    35466     # . prologue
    35467     55/push-ebp
    35468     89/<- %ebp 4/r32/esp
    35469     # . save registers
    35470     50/push-eax
    35471     51/push-ecx
    35472     # if (l == 0) return
    35473     81 7/subop/compare *(ebp+0xc) 0/imm32
    35474     0f 84/jump-if-= $emit-subx-x32:end/disp32
    35475     # var v/eax: (addr stmt-var)
    35476     (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc))  # => eax
    35477     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    35478     (lookup *(eax+0x18) *(eax+0x1c))  # Var-register Var-register => eax
    35479 #?     (write-buffered Stderr "looking up ")
    35480 #?     (write-buffered Stderr %eax)
    35481 #?     (write-buffered Stderr Newline)
    35482 #?     (flush Stderr)
    35483     (maybe-get Mu-registers %eax 0xc)  # => eax: (addr register-index)
    35484     (write-buffered *(ebp+8) Space)
    35485     (write-int32-hex-buffered *(ebp+8) *eax)
    35486     (write-buffered *(ebp+8) "/x32")
    35487 $emit-subx-x32:end:
    35488     # . restore registers
    35489     59/pop-to-ecx
    35490     58/pop-to-eax
    35491     # . epilogue
    35492     89/<- %esp 5/r32/ebp
    35493     5d/pop-to-ebp
    35494     c3/return
    35495
    35496 emit-subx-imm32:  # out: (addr buffered-file), l: arg-location, stmt: (addr stmt)
    35497     # . prologue
    35498     55/push-ebp
    35499     89/<- %ebp 4/r32/esp
    35500     # . save registers
    35501     50/push-eax
    35502     51/push-ecx
    35503     # if (l == 0) return
    35504     81 7/subop/compare *(ebp+0xc) 0/imm32
    35505     0f 84/jump-if-= $emit-subx-imm32:end/disp32
    35506     # var v/eax: (handle var)
    35507     (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc))  # => eax
    35508     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    35509     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    35510     (write-buffered *(ebp+8) Space)
    35511     (write-buffered *(ebp+8) %eax)
    35512     (write-buffered *(ebp+8) "/imm32")
    35513 $emit-subx-imm32:end:
    35514     # . restore registers
    35515     59/pop-to-ecx
    35516     58/pop-to-eax
    35517     # . epilogue
    35518     89/<- %esp 5/r32/ebp
    35519     5d/pop-to-ebp
    35520     c3/return
    35521
    35522 emit-subx-imm8:  # out: (addr buffered-file), l: arg-location, stmt: (addr stmt)
    35523     # . prologue
    35524     55/push-ebp
    35525     89/<- %ebp 4/r32/esp
    35526     # . save registers
    35527     50/push-eax
    35528     51/push-ecx
    35529     # if (l == 0) return
    35530     81 7/subop/compare *(ebp+0xc) 0/imm32
    35531     0f 84/jump-if-= $emit-subx-imm32:end/disp32
    35532     # var v/eax: (handle var)
    35533     (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc))  # => eax
    35534     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    35535     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    35536     (write-buffered *(ebp+8) Space)
    35537     (write-buffered *(ebp+8) %eax)
    35538     (write-buffered *(ebp+8) "/imm8")
    35539 $emit-subx-imm8:end:
    35540     # . restore registers
    35541     59/pop-to-ecx
    35542     58/pop-to-eax
    35543     # . epilogue
    35544     89/<- %esp 5/r32/ebp
    35545     5d/pop-to-ebp
    35546     c3/return
    35547
    35548 emit-subx-disp32:  # out: (addr buffered-file), l: arg-location, stmt: (addr stmt), err: (addr buffered-file), ed: (addr exit-descriptor)
    35549     # . prologue
    35550     55/push-ebp
    35551     89/<- %ebp 4/r32/esp
    35552     # . save registers
    35553     50/push-eax
    35554     51/push-ecx
    35555     # if (location == 0) return
    35556     81 7/subop/compare *(ebp+0xc) 0/imm32
    35557     0f 84/jump-if-= $emit-subx-disp32:end/disp32
    35558     # var v/eax: (addr stmt-var)
    35559     (get-stmt-operand-from-arg-location *(ebp+0x10) *(ebp+0xc) *(ebp+0x14) *(ebp+0x18))  # => eax
    35560     (lookup *eax *(eax+4))  # Stmt-var-value Stmt-var-value => eax
    35561     (lookup *eax *(eax+4))  # Var-name Var-name => eax
    35562     (write-buffered *(ebp+8) Space)
    35563     (write-buffered *(ebp+8) %eax)
    35564     # hack: if instruction operation starts with "break", emit ":break"
    35565     # var name/ecx: (addr array byte) = lookup(stmt->operation)
    35566     8b/-> *(ebp+0x10) 0/r32/eax
    35567     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
    35568     89/<- %ecx 0/r32/eax
    35569     {
    35570       (string-starts-with? %ecx "break")  # => eax
    35571       3d/compare-eax-and 0/imm32/false
    35572       74/jump-if-= break/disp8
    35573       (write-buffered *(ebp+8) ":break")
    35574     }
    35575     # hack: if instruction operation starts with "loop", emit ":loop"
    35576     {
    35577       (string-starts-with? %ecx "loop")  # => eax
    35578       3d/compare-eax-and 0/imm32/false
    35579       74/jump-if-= break/disp8
    35580       (write-buffered *(ebp+8) ":loop")
    35581     }
    35582     (write-buffered *(ebp+8) "/disp32")
    35583 $emit-subx-disp32:end:
    35584     # . restore registers
    35585     59/pop-to-ecx
    35586     58/pop-to-eax
    35587     # . epilogue
    35588     89/<- %esp 5/r32/ebp
    35589     5d/pop-to-ebp
    35590     c3/return
    35591
    35592 emit-call:  # out: (addr buffered-file), stmt: (addr stmt)
    35593     # . prologue
    35594     55/push-ebp
    35595     89/<- %ebp 4/r32/esp
    35596     # . save registers
    35597     50/push-eax
    35598     51/push-ecx
    35599     #
    35600     (emit-indent *(ebp+8) *Curr-block-depth)
    35601     (write-buffered *(ebp+8) "(")
    35602     # ecx = stmt
    35603     8b/-> *(ebp+0xc) 1/r32/ecx
    35604     # - emit function name
    35605     (lookup *(ecx+4) *(ecx+8))  # Stmt1-operation Stmt1-operation => eax
    35606     (write-buffered *(ebp+8) %eax)
    35607     # - emit arguments
    35608     # var curr/eax: (addr stmt-var) = lookup(stmt->inouts)
    35609     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    35610     {
    35611       # if (curr == null) break
    35612       3d/compare-eax-and 0/imm32
    35613       74/jump-if-= break/disp8
    35614       #
    35615       (emit-subx-call-operand *(ebp+8) %eax)
    35616       # curr = lookup(curr->next)
    35617       (lookup *(eax+8) *(eax+0xc))  # Stmt-var-next Stmt-var-next => eax
    35618       eb/jump loop/disp8
    35619     }
    35620     #
    35621     (write-buffered *(ebp+8) ")\n")
    35622 $emit-call:end:
    35623     # . restore registers
    35624     59/pop-to-ecx
    35625     58/pop-to-eax
    35626     # . epilogue
    35627     89/<- %esp 5/r32/ebp
    35628     5d/pop-to-ebp
    35629     c3/return
    35630
    35631 emit-subx-call-operand:  # out: (addr buffered-file), s: (addr stmt-var)
    35632     # shares code with emit-subx-var-as-rm32
    35633     # . prologue
    35634     55/push-ebp
    35635     89/<- %ebp 4/r32/esp
    35636     # . save registers
    35637     50/push-eax
    35638     51/push-ecx
    35639     56/push-esi
    35640     # ecx = s
    35641     8b/-> *(ebp+0xc) 1/r32/ecx
    35642     # var operand/esi: (addr var) = lookup(s->value)
    35643     (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
    35644     89/<- %esi 0/r32/eax
    35645     # if (operand->register && !s->is-deref?) emit "%__"
    35646     {
    35647 $emit-subx-call-operand:check-for-register-direct:
    35648       81 7/subop/compare *(esi+0x18) 0/imm32  # Var-register
    35649       74/jump-if-= break/disp8
    35650       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
    35651       75/jump-if-!= break/disp8
    35652 $emit-subx-call-operand:register-direct:
    35653       (write-buffered *(ebp+8) " %")
    35654       (lookup *(esi+0x18) *(esi+0x1c))  # Var-register Var-register => eax
    35655       (write-buffered *(ebp+8) %eax)
    35656       e9/jump $emit-subx-call-operand:end/disp32
    35657     }
    35658     # else if (operand->register && s->is-deref?) emit "*__"
    35659     {
    35660 $emit-subx-call-operand:check-for-register-indirect:
    35661       81 7/subop/compare *(esi+0x18) 0/imm32  # Var-register
    35662       74/jump-if-= break/disp8
    35663       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
    35664       74/jump-if-= break/disp8
    35665 $emit-subx-call-operand:register-indirect:
    35666       (emit-subx-call-operand-register-indirect *(ebp+8) %esi)
    35667       e9/jump $emit-subx-call-operand:end/disp32
    35668     }
    35669     # else if (operand->stack-offset) emit "*(ebp+__)"
    35670     {
    35671       81 7/subop/compare *(esi+0x14) 0/imm32  # Var-offset
    35672       74/jump-if-= break/disp8
    35673 $emit-subx-call-operand:stack:
    35674       (emit-subx-call-operand-stack *(ebp+8) %esi)
    35675       e9/jump $emit-subx-call-operand:end/disp32
    35676     }
    35677     # else if (operand->type == literal) emit "__"
    35678     {
    35679       (lookup *(esi+8) *(esi+0xc))  # Var-type Var-type => eax
    35680       81 7/subop/compare *(eax+4) 0/imm32  # Type-tree-value
    35681       75/jump-if-!= break/disp8
    35682 $emit-subx-call-operand:literal:
    35683       (write-buffered *(ebp+8) Space)
    35684       (lookup *esi *(esi+4))  # Var-name Var-name => eax
    35685       (write-buffered *(ebp+8) %eax)
    35686       e9/jump $emit-subx-call-operand:end/disp32
    35687     }
    35688     # else if (operand->type == literal-string) emit "__"
    35689     {
    35690       (lookup *(esi+8) *(esi+0xc))  # Var-type Var-type => eax
    35691       81 7/subop/compare *(eax+4) 0x10/imm32  # Type-tree-value
    35692       75/jump-if-!= break/disp8
    35693 $emit-subx-call-operand:literal-string:
    35694       (write-buffered *(ebp+8) Space)
    35695       (lookup *esi *(esi+4))  # Var-name Var-name => eax
    35696       (write-buffered *(ebp+8) %eax)
    35697     }
    35698 $emit-subx-call-operand:end:
    35699     # . restore registers
    35700     5e/pop-to-esi
    35701     59/pop-to-ecx
    35702     58/pop-to-eax
    35703     # . epilogue
    35704     89/<- %esp 5/r32/ebp
    35705     5d/pop-to-ebp
    35706     c3/return
    35707
    35708 emit-subx-call-operand-register-indirect:  # out: (addr buffered-file), v: (addr var)
    35709     # . prologue
    35710     55/push-ebp
    35711     89/<- %ebp 4/r32/esp
    35712     # . save registers
    35713     50/push-eax
    35714     51/push-ecx
    35715     56/push-esi
    35716     # esi = v
    35717     8b/-> *(ebp+0xc) 6/r32/esi
    35718     # var size/ecx: int = size-of-deref(v)
    35719     (size-of-deref %esi)  # => eax
    35720     89/<- %ecx 0/r32/eax
    35721     # var reg-name/esi: (addr array byte) = lookup(v->register)
    35722     (lookup *(esi+0x18) *(esi+0x1c))  # Var-register Var-register => eax
    35723     89/<- %esi 0/r32/eax
    35724     # TODO: assert size is a multiple of 4
    35725     # var i/eax: int = 0
    35726     b8/copy-to-eax 0/imm32
    35727     {
    35728 $emit-subx-call-operand-register-indirect:loop:
    35729       # if (i >= size) break
    35730       39/compare %eax 1/r32/ecx
    35731       7d/jump-if->= break/disp8
    35732       # emit " *(" v->register "+" i ")"
    35733       (write-buffered *(ebp+8) " *(")
    35734       (write-buffered *(ebp+8) %esi)
    35735       (write-buffered *(ebp+8) "+")
    35736       (write-int32-hex-buffered *(ebp+8) %eax)
    35737       (write-buffered *(ebp+8) ")")
    35738       # i += 4
    35739       05/add-to-eax 4/imm32
    35740       #
    35741       eb/jump loop/disp8
    35742     }
    35743 $emit-subx-call-operand-register-indirect:end:
    35744     # . restore registers
    35745     5e/pop-to-esi
    35746     59/pop-to-ecx
    35747     58/pop-to-eax
    35748     # . epilogue
    35749     89/<- %esp 5/r32/ebp
    35750     5d/pop-to-ebp
    35751     c3/return
    35752
    35753 emit-subx-call-operand-stack:  # out: (addr buffered-file), v: (addr var)
    35754     # . prologue
    35755     55/push-ebp
    35756     89/<- %ebp 4/r32/esp
    35757     # . save registers
    35758     50/push-eax
    35759     51/push-ecx
    35760     56/push-esi
    35761     # esi = v
    35762     8b/-> *(ebp+0xc) 6/r32/esi
    35763     # var curr/ecx: int = v->offset
    35764     8b/-> *(esi+0x14) 1/r32/ecx  # Var-offset
    35765     # var max/eax: int = v->offset + size-of(v)
    35766     (size-of %esi)  # => eax
    35767     # TODO: assert size is a multiple of 4
    35768     01/add-to %eax 1/r32/ecx
    35769     {
    35770 $emit-subx-call-operand-stack:loop:
    35771       # if (curr >= max) break
    35772       39/compare %ecx 0/r32/eax
    35773       7d/jump-if->= break/disp8
    35774       # emit " *(ebp+" curr ")"
    35775       (write-buffered *(ebp+8) " *(ebp+")
    35776       (write-int32-hex-buffered *(ebp+8) %ecx)
    35777       (write-buffered *(ebp+8) ")")
    35778       # i += 4
    35779       81 0/subop/add %ecx 4/imm32
    35780       #
    35781       eb/jump loop/disp8
    35782     }
    35783 $emit-subx-call-operand-stack:end:
    35784     # . restore registers
    35785     5e/pop-to-esi
    35786     59/pop-to-ecx
    35787     58/pop-to-eax
    35788     # . epilogue
    35789     89/<- %esp 5/r32/ebp
    35790     5d/pop-to-ebp
    35791     c3/return
    35792
    35793 emit-subx-var-as-rm32:  # out: (addr buffered-file), s: (addr stmt-var)
    35794     # . prologue
    35795     55/push-ebp
    35796     89/<- %ebp 4/r32/esp
    35797     # . save registers
    35798     50/push-eax
    35799     51/push-ecx
    35800     56/push-esi
    35801     # ecx = s
    35802     8b/-> *(ebp+0xc) 1/r32/ecx
    35803     # var operand/esi: (addr var) = lookup(s->value)
    35804     (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
    35805     89/<- %esi 0/r32/eax
    35806     # if (operand->register && s->is-deref?) emit "*__"
    35807     {
    35808 $emit-subx-var-as-rm32:check-for-register-indirect:
    35809       81 7/subop/compare *(esi+0x18) 0/imm32  # Var-register
    35810       74/jump-if-= break/disp8
    35811       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
    35812       74/jump-if-= break/disp8
    35813 $emit-subx-var-as-rm32:register-indirect:
    35814       (write-buffered *(ebp+8) " *")
    35815       (lookup *(esi+0x18) *(esi+0x1c))  # Var-register Var-register => eax
    35816       (write-buffered *(ebp+8) %eax)
    35817       e9/jump $emit-subx-var-as-rm32:end/disp32
    35818     }
    35819     # if (operand->register && !s->is-deref?) emit "%__"
    35820     {
    35821 $emit-subx-var-as-rm32:check-for-register-direct:
    35822       81 7/subop/compare *(esi+0x18) 0/imm32  # Var-register
    35823       74/jump-if-= break/disp8
    35824       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
    35825       75/jump-if-!= break/disp8
    35826 $emit-subx-var-as-rm32:register-direct:
    35827       (write-buffered *(ebp+8) " %")
    35828       (lookup *(esi+0x18) *(esi+0x1c))  # Var-register Var-register => eax
    35829       (write-buffered *(ebp+8) %eax)
    35830       e9/jump $emit-subx-var-as-rm32:end/disp32
    35831     }
    35832     # else if (operand->stack-offset) emit "*(ebp+__)"
    35833     {
    35834       81 7/subop/compare *(esi+0x14) 0/imm32  # Var-offset
    35835       74/jump-if-= break/disp8
    35836 $emit-subx-var-as-rm32:stack:
    35837       (write-buffered *(ebp+8) Space)
    35838       (write-buffered *(ebp+8) "*(ebp+")
    35839       (write-int32-hex-buffered *(ebp+8) *(esi+0x14))  # Var-offset
    35840       (write-buffered *(ebp+8) ")")
    35841     }
    35842 $emit-subx-var-as-rm32:end:
    35843     # . restore registers
    35844     5e/pop-to-esi
    35845     59/pop-to-ecx
    35846     58/pop-to-eax
    35847     # . epilogue
    35848     89/<- %esp 5/r32/ebp
    35849     5d/pop-to-ebp
    35850     c3/return
    35851
    35852 find-matching-primitive:  # primitives: (addr primitive), stmt: (addr stmt) -> result/eax: (addr primitive)
    35853     # . prologue
    35854     55/push-ebp
    35855     89/<- %ebp 4/r32/esp
    35856     # . save registers
    35857     51/push-ecx
    35858     # var curr/ecx: (addr primitive) = primitives
    35859     8b/-> *(ebp+8) 1/r32/ecx
    35860     {
    35861 $find-matching-primitive:loop:
    35862       # if (curr == null) break
    35863       81 7/subop/compare %ecx 0/imm32
    35864       74/jump-if-= break/disp8
    35865       # if match(curr, stmt) return curr
    35866       {
    35867         (mu-stmt-matches-primitive? *(ebp+0xc) %ecx)  # => eax
    35868         3d/compare-eax-and 0/imm32/false
    35869         74/jump-if-= break/disp8
    35870         89/<- %eax 1/r32/ecx
    35871         eb/jump $find-matching-primitive:end/disp8
    35872       }
    35873 $find-matching-primitive:next-primitive:
    35874       # curr = curr->next
    35875       (lookup *(ecx+0x3c) *(ecx+0x40))  # Primitive-next Primitive-next => eax
    35876       89/<- %ecx 0/r32/eax
    35877       #
    35878       e9/jump loop/disp32
    35879     }
    35880     # return null
    35881     b8/copy-to-eax 0/imm32
    35882 $find-matching-primitive:end:
    35883     # . restore registers
    35884     59/pop-to-ecx
    35885     # . epilogue
    35886     89/<- %esp 5/r32/ebp
    35887     5d/pop-to-ebp
    35888     c3/return
    35889
    35890 mu-stmt-matches-primitive?:  # stmt: (addr stmt), primitive: (addr primitive) -> result/eax: boolean
    35891     # A mu stmt matches a primitive if the name matches, all the inout vars
    35892     # match, and all the output vars match.
    35893     # Vars match if types match and registers match.
    35894     # In addition, a stmt output matches a primitive's output if types match
    35895     # and the primitive has a wildcard register.
    35896     # . prologue
    35897     55/push-ebp
    35898     89/<- %ebp 4/r32/esp
    35899     # . save registers
    35900     51/push-ecx
    35901     52/push-edx
    35902     53/push-ebx
    35903     56/push-esi
    35904     57/push-edi
    35905     # ecx = stmt
    35906     8b/-> *(ebp+8) 1/r32/ecx
    35907     # edx = primitive
    35908     8b/-> *(ebp+0xc) 2/r32/edx
    35909     {
    35910 $mu-stmt-matches-primitive?:check-name:
    35911       # if (primitive->name != stmt->operation) return false
    35912       # . var esi: (addr array byte) = lookup(stmt->operation)
    35913       (lookup *(ecx+4) *(ecx+8))  # Stmt1-operation Stmt1-operation => eax
    35914       89/<- %esi 0/r32/eax
    35915       # . var edi: (addr array byte) = lookup(primitive->name)
    35916       (lookup *edx *(edx+4))  # Primitive-name Primitive-name => eax
    35917 #?       (write-buffered Stderr %eax)
    35918 #?       (write-buffered Stderr Newline)
    35919 #?       (flush Stderr)
    35920       89/<- %edi 0/r32/eax
    35921       (string-equal? %esi %edi)  # => eax
    35922       3d/compare-eax-and 0/imm32/false
    35923       75/jump-if-!= break/disp8
    35924       b8/copy-to-eax 0/imm32
    35925       e9/jump $mu-stmt-matches-primitive?:end/disp32
    35926     }
    35927     # var curr/esi: (addr stmt-var) = lookup(stmt->inouts)
    35928     (lookup *(ecx+0xc) *(ecx+0x10))  # Stmt1-inouts Stmt1-inouts => eax
    35929     89/<- %esi 0/r32/eax
    35930     # var curr2/edi: (addr list var) = lookup(primitive->inouts)
    35931     (lookup *(edx+8) *(edx+0xc))  # Primitive-inouts Primitive-inouts => eax
    35932     89/<- %edi 0/r32/eax
    35933     {
    35934 $mu-stmt-matches-primitive?:inouts-loop:
    35935       # if (curr == 0 && curr2 == 0) move on to check outputs
    35936       {
    35937 $mu-stmt-matches-primitive?:check-both-inouts-null:
    35938         81 7/subop/compare %esi 0/imm32
    35939         75/jump-if-!= break/disp8
    35940 $mu-stmt-matches-primitive?:stmt-inout-null:
    35941         81 7/subop/compare %edi 0/imm32
    35942         0f 84/jump-if-= $mu-stmt-matches-primitive?:check-outputs/disp32
    35943 $mu-stmt-matches-primitive?:stmt-inout-null-and-prim-inout-not-null:
    35944         # return false
    35945         b8/copy-to-eax 0/imm32/false
    35946         e9/jump $mu-stmt-matches-primitive?:end/disp32
    35947       }
    35948       # if (curr2 == 0) return false
    35949       {
    35950 $mu-stmt-matches-primitive?:check-prim-inout-null:
    35951         81 7/subop/compare %edi 0/imm32
    35952         75/jump-if-!= break/disp8
    35953 $mu-stmt-matches-primitive?:prim-inout-null:
    35954         b8/copy-to-eax 0/imm32/false
    35955         e9/jump $mu-stmt-matches-primitive?:end/disp32
    35956       }
    35957       # if (curr != curr2) return false
    35958       {
    35959 $mu-stmt-matches-primitive?:check-inouts-match:
    35960         (lookup *edi *(edi+4))  # List-value List-value => eax
    35961         (operand-matches-primitive? %esi %eax)  # => eax
    35962         3d/compare-eax-and 0/imm32/false
    35963         75/jump-if-!= break/disp8
    35964 $mu-stmt-matches-primitive?:inouts-match:
    35965         b8/copy-to-eax 0/imm32/false
    35966         e9/jump $mu-stmt-matches-primitive?:end/disp32
    35967       }
    35968 $mu-stmt-matches-primitive?:next-inout:
    35969       # curr = lookup(curr->next)
    35970       (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
    35971       89/<- %esi 0/r32/eax
    35972       # curr2 = lookup(curr2->next)
    35973       (lookup *(edi+8) *(edi+0xc))  # List-next List-next => eax
    35974       89/<- %edi 0/r32/eax
    35975       #
    35976       e9/jump loop/disp32
    35977     }
    35978 $mu-stmt-matches-primitive?:check-outputs:
    35979     # var curr/esi: (addr stmt-var) = lookup(stmt->outputs)
    35980     (lookup *(ecx+0x14) *(ecx+0x18))  # Stmt1-outputs Stmt1-outputs => eax
    35981     89/<- %esi 0/r32/eax
    35982     # var curr2/edi: (addr list var) = lookup(primitive->outputs)
    35983     (lookup *(edx+0x10) *(edx+0x14))  # Primitive-outputs Primitive-outputs => eax
    35984     89/<- %edi 0/r32/eax
    35985     {
    35986 $mu-stmt-matches-primitive?:outputs-loop:
    35987       # if (curr == 0) return (curr2 == 0)
    35988       {
    35989 $mu-stmt-matches-primitive?:check-both-outputs-null:
    35990         81 7/subop/compare %esi 0/imm32
    35991         75/jump-if-!= break/disp8
    35992         {
    35993 $mu-stmt-matches-primitive?:stmt-output-null:
    35994           81 7/subop/compare %edi 0/imm32
    35995           75/jump-if-!= break/disp8
    35996 $mu-stmt-matches-primitive?:both-outputs-null:
    35997           # return true
    35998           b8/copy-to-eax 1/imm32
    35999           e9/jump $mu-stmt-matches-primitive?:end/disp32
    36000         }
    36001 $mu-stmt-matches-primitive?:stmt-output-null-and-prim-output-not-null:
    36002         # return false
    36003         b8/copy-to-eax 0/imm32
    36004         e9/jump $mu-stmt-matches-primitive?:end/disp32
    36005       }
    36006       # if (curr2 == 0) return false
    36007       {
    36008 $mu-stmt-matches-primitive?:check-prim-output-null:
    36009         81 7/subop/compare %edi 0/imm32
    36010         75/jump-if-!= break/disp8
    36011 $mu-stmt-matches-primitive?:prim-output-is-null:
    36012         b8/copy-to-eax 0/imm32
    36013         e9/jump $mu-stmt-matches-primitive?:end/disp32
    36014       }
    36015       # if (curr != curr2) return false
    36016       {
    36017 $mu-stmt-matches-primitive?:check-outputs-match:
    36018         (lookup *edi *(edi+4))  # List-value List-value => eax
    36019         (operand-matches-primitive? %esi %eax)  # => eax
    36020         3d/compare-eax-and 0/imm32/false
    36021         75/jump-if-!= break/disp8
    36022 $mu-stmt-matches-primitive?:outputs-match:
    36023         b8/copy-to-eax 0/imm32
    36024         e9/jump $mu-stmt-matches-primitive?:end/disp32
    36025       }
    36026 $mu-stmt-matches-primitive?:next-output:
    36027       # curr = lookup(curr->next)
    36028       (lookup *(esi+8) *(esi+0xc))  # Stmt-var-next Stmt-var-next => eax
    36029       89/<- %esi 0/r32/eax
    36030       # curr2 = lookup(curr2->next)
    36031       (lookup *(edi+8) *(edi+0xc))  # List-next List-next => eax
    36032       89/<- %edi 0/r32/eax
    36033       #
    36034       e9/jump loop/disp32
    36035     }
    36036 $mu-stmt-matches-primitive?:return-true:
    36037     b8/copy-to-eax 1/imm32
    36038 $mu-stmt-matches-primitive?:end:
    36039     # . restore registers
    36040     5f/pop-to-edi
    36041     5e/pop-to-esi
    36042     5b/pop-to-ebx
    36043     5a/pop-to-edx
    36044     59/pop-to-ecx
    36045     # . epilogue
    36046     89/<- %esp 5/r32/ebp
    36047     5d/pop-to-ebp
    36048     c3/return
    36049
    36050 operand-matches-primitive?:  # s: (addr stmt-var), prim-var: (addr var) -> result/eax: boolean
    36051     # . prologue
    36052     55/push-ebp
    36053     89/<- %ebp 4/r32/esp
    36054     # . save registers
    36055     51/push-ecx
    36056     52/push-edx
    36057     53/push-ebx
    36058     56/push-esi
    36059     57/push-edi
    36060     # ecx = s
    36061     8b/-> *(ebp+8) 1/r32/ecx
    36062     # var var/esi: (addr var) = lookup(s->value)
    36063     (lookup *ecx *(ecx+4))  # Stmt-var-value Stmt-var-value => eax
    36064     89/<- %esi 0/r32/eax
    36065     # edi = prim-var
    36066     8b/-> *(ebp+0xc) 7/r32/edi
    36067 $operand-matches-primitive?:check-type:
    36068     # if !category-match?(var->type, prim-var->type) return false
    36069     # . var vtype/ebx: (addr type-tree) = lookup(var->type)
    36070     (lookup *(esi+8) *(esi+0xc))  # Var-type Var-type => eax
    36071     89/<- %ebx 0/r32/eax
    36072     # . if s is deref, vtype = vtype->right
    36073     {
    36074       81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
    36075       74/jump-if-= break/disp8
    36076 $operand-matches-primitive?:is-deref:
    36077       # . var t/eax: (addr type)
    36078       (lookup *(ebx+0xc) *(ebx+0x10))  # Type-tree-right Type-tree-right => eax
    36079       # . if !t->is-atom? t = t->left
    36080       81 7/subop/compare *eax 0/imm32/false
    36081       {
    36082         75/jump-if-!= break/disp8
    36083         (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    36084       }
    36085       # .
    36086       89/<- %ebx 0/r32/eax
    36087     }
    36088     # . var ptype/eax: (addr type-tree) = lookup(prim-var->type)
    36089     (lookup *(edi+8) *(edi+0xc))  # Var-type Var-type => eax
    36090     (subx-type-category-match? %ebx %eax)  # => eax
    36091     3d/compare-eax-and 0/imm32/false
    36092     0f 84/jump-if-= $operand-matches-primitive?:return-false/disp32
    36093     {
    36094 $operand-matches-primitive?:check-register:
    36095       # if prim-var is in memory and var is in register but dereference, match
    36096       {
    36097         81 7/subop/compare *(edi+0x18) 0/imm32  # Var-register
    36098         0f 85/jump-if-!= break/disp32
    36099         81 7/subop/compare *(esi+0x18) 0/imm32  # Var-register
    36100         74/jump-if-= break/disp8
    36101         81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
    36102         74/jump-if-= break/disp8
    36103 $operand-matches-primitive?:var-deref-match:
    36104         e9/jump $operand-matches-primitive?:return-true/disp32
    36105       }
    36106       # if prim-var is in register and var is in register but dereference, no match
    36107       {
    36108         81 7/subop/compare *(edi+0x18) 0/imm32  # Var-register
    36109         0f 84/jump-if-= break/disp32
    36110         81 7/subop/compare *(esi+0x18) 0/imm32  # Var-register
    36111         0f 84/jump-if-= break/disp32
    36112         81 7/subop/compare *(ecx+0x10) 0/imm32/false  # Stmt-var-is-deref
    36113         74/jump-if-= break/disp8
    36114 $operand-matches-primitive?:var-deref-no-match:
    36115         e9/jump $operand-matches-primitive?:return-false/disp32
    36116       }
    36117       # return false if var->register doesn't match prim-var->register
    36118       {
    36119         # if register addresses are equal, it's a match
    36120         # var vreg/ebx: (addr array byte) = lookup(var->register)
    36121         (lookup *(esi+0x18) *(esi+0x1c))  # Var-register Var-register => eax
    36122         89/<- %ebx 0/r32/eax
    36123         # var preg/ecx: (addr array byte) = lookup(prim-var->register)
    36124         (lookup *(edi+0x18) *(edi+0x1c))  # Var-register Var-register => eax
    36125         89/<- %ecx 0/r32/eax
    36126         # if (vreg == preg) break
    36127         39/compare %ecx 3/r32/ebx
    36128         74/jump-if-= break/disp8
    36129 $operand-matches-primitive?:var-register-no-match:
    36130         # if either address is 0, return false
    36131         81 7/subop/compare %ebx 0/imm32
    36132         74/jump-if-=  $operand-matches-primitive?:return-false/disp8
    36133         81 7/subop/compare %ecx 0/imm32
    36134         74/jump-if-=  $operand-matches-primitive?:return-false/disp8
    36135         # if prim-var->register is wildcard, it's a match
    36136         (string-equal? %ecx "*")  # Any-register => eax
    36137         3d/compare-eax-and 0/imm32/false
    36138         75/jump-if-!= break/disp8
    36139 $operand-matches-primitive?:wildcard-no-match:
    36140         # if string contents aren't equal, return false
    36141         (string-equal? %ecx %ebx)  # => eax
    36142         3d/compare-eax-and 0/imm32/false
    36143         74/jump-if-= $operand-matches-primitive?:return-false/disp8
    36144       }
    36145     }
    36146 $operand-matches-primitive?:return-true:
    36147     b8/copy-to-eax 1/imm32/true
    36148     eb/jump $operand-matches-primitive?:end/disp8
    36149 $operand-matches-primitive?:return-false:
    36150     b8/copy-to-eax 0/imm32/false
    36151 $operand-matches-primitive?:end:
    36152     # . restore registers
    36153     5f/pop-to-edi
    36154     5e/pop-to-esi
    36155     5b/pop-to-ebx
    36156     5a/pop-to-edx
    36157     59/pop-to-ecx
    36158     # . epilogue
    36159     89/<- %esp 5/r32/ebp
    36160     5d/pop-to-ebp
    36161     c3/return
    36162
    36163 find-matching-function:  # functions: (addr function), stmt: (addr stmt) -> result/eax: (addr function)
    36164     # . prologue
    36165     55/push-ebp
    36166     89/<- %ebp 4/r32/esp
    36167     # . save registers
    36168     51/push-ecx
    36169     # var curr/ecx: (handle function) = functions
    36170     8b/-> *(ebp+8) 1/r32/ecx
    36171     {
    36172       # if (curr == null) break
    36173       81 7/subop/compare %ecx 0/imm32
    36174       74/jump-if-= break/disp8
    36175 #?       (write-buffered Stderr "iter\n")
    36176 #?       (flush Stderr)
    36177       # if match(stmt, curr) return curr
    36178       {
    36179         (mu-stmt-matches-function? *(ebp+0xc) %ecx)  # => eax
    36180         3d/compare-eax-and 0/imm32/false
    36181         74/jump-if-= break/disp8
    36182         89/<- %eax 1/r32/ecx
    36183         eb/jump $find-matching-function:end/disp8
    36184       }
    36185       # curr = curr->next
    36186       (lookup *(ecx+0x20) *(ecx+0x24))  # Function-next Function-next => eax
    36187       89/<- %ecx 0/r32/eax
    36188       #
    36189       eb/jump loop/disp8
    36190     }
    36191     # return null
    36192     b8/copy-to-eax 0/imm32
    36193 $find-matching-function:end:
    36194     # . restore registers
    36195     59/pop-to-ecx
    36196     # . epilogue
    36197     89/<- %esp 5/r32/ebp
    36198     5d/pop-to-ebp
    36199     c3/return
    36200
    36201 # Just compare names; user-defined functions don't support overloading yet.
    36202 mu-stmt-matches-function?:  # stmt: (addr stmt1), function: (addr function) -> result/eax: boolean
    36203     # . prologue
    36204     55/push-ebp
    36205     89/<- %ebp 4/r32/esp
    36206     # . save registers
    36207     51/push-ecx
    36208     # return function->name == stmt->operation
    36209     # ecx = lookup(stmt->operation)
    36210     8b/-> *(ebp+8) 0/r32/eax
    36211     (lookup *(eax+4) *(eax+8))  # Stmt1-operation Stmt1-operation => eax
    36212     89/<- %ecx 0/r32/eax
    36213     # eax = lookup(function->name)
    36214     8b/-> *(ebp+0xc) 0/r32/eax
    36215     (lookup *eax *(eax+4))  # Function-name Function-name => eax
    36216     (string-equal? %eax %ecx)  # => eax
    36217 $mu-stmt-matches-function?:end:
    36218     # . restore registers
    36219     59/pop-to-ecx
    36220     # . epilogue
    36221     89/<- %esp 5/r32/ebp
    36222     5d/pop-to-ebp
    36223     c3/return
    36224
    36225 # Type-checking happens elsewhere. This method is for selecting between
    36226 # primitives.
    36227 subx-type-category-match?:  # a: (addr type-tree), b: (addr type-tree) -> result/eax: boolean
    36228     # . prologue
    36229     55/push-ebp
    36230     89/<- %ebp 4/r32/esp
    36231     # . save registers
    36232     51/push-ecx
    36233     # var cata/ecx: int = type-category(a)
    36234     (type-category *(ebp+8))  # => eax
    36235     89/<- %ecx 0/r32/eax
    36236     # var catb/eax: int = type-category(b)
    36237     (type-category *(ebp+0xc))  # => eax
    36238     # return cata == catb
    36239     39/compare %eax 1/r32/ecx
    36240     0f 94/set-byte-if-= %al
    36241     25/and-eax-with 0xff/imm32
    36242 $subx-type-category-match?:end:
    36243     # . restore registers
    36244     59/pop-to-ecx
    36245     # . epilogue
    36246     89/<- %esp 5/r32/ebp
    36247     5d/pop-to-ebp
    36248     c3/return
    36249
    36250 type-category:  # a: (addr type-tree) -> result/eax: int
    36251     # . prologue
    36252     55/push-ebp
    36253     89/<- %ebp 4/r32/esp
    36254     # . save registers
    36255     51/push-ecx
    36256     # var lit?/ecx: boolean = literal-type?(a)
    36257     (simple-mu-type? *(ebp+8) 0)  # literal => eax
    36258     89/<- %ecx 0/r32/eax
    36259     # var float?/eax: int = float?(a)
    36260     (simple-mu-type? *(ebp+8) 0xf)  # => eax
    36261     # set bits for lit? and float?
    36262     c1/shift 4/subop/left %ecx 1/imm8
    36263     09/or %eax 1/r32/ecx
    36264 $type-category:end:
    36265     # . restore registers
    36266     59/pop-to-ecx
    36267     # . epilogue
    36268     89/<- %esp 5/r32/ebp
    36269     5d/pop-to-ebp
    36270     c3/return
    36271
    36272 simple-mu-type?:  # a: (addr type-tree), n: type-id -> result/eax: boolean
    36273     # . prologue
    36274     55/push-ebp
    36275     89/<- %ebp 4/r32/esp
    36276     # . save registers
    36277     51/push-ecx
    36278     # ecx = n
    36279     8b/-> *(ebp+0xc) 1/r32/ecx
    36280     # return (a->value == n)
    36281     8b/-> *(ebp+8) 0/r32/eax
    36282     39/compare *(eax+4) 1/r32/ecx  # Type-tree-value
    36283     0f 94/set-byte-if-= %al
    36284     25/and-eax-with 0xff/imm32
    36285 $simple-mu-type?:end:
    36286     # . restore registers
    36287     59/pop-to-ecx
    36288     # . epilogue
    36289     89/<- %esp 5/r32/ebp
    36290     5d/pop-to-ebp
    36291     c3/return
    36292
    36293 mu-addr-type?:  # a: (addr type-tree) -> result/eax: boolean
    36294     # . prologue
    36295     55/push-ebp
    36296     89/<- %ebp 4/r32/esp
    36297     # eax = a
    36298     8b/-> *(ebp+8) 0/r32/eax
    36299     # if (!a->is-atom?) a = a->left
    36300     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
    36301     {
    36302       75/jump-if-!= break/disp8
    36303       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    36304     }
    36305     # return (a->value == addr)
    36306     81 7/subop/compare *(eax+4) 2/imm32/addr  # Type-tree-value
    36307     0f 94/set-byte-if-= %al
    36308     25/and-eax-with 0xff/imm32
    36309 $mu-addr-type?:end:
    36310     # . epilogue
    36311     89/<- %esp 5/r32/ebp
    36312     5d/pop-to-ebp
    36313     c3/return
    36314
    36315 mu-array-type?:  # a: (addr type-tree) -> result/eax: boolean
    36316     # . prologue
    36317     55/push-ebp
    36318     89/<- %ebp 4/r32/esp
    36319     # eax = a
    36320     8b/-> *(ebp+8) 0/r32/eax
    36321     # if (!a->is-atom?) a = a->left
    36322     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
    36323     {
    36324       75/jump-if-!= break/disp8
    36325       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    36326     }
    36327     # return (a->value == array)
    36328     81 7/subop/compare *(eax+4) 3/imm32/array  # Type-tree-value
    36329     0f 94/set-byte-if-= %al
    36330     25/and-eax-with 0xff/imm32
    36331 $mu-array-type?:end:
    36332     # . epilogue
    36333     89/<- %esp 5/r32/ebp
    36334     5d/pop-to-ebp
    36335     c3/return
    36336
    36337 mu-string-type?:  # a: (addr type-tree) -> result/eax: boolean
    36338     # . prologue
    36339     55/push-ebp
    36340     89/<- %ebp 4/r32/esp
    36341     # . save registers
    36342     56/push-esi
    36343     # esi = a
    36344     8b/-> *(ebp+8) 6/r32/esi
    36345     # if (a->is-atom?) return false
    36346     81 7/subop/compare *esi 0/imm32/false  # Type-tree-is-atom
    36347     0f 85/jump-if-!= $mu-string-type?:return-false/disp32
    36348     # if a is not an addr, return false
    36349     (mu-addr-type? %esi)  # => eax
    36350     3d/compare-eax-with 0/imm32/false
    36351     0f 84/jump-if-= $mu-string-type?:end/disp32  # eax changes var
    36352     # if a is not an array, return false
    36353     (lookup *(esi+0xc) *(esi+0x10))  # Type-tree-right Type-tree-right => eax
    36354     (mu-array-type? %eax)  # => eax
    36355     3d/compare-eax-with 0/imm32/false
    36356     74/jump-if-= $mu-string-type?:end/disp8  # eax changes var
    36357     # var p/eax: (addr type-tree) = payload of a
    36358     (lookup *(esi+0xc) *(esi+0x10))  # Type-tree-right Type-tree-right => eax
    36359     (lookup *(eax+0xc) *(eax+0x10))  # Type-tree-right Type-tree-right => eax
    36360     # if p is an atom, return false
    36361     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
    36362     75/jump-if-!= $mu-string-type?:return-false/disp8
    36363     # return (p == byte)
    36364     (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    36365     (simple-mu-type? %eax 8)  # byte => eax
    36366     eb/jump $mu-string-type?:end/disp8
    36367 $mu-string-type?:return-false:
    36368     b8/copy-to-eax 0/imm32/false
    36369 $mu-string-type?:end:
    36370     # . restore registers
    36371     5e/pop-to-esi
    36372     # . epilogue
    36373     89/<- %esp 5/r32/ebp
    36374     5d/pop-to-ebp
    36375     c3/return
    36376
    36377 mu-stream-type?:  # a: (addr type-tree) -> result/eax: boolean
    36378     # . prologue
    36379     55/push-ebp
    36380     89/<- %ebp 4/r32/esp
    36381     # eax = a
    36382     8b/-> *(ebp+8) 0/r32/eax
    36383     # if (!a->is-atom?) a = a->left
    36384     81 7/subop/compare *eax 0/imm32/false  # Type-tree-is-atom
    36385     {
    36386       75/jump-if-!= break/disp8
    36387       (lookup *(eax+4) *(eax+8))  # Type-tree-left Type-tree-left => eax
    36388     }
    36389     # return (a->value == stream)
    36390     81 7/subop/compare *(eax+4) 0xb/imm32/stream  # Type-tree-value
    36391     0f 94/set-byte-if-= %al
    36392     25/and-eax-with 0xff/imm32
    36393 $mu-stream-type?:end:
    36394     # . epilogue
    36395     89/<- %esp 5/r32/ebp
    36396     5d/pop-to-ebp
    36397     c3/return
    36398
    36399 test-emit-subx-stmt-primitive:
    36400     # Primitive operation on a variable on the stack.
    36401     #   increment foo
    36402     # =>
    36403     #   ff 0/subop/increment *(ebp-8)
    36404     #
    36405     # There's a variable on the var stack as follows:
    36406     #   name: 'foo'
    36407     #   type: int
    36408     #   stack-offset: -8
    36409     #
    36410     # There's a primitive with this info:
    36411     #   name: 'increment'
    36412     #   inouts: int/mem
    36413     #   value: 'ff 0/subop/increment'
    36414     #
    36415     # . prologue
    36416     55/push-ebp
    36417     89/<- %ebp 4/r32/esp
    36418     # setup
    36419     (clear-stream _test-output-stream)
    36420     (clear-stream $_test-output-buffered-file->buffer)
    36421     # simulate allocated payloads starting with an initial fake alloc-id (0x11)
    36422 $test-emit-subx-stmt-primitive:initialize-type:
    36423     # var type/ecx: (payload type-tree) = int
    36424     68/push 0/imm32/right:null
    36425     68/push 0/imm32/right:null
    36426     68/push 0/imm32/left:unused
    36427     68/push 1/imm32/value:int
    36428     68/push 1/imm32/is-atom?:true
    36429     68/push 0x11/imm32/alloc-id:fake:payload
    36430     89/<- %ecx 4/r32/esp
    36431 $test-emit-subx-stmt-primitive:initialize-var:
    36432     # var var-foo/ecx: (payload var) = var(type)
    36433     68/push 0/imm32/no-register
    36434     68/push 0/imm32/no-register
    36435     68/push -8/imm32/stack-offset
    36436     68/push 1/imm32/block-depth
    36437     51/push-ecx/type
    36438     68/push 0x11/imm32/alloc-id:fake
    36439     68/push 0/imm32/name
    36440     68/push 0/imm32/name
    36441     68/push 0x11/imm32/alloc-id:fake:payload
    36442     89/<- %ecx 4/r32/esp
    36443 $test-emit-subx-stmt-primitive:initialize-var-name:
    36444     # var-foo->name = "foo"
    36445     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
    36446     (copy-array Heap "foo" %eax)
    36447 $test-emit-subx-stmt-primitive:initialize-stmt-var:
    36448     # var operand/ebx: (payload stmt-var) = stmt-var(var-foo)
    36449     68/push 0/imm32/is-deref:false
    36450     68/push 0/imm32/next
    36451     68/push 0/imm32/next
    36452     51/push-ecx/var-foo
    36453     68/push 0x11/imm32/alloc-id:fake
    36454     68/push 0x11/imm32/alloc-id:fake:payload
    36455     89/<- %ebx 4/r32/esp
    36456 $test-emit-subx-stmt-primitive:initialize-stmt:
    36457     # var stmt/esi: (addr statement)
    36458     68/push 0/imm32/no-outputs
    36459     68/push 0/imm32/no-outputs
    36460     53/push-ebx/inouts
    36461     68/push 0x11/imm32/alloc-id:fake
    36462     68/push 0/imm32/operation
    36463     68/push 0/imm32/operation
    36464     68/push 1/imm32/tag
    36465     89/<- %esi 4/r32/esp
    36466 $test-emit-subx-stmt-primitive:initialize-stmt-operation:
    36467     # stmt->operation = "increment"
    36468     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
    36469     (copy-array Heap "increment" %eax)
    36470 $test-emit-subx-stmt-primitive:initialize-primitive:
    36471     # var primitives/ebx: (addr primitive)
    36472     68/push 0/imm32/next
    36473     68/push 0/imm32/next
    36474     68/push 0/imm32/no-x32
    36475     68/push 0/imm32/no-xm32
    36476     68/push 0/imm32/no-disp32
    36477     68/push 0/imm32/no-imm8
    36478     68/push 0/imm32/no-imm32
    36479     68/push 0/imm32/no-r32
    36480     68/push 1/imm32/rm32-is-first-inout
    36481     68/push 0/imm32/subx-name
    36482     68/push 0/imm32/subx-name
    36483     68/push 0/imm32/no-outputs
    36484     68/push 0/imm32/no-outputs
    36485     53/push-ebx/inouts  # hack: reuse stmt-var from call stmt as (list var) in function declaration
    36486     68/push 0x11/imm32/alloc-id:fake
    36487     68/push 0/imm32/name
    36488     68/push 0/imm32/name
    36489     89/<- %ebx 4/r32/esp
    36490 $test-emit-subx-stmt-primitive:initialize-primitive-name:
    36491     # primitives->name = "increment"
    36492     (copy-array Heap "increment" %ebx)  # Primitive-name
    36493 $test-emit-subx-stmt-primitive:initialize-primitive-subx-name:
    36494     # primitives->subx-name = "ff 0/subop/increment"
    36495     8d/copy-address *(ebx+0x18) 0/r32/eax  # Primitive-subx-name
    36496     (copy-array Heap "ff 0/subop/increment" %eax)
    36497     # convert
    36498     c7 0/subop/copy *Curr-block-depth 0/imm32
    36499     (emit-subx-stmt _test-output-buffered-file %esi %ebx 0 Stderr 0)
    36500     (flush _test-output-buffered-file)
    36501 +--  6 lines: #?     # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------
    36507     # check output
    36508     (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment *(ebp+0xfffffff8)" "F - test-emit-subx-stmt-primitive")
    36509     # . epilogue
    36510     89/<- %esp 5/r32/ebp
    36511     5d/pop-to-ebp
    36512     c3/return
    36513
    36514 test-emit-subx-stmt-primitive-register:
    36515     # Primitive operation on a variable in a register.
    36516     #   foo <- increment
    36517     # =>
    36518     #   ff 0/subop/increment %eax  # sub-optimal, but should suffice
    36519     #
    36520     # There's a variable on the var stack as follows:
    36521     #   name: 'foo'
    36522     #   type: int
    36523     #   register: 'eax'
    36524     #
    36525     # There's a primitive with this info:
    36526     #   name: 'increment'
    36527     #   out: int/reg
    36528     #   value: 'ff 0/subop/increment'
    36529     #
    36530     # . prologue
    36531     55/push-ebp
    36532     89/<- %ebp 4/r32/esp
    36533     # setup
    36534     (clear-stream _test-output-stream)
    36535     (clear-stream $_test-output-buffered-file->buffer)
    36536 $test-emit-subx-stmt-primitive-register:initialize-type:
    36537     # var type/ecx: (payload type-tree) = int
    36538     68/push 0/imm32/right:null
    36539     68/push 0/imm32/right:null
    36540     68/push 0/imm32/left:unused
    36541     68/push 1/imm32/value:int
    36542     68/push 1/imm32/is-atom?:true
    36543     68/push 0x11/imm32/alloc-id:fake:payload
    36544     89/<- %ecx 4/r32/esp
    36545 $test-emit-subx-stmt-primitive-register:initialize-var:
    36546     # var var-foo/ecx: (payload var)
    36547     68/push 0/imm32/register
    36548     68/push 0/imm32/register
    36549     68/push 0/imm32/no-stack-offset
    36550     68/push 1/imm32/block-depth
    36551     51/push-ecx
    36552     68/push 0x11/imm32/alloc-id:fake
    36553     68/push 0/imm32/name
    36554     68/push 0/imm32/name
    36555     68/push 0x11/imm32/alloc-id:fake:payload
    36556     89/<- %ecx 4/r32/esp
    36557 $test-emit-subx-stmt-primitive-register:initialize-var-name:
    36558     # var-foo->name = "foo"
    36559     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
    36560     (copy-array Heap "foo" %eax)
    36561 $test-emit-subx-stmt-primitive-register:initialize-var-register:
    36562     # var-foo->register = "eax"
    36563     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
    36564     (copy-array Heap "eax" %eax)
    36565 $test-emit-subx-stmt-primitive-register:initialize-stmt-var:
    36566     # var operand/ebx: (payload stmt-var)
    36567     68/push 0/imm32/is-deref:false
    36568     68/push 0/imm32/next
    36569     68/push 0/imm32/next
    36570     51/push-ecx/var-foo
    36571     68/push 0x11/imm32/alloc-id:fake
    36572     68/push 0x11/imm32/alloc-id:fake:payload
    36573     89/<- %ebx 4/r32/esp
    36574 $test-emit-subx-stmt-primitive-register:initialize-stmt:
    36575     # var stmt/esi: (addr statement)
    36576     53/push-ebx/outputs
    36577     68/push 0x11/imm32/alloc-id:fake
    36578     68/push 0/imm32/no-inouts
    36579     68/push 0/imm32/no-inouts
    36580     68/push 0/imm32/operation
    36581     68/push 0/imm32/operation
    36582     68/push 1/imm32
    36583     89/<- %esi 4/r32/esp
    36584 $test-emit-subx-stmt-primitive-register:initialize-stmt-operation:
    36585     # stmt->operation = "increment"
    36586     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
    36587     (copy-array Heap "increment" %eax)
    36588 $test-emit-subx-stmt-primitive-register:initialize-formal-var:
    36589     # var formal-var/ebx: (payload var)
    36590     68/push 0/imm32/register
    36591     68/push 0/imm32/register
    36592     68/push 0/imm32/no-stack-offset
    36593     68/push 1/imm32/block-depth
    36594     ff 6/subop/push *(ecx+0x10)  # Var-type + payload alloc id + handle alloc id
    36595     68/push 0x11/imm32/alloc-id:fake
    36596     68/push 0/imm32/name
    36597     68/push 0/imm32/name
    36598     68/push 0x11/imm32/alloc-id:fake:payload
    36599     89/<- %ebx 4/r32/esp
    36600 $test-emit-subx-stmt-primitive-register:initialize-formal-var-name:
    36601     # formal-var->name = "dummy"
    36602     8d/copy-address *(ebx+4) 0/r32/eax  # Var-name + 4
    36603     (copy-array Heap "dummy" %eax)
    36604 $test-emit-subx-stmt-primitive-register:initialize-formal-register:
    36605     # formal-var->register = "*"
    36606     8d/copy-address *(ebx+0x1c) 0/r32/eax  # Var-register + 4
    36607     (copy-array Heap "*" %eax)  # Any-register
    36608 $test-emit-subx-stmt-primitive-register:initialize-var-list:
    36609     # var formal-outputs/ebx: (payload list var)
    36610     68/push 0/imm32/next
    36611     68/push 0/imm32/next
    36612     53/push-ebx/formal-var
    36613     68/push 0x11/imm32/alloc-id:fake
    36614     68/push 0x11/imm32/alloc-id:fake:payload
    36615     89/<- %ebx 4/r32/esp
    36616 $test-emit-subx-stmt-primitive-register:initialize-primitive:
    36617     # var primitives/ebx: (addr primitive)
    36618     68/push 0/imm32/next
    36619     68/push 0/imm32/next
    36620     68/push 0/imm32/no-x32
    36621     68/push 0/imm32/no-xm32
    36622     68/push 0/imm32/no-disp32
    36623     68/push 0/imm32/no-imm8
    36624     68/push 0/imm32/no-imm32
    36625     68/push 0/imm32/no-r32
    36626     68/push 3/imm32/rm32-is-first-output
    36627     68/push 0/imm32/subx-name
    36628     68/push 0/imm32/subx-name
    36629     53/push-ebx/outputs
    36630     68/push 0x11/imm32/alloc-id:fake
    36631     68/push 0/imm32/no-inouts
    36632     68/push 0/imm32/no-inouts
    36633     68/push 0/imm32/name
    36634     68/push 0/imm32/name
    36635     89/<- %ebx 4/r32/esp
    36636 $test-emit-subx-stmt-primitive-register:initialize-primitive-name:
    36637     # primitives->name = "increment"
    36638     (copy-array Heap "increment" %ebx)  # Primitive-name
    36639 $test-emit-subx-stmt-primitive-register:initialize-primitive-subx-name:
    36640     # primitives->subx-name = "ff 0/subop/increment"
    36641     8d/copy-address *(ebx+0x18) 0/r32/eax  # Primitive-subx-name
    36642     (copy-array Heap "ff 0/subop/increment" %eax)
    36643     # convert
    36644     c7 0/subop/copy *Curr-block-depth 0/imm32
    36645     (emit-subx-stmt _test-output-buffered-file %esi %ebx 0 Stderr 0)
    36646     (flush _test-output-buffered-file)
    36647 +--  6 lines: #?     # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------
    36653     # check output
    36654     (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-stmt-primitive-register")
    36655     # . epilogue
    36656     89/<- %esp 5/r32/ebp
    36657     5d/pop-to-ebp
    36658     c3/return
    36659
    36660 test-emit-subx-stmt-select-primitive:
    36661     # Select the right primitive between overloads.
    36662     #   foo <- increment
    36663     # =>
    36664     #   ff 0/subop/increment %eax  # sub-optimal, but should suffice
    36665     #
    36666     # There's a variable on the var stack as follows:
    36667     #   name: 'foo'
    36668     #   type: int
    36669     #   register: 'eax'
    36670     #
    36671     # There's two primitives, as follows:
    36672     #   - name: 'increment'
    36673     #     out: int/reg
    36674     #     value: 'ff 0/subop/increment'
    36675     #   - name: 'increment'
    36676     #     inout: int/mem
    36677     #     value: 'ff 0/subop/increment'
    36678     #
    36679     # . prologue
    36680     55/push-ebp
    36681     89/<- %ebp 4/r32/esp
    36682     # setup
    36683     (clear-stream _test-output-stream)
    36684     (clear-stream $_test-output-buffered-file->buffer)
    36685 $test-emit-subx-stmt-select-primitive:initialize-type:
    36686     # var type/ecx: (payload type-tree) = int
    36687     68/push 0/imm32/right:null
    36688     68/push 0/imm32/right:null
    36689     68/push 0/imm32/left:unused
    36690     68/push 1/imm32/value:int
    36691     68/push 1/imm32/is-atom?:true
    36692     68/push 0x11/imm32/alloc-id:fake:payload
    36693     89/<- %ecx 4/r32/esp
    36694 $test-emit-subx-stmt-select-primitive:initialize-var:
    36695     # var var-foo/ecx: (payload var)
    36696     68/push 0/imm32/register
    36697     68/push 0/imm32/register
    36698     68/push 0/imm32/no-stack-offset
    36699     68/push 1/imm32/block-depth
    36700     51/push-ecx
    36701     68/push 0x11/imm32/alloc-id:fake
    36702     68/push 0/imm32/name
    36703     68/push 0/imm32/name
    36704     68/push 0x11/imm32/alloc-id:fake:payload
    36705     89/<- %ecx 4/r32/esp
    36706 $test-emit-subx-stmt-select-primitive:initialize-var-name:
    36707     # var-foo->name = "foo"
    36708     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
    36709     (copy-array Heap "foo" %eax)
    36710 $test-emit-subx-stmt-select-primitive:initialize-var-register:
    36711     # var-foo->register = "eax"
    36712     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
    36713     (copy-array Heap "eax" %eax)
    36714 $test-emit-subx-stmt-select-primitive:initialize-stmt-var:
    36715     # var operand/ebx: (payload stmt-var)
    36716     68/push 0/imm32/is-deref:false
    36717     68/push 0/imm32/next
    36718     68/push 0/imm32/next
    36719     51/push-ecx/var-foo
    36720     68/push 0x11/imm32/alloc-id:fake
    36721     68/push 0x11/imm32/alloc-id:fake:payload
    36722     89/<- %ebx 4/r32/esp
    36723 $test-emit-subx-stmt-select-primitive:initialize-stmt:
    36724     # var stmt/esi: (addr statement)
    36725     53/push-ebx/outputs
    36726     68/push 0x11/imm32/alloc-id:fake
    36727     68/push 0/imm32/no-inouts
    36728     68/push 0/imm32/no-inouts
    36729     68/push 0/imm32/operation
    36730     68/push 0/imm32/operation
    36731     68/push 1/imm32
    36732     89/<- %esi 4/r32/esp
    36733 $test-emit-subx-stmt-select-primitive:initialize-stmt-operation:
    36734     # stmt->operation = "increment"
    36735     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
    36736     (copy-array Heap "increment" %eax)
    36737 $test-emit-subx-stmt-select-primitive:initialize-formal-var:
    36738     # var formal-var/ebx: (payload var)
    36739     68/push 0/imm32/register
    36740     68/push 0/imm32/register
    36741     68/push 0/imm32/no-stack-offset
    36742     68/push 1/imm32/block-depth
    36743     ff 6/subop/push *(ecx+0x10)  # Var-type + payload alloc id + handle alloc id
    36744     68/push 0x11/imm32/alloc-id:fake
    36745     68/push 0/imm32/name
    36746     68/push 0/imm32/name
    36747     68/push 0x11/imm32/alloc-id:fake:payload
    36748     89/<- %ebx 4/r32/esp
    36749 $test-emit-subx-stmt-select-primitive:initialize-formal-var-name:
    36750     # formal-var->name = "dummy"
    36751     8d/copy-address *(ebx+4) 0/r32/eax  # Var-name + 4
    36752     (copy-array Heap "dummy" %eax)
    36753 $test-emit-subx-stmt-select-primitive:initialize-formal-register:
    36754     # formal-var->register = "*"
    36755     8d/copy-address *(ebx+0x1c) 0/r32/eax  # Var-register + 4
    36756     (copy-array Heap "*" %eax)  # Any-register
    36757 $test-emit-subx-stmt-select-primitive:initialize-var-list:
    36758     # var formal-outputs/ebx: (payload list var)
    36759     68/push 0/imm32/next
    36760     68/push 0/imm32/next
    36761     53/push-ebx/formal-var
    36762     68/push 0x11/imm32/alloc-id:fake
    36763     68/push 0x11/imm32/alloc-id:fake:payload
    36764     89/<- %ebx 4/r32/esp
    36765 $test-emit-subx-stmt-select-primitive:initialize-primitive2:
    36766     # var primitive2/edi: (payload primitive)
    36767     68/push 0/imm32/next
    36768     68/push 0/imm32/next
    36769     68/push 0/imm32/no-x32
    36770     68/push 0/imm32/no-xm32
    36771     68/push 0/imm32/no-disp32
    36772     68/push 0/imm32/no-imm8
    36773     68/push 0/imm32/no-imm32
    36774     68/push 0/imm32/no-r32
    36775     68/push 3/imm32/rm32-is-first-output
    36776     68/push 0/imm32/subx-name
    36777     68/push 0/imm32/subx-name
    36778     53/push-ebx/outputs
    36779     68/push 0x11/imm32/alloc-id:fake
    36780     68/push 0/imm32/no-inouts
    36781     68/push 0/imm32/no-inouts
    36782     68/push 0/imm32/name
    36783     68/push 0/imm32/name
    36784     68/push 0x11/imm32/alloc-id:fake:payload
    36785     89/<- %edi 4/r32/esp
    36786 $test-emit-subx-stmt-select-primitive:initialize-primitive2-name:
    36787     # primitives->name = "increment"
    36788     8d/copy-address *(edi+4) 0/r32/eax  # Primitive-name + 4
    36789     (copy-array Heap "increment" %eax)
    36790 $test-emit-subx-stmt-select-primitive:initialize-primitive2-subx-name:
    36791     # primitives->subx-name = "ff 0/subop/increment"
    36792     8d/copy-address *(edi+0x1c) 0/r32/eax  # Primitive-subx-name + 4
    36793     (copy-array Heap "ff 0/subop/increment" %eax)
    36794 $test-emit-subx-stmt-select-primitive:initialize-primitive:
    36795     # var primitives/ebx: (addr primitive)
    36796     57/push-edi
    36797     68/push 0x11/imm32/alloc-id:fake
    36798     68/push 0/imm32/no-x32
    36799     68/push 0/imm32/no-xm32
    36800     68/push 0/imm32/no-disp32
    36801     68/push 0/imm32/no-imm8
    36802     68/push 0/imm32/no-imm32
    36803     68/push 0/imm32/no-r32
    36804     68/push 1/imm32/rm32-is-first-inout
    36805     68/push 0/imm32/subx-name
    36806     68/push 0/imm32/subx-name
    36807     68/push 0/imm32/no-outputs
    36808     68/push 0/imm32/no-outputs
    36809     53/push-ebx/inouts  # hack: reuse stmt-var from call stmt as (list var) in function declaration
    36810     68/push 0x11/imm32/alloc-id:fake
    36811     68/push 0/imm32/name
    36812     68/push 0/imm32/name
    36813     89/<- %ebx 4/r32/esp
    36814 $test-emit-subx-stmt-select-primitive:initialize-primitive-name:
    36815     # primitives->name = "increment"
    36816     (copy-array Heap "increment" %ebx)  # Primitive-name
    36817 $test-emit-subx-stmt-select-primitive:initialize-primitive-subx-name:
    36818     # primitives->subx-name = "ff 0/subop/increment"
    36819     8d/copy-address *(ebx+0x18) 0/r32/eax  # Primitive-subx-name
    36820     (copy-array Heap "ff 0/subop/increment" %eax)
    36821     # convert
    36822     c7 0/subop/copy *Curr-block-depth 0/imm32
    36823     (emit-subx-stmt _test-output-buffered-file %esi %ebx 0 Stderr 0)
    36824     (flush _test-output-buffered-file)
    36825 +--  6 lines: #?     # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------
    36831     # check output
    36832     (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-stmt-select-primitive")
    36833     # . epilogue
    36834     89/<- %esp 5/r32/ebp
    36835     5d/pop-to-ebp
    36836     c3/return
    36837
    36838 test-emit-subx-stmt-select-primitive-2:
    36839     # Select the right primitive between overloads.
    36840     #   increment foo
    36841     # =>
    36842     #   ff 0/subop/increment %eax  # sub-optimal, but should suffice
    36843     #
    36844     # There's a variable on the var stack as follows:
    36845     #   name: 'foo'
    36846     #   type: int
    36847     #   register: 'eax'
    36848     #
    36849     # There's two primitives, as follows:
    36850     #   - name: 'increment'
    36851     #     out: int/reg
    36852     #     value: 'ff 0/subop/increment'
    36853     #   - name: 'increment'
    36854     #     inout: int/mem
    36855     #     value: 'ff 0/subop/increment'
    36856     #
    36857     # . prologue
    36858     55/push-ebp
    36859     89/<- %ebp 4/r32/esp
    36860     # setup
    36861     (clear-stream _test-output-stream)
    36862     (clear-stream $_test-output-buffered-file->buffer)
    36863 $test-emit-subx-stmt-select-primitive-2:initialize-type:
    36864     # var type/ecx: (payload type-tree) = int
    36865     68/push 0/imm32/right:null
    36866     68/push 0/imm32/right:null
    36867     68/push 0/imm32/left:unused
    36868     68/push 1/imm32/value:int
    36869     68/push 1/imm32/is-atom?:true
    36870     68/push 0x11/imm32/alloc-id:fake:payload
    36871     89/<- %ecx 4/r32/esp
    36872 $test-emit-subx-stmt-select-primitive-2:initialize-var:
    36873     # var var-foo/ecx: (payload var)
    36874     68/push 0/imm32/register
    36875     68/push 0/imm32/register
    36876     68/push 0/imm32/no-stack-offset
    36877     68/push 1/imm32/block-depth
    36878     51/push-ecx
    36879     68/push 0x11/imm32/alloc-id:fake
    36880     68/push 0/imm32/name
    36881     68/push 0/imm32/name
    36882     68/push 0x11/imm32/alloc-id:fake:payload
    36883     89/<- %ecx 4/r32/esp
    36884 $test-emit-subx-stmt-select-primitive-2:initialize-var-name:
    36885     # var-foo->name = "foo"
    36886     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
    36887     (copy-array Heap "foo" %eax)
    36888 $test-emit-subx-stmt-select-primitive-2:initialize-var-register:
    36889     # var-foo->register = "eax"
    36890     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
    36891     (copy-array Heap "eax" %eax)
    36892 $test-emit-subx-stmt-select-primitive-2:initialize-stmt-var:
    36893     # var operand/ebx: (payload stmt-var)
    36894     68/push 0/imm32/is-deref:false
    36895     68/push 0/imm32/next
    36896     68/push 0/imm32/next
    36897     51/push-ecx/var-foo
    36898     68/push 0x11/imm32/alloc-id:fake
    36899     68/push 0x11/imm32/alloc-id:fake:payload
    36900     89/<- %ebx 4/r32/esp
    36901 $test-emit-subx-stmt-select-primitive-2:initialize-stmt:
    36902     # var stmt/esi: (addr statement)
    36903     68/push 0/imm32/no-outputs
    36904     68/push 0/imm32/no-outputs
    36905     53/push-ebx/inouts
    36906     68/push 0x11/imm32/alloc-id:fake
    36907     68/push 0/imm32/operation
    36908     68/push 0/imm32/operation
    36909     68/push 1/imm32
    36910     89/<- %esi 4/r32/esp
    36911 $test-emit-subx-stmt-select-primitive-2:initialize-stmt-operation:
    36912     # stmt->operation = "increment"
    36913     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
    36914     (copy-array Heap "increment" %eax)
    36915 $test-emit-subx-stmt-select-primitive-2:initialize-formal-var:
    36916     # var formal-var/ebx: (payload var)
    36917     68/push 0/imm32/register
    36918     68/push 0/imm32/register
    36919     68/push 0/imm32/no-stack-offset
    36920     68/push 1/imm32/block-depth
    36921     ff 6/subop/push *(ecx+0x10)  # Var-type + payload alloc id + handle alloc id
    36922     68/push 0x11/imm32/alloc-id:fake
    36923     68/push 0/imm32/name
    36924     68/push 0/imm32/name
    36925     68/push 0x11/imm32/alloc-id:fake:payload
    36926     89/<- %ebx 4/r32/esp
    36927 $test-emit-subx-stmt-select-primitive-2:initialize-formal-var-name:
    36928     # formal-var->name = "dummy"
    36929     8d/copy-address *(ebx+4) 0/r32/eax  # Var-name + 4
    36930     (copy-array Heap "dummy" %eax)
    36931 $test-emit-subx-stmt-select-primitive-2:initialize-formal-register:
    36932     # formal-var->register = "*"
    36933     8d/copy-address *(ebx+0x1c) 0/r32/eax  # Var-register + 4
    36934     (copy-array Heap "*" %eax)  # Any-register
    36935 $test-emit-subx-stmt-select-primitive-2:initialize-var-list:
    36936     # var formal-outputs/ebx: (payload list stmt-var)
    36937     68/push 0/imm32/next
    36938     68/push 0/imm32/next
    36939     53/push-ebx/formal-var
    36940     68/push 0x11/imm32/alloc-id:fake
    36941     68/push 0x11/imm32/alloc-id:fake:payload
    36942     89/<- %ebx 4/r32/esp
    36943 $test-emit-subx-stmt-select-primitive-2:initialize-primitive2:
    36944     # var primitive2/edi: (payload primitive)
    36945     68/push 0/imm32/next
    36946     68/push 0/imm32/next
    36947     68/push 0/imm32/no-x32
    36948     68/push 0/imm32/no-xm32
    36949     68/push 0/imm32/no-disp32
    36950     68/push 0/imm32/no-imm8
    36951     68/push 0/imm32/no-imm32
    36952     68/push 0/imm32/no-r32
    36953     68/push 3/imm32/rm32-is-first-output
    36954     68/push 0/imm32/subx-name
    36955     68/push 0/imm32/subx-name
    36956     53/push-ebx/outputs
    36957     68/push 0x11/imm32/alloc-id:fake
    36958     68/push 0/imm32/no-inouts
    36959     68/push 0/imm32/no-inouts
    36960     68/push 0/imm32/name
    36961     68/push 0/imm32/name
    36962     68/push 0x11/imm32/alloc-id:fake:payload
    36963     89/<- %edi 4/r32/esp
    36964 $test-emit-subx-stmt-select-primitive-2:initialize-primitive2-name:
    36965     # primitives->name = "increment"
    36966     8d/copy-address *(edi+4) 0/r32/eax  # Primitive-name + 4
    36967     (copy-array Heap "increment" %eax)
    36968 $test-emit-subx-stmt-select-primitive-2:initialize-primitive2-subx-name:
    36969     # primitives->subx-name = "ff 0/subop/increment"
    36970     8d/copy-address *(edi+0x1c) 0/r32/eax  # Primitive-subx-name + 4
    36971     (copy-array Heap "ff 0/subop/increment" %eax)
    36972 $test-emit-subx-stmt-select-primitive-2:initialize-primitive:
    36973     # var primitives/ebx: (addr primitive)
    36974     57/push-edi
    36975     68/push 0x11/imm32/alloc-id:fake
    36976     68/push 0/imm32/no-x32
    36977     68/push 0/imm32/no-xm32
    36978     68/push 0/imm32/no-disp32
    36979     68/push 0/imm32/no-imm8
    36980     68/push 0/imm32/no-imm32
    36981     68/push 0/imm32/no-r32
    36982     68/push 1/imm32/rm32-is-first-inout
    36983     68/push 0/imm32/subx-name
    36984     68/push 0/imm32/subx-name
    36985     68/push 0/imm32/no-outputs
    36986     68/push 0/imm32/no-outputs
    36987     53/push-ebx/inouts  # hack: reuse stmt-var from call stmt as (list var) in function declaration
    36988     68/push 0x11/imm32/alloc-id:fake
    36989     68/push 0/imm32/name
    36990     68/push 0/imm32/name
    36991     89/<- %ebx 4/r32/esp
    36992 $test-emit-subx-stmt-select-primitive-2:initialize-primitive-name:
    36993     # primitives->name = "increment"
    36994     (copy-array Heap "increment" %ebx)  # Primitive-name
    36995 $test-emit-subx-stmt-select-primitive-2:initialize-primitive-subx-name:
    36996     # primitives->subx-name = "ff 0/subop/increment"
    36997     8d/copy-address *(ebx+0x18) 0/r32/eax  # Primitive-subx-name
    36998     (copy-array Heap "ff 0/subop/increment" %eax)
    36999     # convert
    37000     c7 0/subop/copy *Curr-block-depth 0/imm32
    37001     (emit-subx-stmt _test-output-buffered-file %esi %ebx 0 Stderr 0)
    37002     (flush _test-output-buffered-file)
    37003 +--  6 lines: #?     # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------
    37009     # check output
    37010     (check-next-stream-line-equal _test-output-stream "ff 0/subop/increment %eax" "F - test-emit-subx-stmt-select-primitive-2")
    37011     # . epilogue
    37012     89/<- %esp 5/r32/ebp
    37013     5d/pop-to-ebp
    37014     c3/return
    37015
    37016 test-increment-register:
    37017     # Select the right register between overloads.
    37018     #   foo <- increment
    37019     # =>
    37020     #   50/increment-eax
    37021     #
    37022     # There's a variable on the var stack as follows:
    37023     #   name: 'foo'
    37024     #   type: int
    37025     #   register: 'eax'
    37026     #
    37027     # Primitives are the global definitions.
    37028     #
    37029     # . prologue
    37030     55/push-ebp
    37031     89/<- %ebp 4/r32/esp
    37032     # setup
    37033     (clear-stream _test-output-stream)
    37034     (clear-stream $_test-output-buffered-file->buffer)
    37035 $test-increment-register:initialize-type:
    37036     # var type/ecx: (payload type-tree) = int
    37037     68/push 0/imm32/right:null
    37038     68/push 0/imm32/right:null
    37039     68/push 0/imm32/left:unused
    37040     68/push 1/imm32/value:int
    37041     68/push 1/imm32/is-atom?:true
    37042     68/push 0x11/imm32/alloc-id:fake:payload
    37043     89/<- %ecx 4/r32/esp
    37044 $test-increment-register:initialize-var:
    37045     # var var-foo/ecx: (payload var)
    37046     68/push 0/imm32/register
    37047     68/push 0/imm32/register
    37048     68/push 0/imm32/no-stack-offset
    37049     68/push 1/imm32/block-depth
    37050     51/push-ecx
    37051     68/push 0x11/imm32/alloc-id:fake
    37052     68/push 0/imm32/name
    37053     68/push 0/imm32/name
    37054     68/push 0x11/imm32/alloc-id:fake:payload
    37055     89/<- %ecx 4/r32/esp
    37056 $test-increment-register:initialize-var-name:
    37057     # var-foo->name = "foo"
    37058     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
    37059     (copy-array Heap "foo" %eax)
    37060 $test-increment-register:initialize-var-register:
    37061     # var-foo->register = "eax"
    37062     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
    37063     (copy-array Heap "eax" %eax)
    37064 $test-increment-register:initialize-stmt-var:
    37065     # var operand/ebx: (payload stmt-var)
    37066     68/push 0/imm32/is-deref:false
    37067     68/push 0/imm32/next
    37068     68/push 0/imm32/next
    37069     51/push-ecx/var-foo
    37070     68/push 0x11/imm32/alloc-id:fake
    37071     68/push 0x11/imm32/alloc-id:fake:payload
    37072     89/<- %ebx 4/r32/esp
    37073 $test-increment-register:initialize-stmt:
    37074     # var stmt/esi: (addr statement)
    37075     53/push-ebx/outputs
    37076     68/push 0x11/imm32/alloc-id:fake
    37077     68/push 0/imm32/no-inouts
    37078     68/push 0/imm32/no-inouts
    37079     68/push 0/imm32/operation
    37080     68/push 0/imm32/operation
    37081     68/push 1/imm32
    37082     89/<- %esi 4/r32/esp
    37083 $test-increment-register:initialize-stmt-operation:
    37084     # stmt->operation = "increment"
    37085     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
    37086     (copy-array Heap "increment" %eax)
    37087     # convert
    37088     c7 0/subop/copy *Curr-block-depth 0/imm32
    37089     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
    37090     (flush _test-output-buffered-file)
    37091 +--  6 lines: #?     # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------
    37097     # check output
    37098     (check-next-stream-line-equal _test-output-stream "40/increment-eax" "F - test-increment-register")
    37099     # . epilogue
    37100     89/<- %esp 5/r32/ebp
    37101     5d/pop-to-ebp
    37102     c3/return
    37103
    37104 test-add-reg-to-reg:
    37105     #   var1/reg <- add var2/reg
    37106     # =>
    37107     #   01/add-to %var1 var2
    37108     #
    37109     # . prologue
    37110     55/push-ebp
    37111     89/<- %ebp 4/r32/esp
    37112     # setup
    37113     (clear-stream _test-output-stream)
    37114     (clear-stream $_test-output-buffered-file->buffer)
    37115 $test-add-reg-to-reg:initialize-type:
    37116     # var type/ecx: (payload type-tree) = int
    37117     68/push 0/imm32/right:null
    37118     68/push 0/imm32/right:null
    37119     68/push 0/imm32/left:unused
    37120     68/push 1/imm32/value:int
    37121     68/push 1/imm32/is-atom?:true
    37122     68/push 0x11/imm32/alloc-id:fake:payload
    37123     89/<- %ecx 4/r32/esp
    37124 $test-add-reg-to-reg:initialize-var1:
    37125     # var var1/ecx: (payload var)
    37126     68/push 0/imm32/register
    37127     68/push 0/imm32/register
    37128     68/push 0/imm32/no-stack-offset
    37129     68/push 1/imm32/block-depth
    37130     51/push-ecx
    37131     68/push 0x11/imm32/alloc-id:fake
    37132     68/push 0/imm32/name
    37133     68/push 0/imm32/name
    37134     68/push 0x11/imm32/alloc-id:fake:payload
    37135     89/<- %ecx 4/r32/esp
    37136 $test-add-reg-to-reg:initialize-var1-name:
    37137     # var1->name = "var1"
    37138     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
    37139     (copy-array Heap "var1" %eax)
    37140 $test-add-reg-to-reg:initialize-var1-register:
    37141     # var1->register = "eax"
    37142     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
    37143     (copy-array Heap "eax" %eax)
    37144 $test-add-reg-to-reg:initialize-var2:
    37145     # var var2/edx: (payload var)
    37146     68/push 0/imm32/register
    37147     68/push 0/imm32/register
    37148     68/push 0/imm32/no-stack-offset
    37149     68/push 1/imm32/block-depth
    37150     ff 6/subop/push *(ecx+0x10)
    37151     68/push 0x11/imm32/alloc-id:fake
    37152     68/push 0/imm32/name
    37153     68/push 0/imm32/name
    37154     68/push 0x11/imm32/alloc-id:fake:payload
    37155     89/<- %edx 4/r32/esp
    37156 $test-add-reg-to-reg:initialize-var2-name:
    37157     # var2->name = "var2"
    37158     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
    37159     (copy-array Heap "var2" %eax)
    37160 $test-add-reg-to-reg:initialize-var2-register:
    37161     # var2->register = "ecx"
    37162     8d/copy-address *(edx+0x1c) 0/r32/eax  # Var-register + 4
    37163     (copy-array Heap "ecx" %eax)
    37164 $test-add-reg-to-reg:initialize-inouts:
    37165     # var inouts/esi: (payload stmt-var) = [var2]
    37166     68/push 0/imm32/is-deref:false
    37167     68/push 0/imm32/next
    37168     68/push 0/imm32/next
    37169     52/push-edx/var2
    37170     68/push 0x11/imm32/alloc-id:fake
    37171     68/push 0x11/imm32/alloc-id:fake:payload
    37172     89/<- %esi 4/r32/esp
    37173 $test-add-reg-to-reg:initialize-outputs:
    37174     # var outputs/edi: (payload stmt-var) = [var1]
    37175     68/push 0/imm32/is-deref:false
    37176     68/push 0/imm32/next
    37177     68/push 0/imm32/next
    37178     51/push-ecx/var1
    37179     68/push 0x11/imm32/alloc-id:fake
    37180     68/push 0x11/imm32/alloc-id:fake:payload
    37181     89/<- %edi 4/r32/esp
    37182 $test-add-reg-to-reg:initialize-stmt:
    37183     # var stmt/esi: (addr statement)
    37184     68/push 0/imm32/next
    37185     68/push 0/imm32/next
    37186     57/push-edi/outputs
    37187     68/push 0x11/imm32/alloc-id:fake
    37188     56/push-esi/inouts
    37189     68/push 0x11/imm32/alloc-id:fake
    37190     68/push 0/imm32/operation
    37191     68/push 0/imm32/operation
    37192     68/push 1/imm32/tag:stmt1
    37193     89/<- %esi 4/r32/esp
    37194 $test-add-reg-to-reg:initialize-stmt-operation:
    37195     # stmt->operation = "add"
    37196     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
    37197     (copy-array Heap "add" %eax)
    37198     # convert
    37199     c7 0/subop/copy *Curr-block-depth 0/imm32
    37200     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
    37201     (flush _test-output-buffered-file)
    37202 +--  6 lines: #?     # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------
    37208     # check output
    37209     (check-next-stream-line-equal _test-output-stream "01/add-to %eax 0x00000001/r32" "F - test-add-reg-to-reg")
    37210     # . epilogue
    37211     89/<- %esp 5/r32/ebp
    37212     5d/pop-to-ebp
    37213     c3/return
    37214
    37215 test-add-reg-to-mem:
    37216     #   add-to var1 var2/reg
    37217     # =>
    37218     #   01/add-to *(ebp+__) var2
    37219     #
    37220     # . prologue
    37221     55/push-ebp
    37222     89/<- %ebp 4/r32/esp
    37223     # setup
    37224     (clear-stream _test-output-stream)
    37225     (clear-stream $_test-output-buffered-file->buffer)
    37226 $test-add-reg-to-mem:initialize-type:
    37227     # var type/ecx: (payload type-tree) = int
    37228     68/push 0/imm32/right:null
    37229     68/push 0/imm32/right:null
    37230     68/push 0/imm32/left:unused
    37231     68/push 1/imm32/value:int
    37232     68/push 1/imm32/is-atom?:true
    37233     68/push 0x11/imm32/alloc-id:fake:payload
    37234     89/<- %ecx 4/r32/esp
    37235 $test-add-reg-to-mem:initialize-var1:
    37236     # var var1/ecx: (payload var)
    37237     68/push 0/imm32/register
    37238     68/push 0/imm32/register
    37239     68/push 8/imm32/stack-offset
    37240     68/push 1/imm32/block-depth
    37241     51/push-ecx
    37242     68/push 0x11/imm32/alloc-id:fake
    37243     68/push 0/imm32/name
    37244     68/push 0/imm32/name
    37245     68/push 0x11/imm32/alloc-id:fake:payload
    37246     89/<- %ecx 4/r32/esp
    37247 $test-add-reg-to-mem:initialize-var1-name:
    37248     # var1->name = "var1"
    37249     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
    37250     (copy-array Heap "var1" %eax)
    37251 $test-add-reg-to-mem:initialize-var2:
    37252     # var var2/edx: (payload var)
    37253     68/push 0/imm32/register
    37254     68/push 0/imm32/register
    37255     68/push 0/imm32/no-stack-offset
    37256     68/push 1/imm32/block-depth
    37257     ff 6/subop/push *(ecx+0x10)
    37258     68/push 0x11/imm32/alloc-id:fake
    37259     68/push 0/imm32/name
    37260     68/push 0/imm32/name
    37261     68/push 0x11/imm32/alloc-id:fake:payload
    37262     89/<- %edx 4/r32/esp
    37263 $test-add-reg-to-mem:initialize-var2-name:
    37264     # var2->name = "var2"
    37265     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
    37266     (copy-array Heap "var2" %eax)
    37267 $test-add-reg-to-mem:initialize-var2-register:
    37268     # var2->register = "ecx"
    37269     8d/copy-address *(edx+0x1c) 0/r32/eax  # Var-register + 4
    37270     (copy-array Heap "ecx" %eax)
    37271 $test-add-reg-to-mem:initialize-inouts:
    37272     # var inouts/esi: (payload stmt-var) = [var2]
    37273     68/push 0/imm32/is-deref:false
    37274     68/push 0/imm32/next
    37275     68/push 0/imm32/next
    37276     52/push-edx/var2
    37277     68/push 0x11/imm32/alloc-id:fake
    37278     68/push 0x11/imm32/alloc-id:fake:payload
    37279     89/<- %esi 4/r32/esp
    37280     # inouts = [var1, var2]
    37281     68/push 0/imm32/is-deref:false
    37282     56/push-esi/next
    37283     68/push 0x11/imm32/alloc-id:fake
    37284     51/push-ecx/var1
    37285     68/push 0x11/imm32/alloc-id:fake
    37286     68/push 0x11/imm32/alloc-id:fake:payload
    37287     89/<- %esi 4/r32/esp
    37288 $test-add-reg-to-mem:initialize-stmt:
    37289     # var stmt/esi: (addr statement)
    37290     68/push 0/imm32/next
    37291     68/push 0/imm32/next
    37292     68/push 0/imm32/outputs
    37293     68/push 0/imm32/outputs
    37294     56/push-esi/inouts
    37295     68/push 0x11/imm32/alloc-id:fake
    37296     68/push 0/imm32/operation
    37297     68/push 0/imm32/operation
    37298     68/push 1/imm32/tag:stmt1
    37299     89/<- %esi 4/r32/esp
    37300 $test-add-reg-to-mem:initialize-stmt-operation:
    37301     # stmt->operation = "add-to"
    37302     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
    37303     (copy-array Heap "add-to" %eax)
    37304     # convert
    37305     c7 0/subop/copy *Curr-block-depth 0/imm32
    37306     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
    37307     (flush _test-output-buffered-file)
    37308 +--  6 lines: #?     # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------
    37314     # check output
    37315     (check-next-stream-line-equal _test-output-stream "01/add-to *(ebp+0x00000008) 0x00000001/r32" "F - test-add-reg-to-mem")
    37316     # . epilogue
    37317     89/<- %esp 5/r32/ebp
    37318     5d/pop-to-ebp
    37319     c3/return
    37320
    37321 test-add-mem-to-reg:
    37322     #   var1/reg <- add var2
    37323     # =>
    37324     #   03/add *(ebp+__) var1
    37325     #
    37326     # . prologue
    37327     55/push-ebp
    37328     89/<- %ebp 4/r32/esp
    37329     # setup
    37330     (clear-stream _test-output-stream)
    37331     (clear-stream $_test-output-buffered-file->buffer)
    37332 $test-add-mem-to-reg:initialize-type:
    37333     # var type/ecx: (payload type-tree) = int
    37334     68/push 0/imm32/right:null
    37335     68/push 0/imm32/right:null
    37336     68/push 0/imm32/left:unused
    37337     68/push 1/imm32/value:int
    37338     68/push 1/imm32/is-atom?:true
    37339     68/push 0x11/imm32/alloc-id:fake:payload
    37340     89/<- %ecx 4/r32/esp
    37341 $test-add-mem-to-reg:initialize-var:
    37342     # var var1/ecx: (payload var)
    37343     68/push 0/imm32/register
    37344     68/push 0/imm32/register
    37345     68/push 0/imm32/no-stack-offset
    37346     68/push 1/imm32/block-depth
    37347     51/push-ecx
    37348     68/push 0x11/imm32/alloc-id:fake
    37349     68/push 0/imm32/name
    37350     68/push 0/imm32/name
    37351     68/push 0x11/imm32/alloc-id:fake:payload
    37352     89/<- %ecx 4/r32/esp
    37353 $test-add-mem-to-reg:initialize-var-name:
    37354     # var1->name = "foo"
    37355     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
    37356     (copy-array Heap "var1" %eax)
    37357 $test-add-mem-to-reg:initialize-var-register:
    37358     # var1->register = "eax"
    37359     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
    37360     (copy-array Heap "eax" %eax)
    37361 $test-add-mem-to-reg:initialize-var2:
    37362     # var var2/edx: (payload var)
    37363     68/push 0/imm32/register
    37364     68/push 0/imm32/register
    37365     68/push 8/imm32/stack-offset
    37366     68/push 1/imm32/block-depth
    37367     ff 6/subop/push *(ecx+0x10)
    37368     68/push 0x11/imm32/alloc-id:fake
    37369     68/push 0/imm32/name
    37370     68/push 0/imm32/name
    37371     68/push 0x11/imm32/alloc-id:fake:payload
    37372     89/<- %edx 4/r32/esp
    37373 $test-add-mem-to-reg:initialize-var2-name:
    37374     # var2->name = "var2"
    37375     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
    37376     (copy-array Heap "var2" %eax)
    37377 $test-add-mem-to-reg:initialize-inouts:
    37378     # var inouts/esi: (payload stmt-var) = [var2]
    37379     68/push 0/imm32/is-deref:false
    37380     68/push 0/imm32/next
    37381     68/push 0/imm32/next
    37382     52/push-edx/var2
    37383     68/push 0x11/imm32/alloc-id:fake
    37384     68/push 0x11/imm32/alloc-id:fake:payload
    37385     89/<- %esi 4/r32/esp
    37386 $test-add-mem-to-reg:initialize-outputs:
    37387     # var outputs/edi: (payload stmt-var) = [var1]
    37388     68/push 0/imm32/is-deref:false
    37389     68/push 0/imm32/next
    37390     68/push 0/imm32/next
    37391     51/push-ecx/var1
    37392     68/push 0x11/imm32/alloc-id:fake
    37393     68/push 0x11/imm32/alloc-id:fake:payload
    37394     89/<- %edi 4/r32/esp
    37395 $test-add-mem-to-reg:initialize-stmt:
    37396     # var stmt/esi: (addr statement)
    37397     68/push 0/imm32/next
    37398     68/push 0/imm32/next
    37399     57/push-edi/outputs
    37400     68/push 0x11/imm32/alloc-id:fake
    37401     56/push-esi/inouts
    37402     68/push 0x11/imm32/alloc-id:fake
    37403     68/push 0/imm32/operation
    37404     68/push 0/imm32/operation
    37405     68/push 1/imm32/tag:stmt1
    37406     89/<- %esi 4/r32/esp
    37407 $test-add-mem-to-reg:initialize-stmt-operation:
    37408     # stmt->operation = "add"
    37409     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
    37410     (copy-array Heap "add" %eax)
    37411     # convert
    37412     c7 0/subop/copy *Curr-block-depth 0/imm32
    37413     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
    37414     (flush _test-output-buffered-file)
    37415 +--  6 lines: #?     # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------
    37421     # check output
    37422     (check-next-stream-line-equal _test-output-stream "03/add *(ebp+0x00000008) 0x00000000/r32" "F - test-add-mem-to-reg")
    37423     # . epilogue
    37424     89/<- %esp 5/r32/ebp
    37425     5d/pop-to-ebp
    37426     c3/return
    37427
    37428 test-add-literal-to-eax:
    37429     #   var1/eax <- add 0x34
    37430     # =>
    37431     #   05/add-to-eax 0x34/imm32
    37432     #
    37433     # . prologue
    37434     55/push-ebp
    37435     89/<- %ebp 4/r32/esp
    37436     # setup
    37437     (clear-stream _test-output-stream)
    37438     (clear-stream $_test-output-buffered-file->buffer)
    37439 $test-add-literal-to-eax:initialize-var-type:
    37440     # var type/ecx: (payload type-tree) = int
    37441     68/push 0/imm32/right:null
    37442     68/push 0/imm32/right:null
    37443     68/push 0/imm32/left:unused
    37444     68/push 1/imm32/value:int
    37445     68/push 1/imm32/is-atom?:true
    37446     68/push 0x11/imm32/alloc-id:fake:payload
    37447     89/<- %ecx 4/r32/esp
    37448 $test-add-literal-to-eax:initialize-var:
    37449     # var v/ecx: (payload var)
    37450     68/push 0/imm32/register
    37451     68/push 0/imm32/register
    37452     68/push 0/imm32/no-stack-offset
    37453     68/push 1/imm32/block-depth
    37454     51/push-ecx
    37455     68/push 0x11/imm32/alloc-id:fake
    37456     68/push 0/imm32/name
    37457     68/push 0/imm32/name
    37458     68/push 0x11/imm32/alloc-id:fake:payload
    37459     89/<- %ecx 4/r32/esp
    37460 $test-add-literal-to-eax:initialize-var-name:
    37461     # v->name = "v"
    37462     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
    37463     (copy-array Heap "v" %eax)
    37464 $test-add-literal-to-eax:initialize-var-register:
    37465     # v->register = "eax"
    37466     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
    37467     (copy-array Heap "eax" %eax)
    37468 $test-add-literal-to-eax:initialize-literal-type:
    37469     # var type/edx: (payload type-tree) = literal
    37470     68/push 0/imm32/right:null
    37471     68/push 0/imm32/right:null
    37472     68/push 0/imm32/left:unused
    37473     68/push 0/imm32/value:literal
    37474     68/push 1/imm32/is-atom?:true
    37475     68/push 0x11/imm32/alloc-id:fake:payload
    37476     89/<- %edx 4/r32/esp
    37477 $test-add-literal-to-eax:initialize-literal:
    37478     # var l/edx: (payload var)
    37479     68/push 0/imm32/register
    37480     68/push 0/imm32/register
    37481     68/push 0/imm32/no-stack-offset
    37482     68/push 1/imm32/block-depth
    37483     52/push-edx
    37484     68/push 0x11/imm32/alloc-id:fake
    37485     68/push 0/imm32/name
    37486     68/push 0/imm32/name
    37487     68/push 0x11/imm32/alloc-id:fake:payload
    37488     89/<- %edx 4/r32/esp
    37489 $test-add-literal-to-eax:initialize-literal-value:
    37490     # l->name = "0x34"
    37491     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
    37492     (copy-array Heap "0x34" %eax)
    37493 $test-add-literal-to-eax:initialize-inouts:
    37494     # var inouts/esi: (payload stmt-var) = [l]
    37495     68/push 0/imm32/is-deref:false
    37496     68/push 0/imm32/next
    37497     68/push 0/imm32/next
    37498     52/push-edx/l
    37499     68/push 0x11/imm32/alloc-id:fake
    37500     68/push 0x11/imm32/alloc-id:fake:payload
    37501     89/<- %esi 4/r32/esp
    37502 $test-add-literal-to-eax:initialize-outputs:
    37503     # var outputs/edi: (payload stmt-var) = [v]
    37504     68/push 0/imm32/is-deref:false
    37505     68/push 0/imm32/next
    37506     68/push 0/imm32/next
    37507     51/push-ecx/v
    37508     68/push 0x11/imm32/alloc-id:fake
    37509     68/push 0x11/imm32/alloc-id:fake:payload
    37510     89/<- %edi 4/r32/esp
    37511 $test-add-literal-to-eax:initialize-stmt:
    37512     # var stmt/esi: (addr statement)
    37513     68/push 0/imm32/next
    37514     68/push 0/imm32/next
    37515     57/push-edi/outputs
    37516     68/push 0x11/imm32/alloc-id:fake
    37517     56/push-esi/inouts
    37518     68/push 0x11/imm32/alloc-id:fake
    37519     68/push 0/imm32/operation
    37520     68/push 0/imm32/operation
    37521     68/push 1/imm32/tag:stmt1
    37522     89/<- %esi 4/r32/esp
    37523 $test-add-literal-to-eax:initialize-stmt-operation:
    37524     # stmt->operation = "add"
    37525     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
    37526     (copy-array Heap "add" %eax)
    37527     # convert
    37528     c7 0/subop/copy *Curr-block-depth 0/imm32
    37529     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
    37530     (flush _test-output-buffered-file)
    37531 +--  6 lines: #?     # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------
    37537     # check output
    37538     (check-next-stream-line-equal _test-output-stream "05/add-to-eax 0x34/imm32" "F - test-add-literal-to-eax")
    37539     # . epilogue
    37540     89/<- %esp 5/r32/ebp
    37541     5d/pop-to-ebp
    37542     c3/return
    37543
    37544 test-add-literal-to-reg:
    37545     #   var1/ecx <- add 0x34
    37546     # =>
    37547     #   81 0/subop/add %ecx 0x34/imm32
    37548     #
    37549     # . prologue
    37550     55/push-ebp
    37551     89/<- %ebp 4/r32/esp
    37552     # setup
    37553     (clear-stream _test-output-stream)
    37554     (clear-stream $_test-output-buffered-file->buffer)
    37555 $test-add-literal-to-reg:initialize-var-type:
    37556     # var type/ecx: (payload type-tree) = int
    37557     68/push 0/imm32/right:null
    37558     68/push 0/imm32/right:null
    37559     68/push 0/imm32/left:unused
    37560     68/push 1/imm32/value:int
    37561     68/push 1/imm32/is-atom?:true
    37562     68/push 0x11/imm32/alloc-id:fake:payload
    37563     89/<- %ecx 4/r32/esp
    37564 $test-add-literal-to-reg:initialize-var:
    37565     # var v/ecx: (payload var)
    37566     68/push 0/imm32/register
    37567     68/push 0/imm32/register
    37568     68/push 0/imm32/no-stack-offset
    37569     68/push 1/imm32/block-depth
    37570     51/push-ecx
    37571     68/push 0x11/imm32/alloc-id:fake
    37572     68/push 0/imm32/name
    37573     68/push 0/imm32/name
    37574     68/push 0x11/imm32/alloc-id:fake:payload
    37575     89/<- %ecx 4/r32/esp
    37576 $test-add-literal-to-reg:initialize-var-name:
    37577     # v->name = "v"
    37578     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
    37579     (copy-array Heap "v" %eax)
    37580 $test-add-literal-to-reg:initialize-var-register:
    37581     # v->register = "ecx"
    37582     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
    37583     (copy-array Heap "ecx" %eax)
    37584 $test-add-literal-to-reg:initialize-literal-type:
    37585     # var type/edx: (payload type-tree) = literal
    37586     68/push 0/imm32/right:null
    37587     68/push 0/imm32/right:null
    37588     68/push 0/imm32/left:unused
    37589     68/push 0/imm32/value:literal
    37590     68/push 1/imm32/is-atom?:true
    37591     68/push 0x11/imm32/alloc-id:fake:payload
    37592     89/<- %edx 4/r32/esp
    37593 $test-add-literal-to-reg:initialize-literal:
    37594     # var l/edx: (payload var)
    37595     68/push 0/imm32/register
    37596     68/push 0/imm32/register
    37597     68/push 0/imm32/no-stack-offset
    37598     68/push 1/imm32/block-depth
    37599     52/push-edx
    37600     68/push 0x11/imm32/alloc-id:fake
    37601     68/push 0/imm32/name
    37602     68/push 0/imm32/name
    37603     68/push 0x11/imm32/alloc-id:fake:payload
    37604     89/<- %edx 4/r32/esp
    37605 $test-add-literal-to-reg:initialize-literal-value:
    37606     # l->name = "0x34"
    37607     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
    37608     (copy-array Heap "0x34" %eax)
    37609 $test-add-literal-to-reg:initialize-inouts:
    37610     # var inouts/esi: (payload stmt-var) = [l]
    37611     68/push 0/imm32/is-deref:false
    37612     68/push 0/imm32/next
    37613     68/push 0/imm32/next
    37614     52/push-edx/l
    37615     68/push 0x11/imm32/alloc-id:fake
    37616     68/push 0x11/imm32/alloc-id:fake:payload
    37617     89/<- %esi 4/r32/esp
    37618 $test-add-literal-to-reg:initialize-outputs:
    37619     # var outputs/edi: (payload stmt-var) = [v]
    37620     68/push 0/imm32/is-deref:false
    37621     68/push 0/imm32/next
    37622     68/push 0/imm32/next
    37623     51/push-ecx/v
    37624     68/push 0x11/imm32/alloc-id:fake
    37625     68/push 0x11/imm32/alloc-id:fake:payload
    37626     89/<- %edi 4/r32/esp
    37627 $test-add-literal-to-reg:initialize-stmt:
    37628     # var stmt/esi: (addr statement)
    37629     68/push 0/imm32/next
    37630     68/push 0/imm32/next
    37631     57/push-edi/outputs
    37632     68/push 0x11/imm32/alloc-id:fake
    37633     56/push-esi/inouts
    37634     68/push 0x11/imm32/alloc-id:fake
    37635     68/push 0/imm32/operation
    37636     68/push 0/imm32/operation
    37637     68/push 1/imm32/tag:stmt1
    37638     89/<- %esi 4/r32/esp
    37639 $test-add-literal-to-reg:initialize-stmt-operation:
    37640     # stmt->operation = "add"
    37641     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
    37642     (copy-array Heap "add" %eax)
    37643     # convert
    37644     c7 0/subop/copy *Curr-block-depth 0/imm32
    37645     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
    37646     (flush _test-output-buffered-file)
    37647 +--  6 lines: #?     # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------
    37653     # check output
    37654     (check-next-stream-line-equal _test-output-stream "81 0/subop/add %ecx 0x34/imm32" "F - test-add-literal-to-reg")
    37655     # . epilogue
    37656     89/<- %esp 5/r32/ebp
    37657     5d/pop-to-ebp
    37658     c3/return
    37659
    37660 test-add-literal-to-mem:
    37661     #   add-to var1, 0x34
    37662     # =>
    37663     #   81 0/subop/add %eax 0x34/imm32
    37664     #
    37665     # . prologue
    37666     55/push-ebp
    37667     89/<- %ebp 4/r32/esp
    37668     # setup
    37669     (clear-stream _test-output-stream)
    37670     (clear-stream $_test-output-buffered-file->buffer)
    37671 $test-add-literal-to-mem:initialize-type:
    37672     # var type/ecx: (payload type-tree) = int
    37673     68/push 0/imm32/right:null
    37674     68/push 0/imm32/right:null
    37675     68/push 0/imm32/left:unused
    37676     68/push 1/imm32/value:int
    37677     68/push 1/imm32/is-atom?:true
    37678     68/push 0x11/imm32/alloc-id:fake:payload
    37679     89/<- %ecx 4/r32/esp
    37680 $test-add-literal-to-mem:initialize-var1:
    37681     # var var1/ecx: (payload var)
    37682     68/push 0/imm32/register
    37683     68/push 0/imm32/register
    37684     68/push 8/imm32/stack-offset
    37685     68/push 1/imm32/block-depth
    37686     51/push-ecx
    37687     68/push 0x11/imm32/alloc-id:fake
    37688     68/push 0/imm32/name
    37689     68/push 0/imm32/name
    37690     68/push 0x11/imm32/alloc-id:fake:payload
    37691     89/<- %ecx 4/r32/esp
    37692 $test-add-literal-to-mem:initialize-var1-name:
    37693     # var1->name = "var1"
    37694     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
    37695     (copy-array Heap "var1" %eax)
    37696 $test-add-literal-to-mem:initialize-literal-type:
    37697     # var type/edx: (payload type-tree) = literal
    37698     68/push 0/imm32/right:null
    37699     68/push 0/imm32/right:null
    37700     68/push 0/imm32/left:unused
    37701     68/push 0/imm32/value:literal
    37702     68/push 1/imm32/is-atom?:true
    37703     68/push 0x11/imm32/alloc-id:fake:payload
    37704     89/<- %edx 4/r32/esp
    37705 $test-add-literal-to-mem:initialize-literal:
    37706     # var l/edx: (payload var)
    37707     68/push 0/imm32/register
    37708     68/push 0/imm32/register
    37709     68/push 0/imm32/no-stack-offset
    37710     68/push 1/imm32/block-depth
    37711     52/push-edx
    37712     68/push 0x11/imm32/alloc-id:fake
    37713     68/push 0/imm32/name
    37714     68/push 0/imm32/name
    37715     68/push 0x11/imm32/alloc-id:fake:payload
    37716     89/<- %edx 4/r32/esp
    37717 $test-add-literal-to-mem:initialize-literal-value:
    37718     # l->name = "0x34"
    37719     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
    37720     (copy-array Heap "0x34" %eax)
    37721 $test-add-literal-to-mem:initialize-inouts:
    37722     # var inouts/esi: (payload stmt-var) = [l]
    37723     68/push 0/imm32/is-deref:false
    37724     68/push 0/imm32/next
    37725     68/push 0/imm32/next
    37726     52/push-edx/l
    37727     68/push 0x11/imm32/alloc-id:fake
    37728     68/push 0x11/imm32/alloc-id:fake:payload
    37729     89/<- %esi 4/r32/esp
    37730     # var inouts = (handle stmt-var) = [var1, var2]
    37731     68/push 0/imm32/is-deref:false
    37732     56/push-esi/next
    37733     68/push 0x11/imm32/alloc-id:fake
    37734     51/push-ecx/var1
    37735     68/push 0x11/imm32/alloc-id:fake
    37736     68/push 0x11/imm32/alloc-id:fake:payload
    37737     89/<- %esi 4/r32/esp
    37738 $test-add-literal-to-mem:initialize-stmt:
    37739     # var stmt/esi: (addr statement)
    37740     68/push 0/imm32/next
    37741     68/push 0/imm32/next
    37742     68/push 0/imm32/outputs
    37743     68/push 0/imm32/outputs
    37744     56/push-esi/inouts
    37745     68/push 0x11/imm32/alloc-id:fake
    37746     68/push 0/imm32/operation
    37747     68/push 0/imm32/operation
    37748     68/push 1/imm32/tag:stmt1
    37749     89/<- %esi 4/r32/esp
    37750 $test-add-literal-to-mem:initialize-stmt-operation:
    37751     # stmt->operation = "add-to"
    37752     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
    37753     (copy-array Heap "add-to" %eax)
    37754     # convert
    37755     c7 0/subop/copy *Curr-block-depth 0/imm32
    37756     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
    37757     (flush _test-output-buffered-file)
    37758 +--  6 lines: #?     # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------
    37764     # check output
    37765     (check-next-stream-line-equal _test-output-stream "81 0/subop/add *(ebp+0x00000008) 0x34/imm32" "F - test-add-literal-to-mem")
    37766     # . epilogue
    37767     89/<- %esp 5/r32/ebp
    37768     5d/pop-to-ebp
    37769     c3/return
    37770
    37771 test-shift-reg-by-literal:
    37772     #   var1/ecx <- shift-left 2
    37773     # =>
    37774     #   c1/shift 4/subop/left %ecx 2/imm8
    37775     #
    37776     # . prologue
    37777     55/push-ebp
    37778     89/<- %ebp 4/r32/esp
    37779     # setup
    37780     (clear-stream _test-output-stream)
    37781     (clear-stream $_test-output-buffered-file->buffer)
    37782 $test-shift-reg-by-literal:initialize-var-type:
    37783     # var type/ecx: (payload type-tree) = int
    37784     68/push 0/imm32/right:null
    37785     68/push 0/imm32/right:null
    37786     68/push 0/imm32/left:unused
    37787     68/push 1/imm32/value:int
    37788     68/push 1/imm32/is-atom?:true
    37789     68/push 0x11/imm32/alloc-id:fake:payload
    37790     89/<- %ecx 4/r32/esp
    37791 $test-shift-reg-by-literal:initialize-var:
    37792     # var v/ecx: (payload var)
    37793     68/push 0/imm32/register
    37794     68/push 0/imm32/register
    37795     68/push 0/imm32/no-stack-offset
    37796     68/push 1/imm32/block-depth
    37797     51/push-ecx
    37798     68/push 0x11/imm32/alloc-id:fake
    37799     68/push 0/imm32/name
    37800     68/push 0/imm32/name
    37801     68/push 0x11/imm32/alloc-id:fake:payload
    37802     89/<- %ecx 4/r32/esp
    37803 $test-shift-reg-by-literal:initialize-var-name:
    37804     # v->name = "v"
    37805     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
    37806     (copy-array Heap "v" %eax)
    37807 $test-shift-reg-by-literal:initialize-var-register:
    37808     # v->register = "ecx"
    37809     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
    37810     (copy-array Heap "ecx" %eax)
    37811 $test-shift-reg-by-literal:initialize-literal-type:
    37812     # var type/edx: (payload type-tree) = literal
    37813     68/push 0/imm32/right:null
    37814     68/push 0/imm32/right:null
    37815     68/push 0/imm32/left:unused
    37816     68/push 0/imm32/value:literal
    37817     68/push 1/imm32/is-atom?:true
    37818     68/push 0x11/imm32/alloc-id:fake:payload
    37819     89/<- %edx 4/r32/esp
    37820 $test-shift-reg-by-literal:initialize-literal:
    37821     # var l/edx: (payload var)
    37822     68/push 0/imm32/register
    37823     68/push 0/imm32/register
    37824     68/push 0/imm32/no-stack-offset
    37825     68/push 1/imm32/block-depth
    37826     52/push-edx
    37827     68/push 0x11/imm32/alloc-id:fake
    37828     68/push 0/imm32/name
    37829     68/push 0/imm32/name
    37830     68/push 0x11/imm32/alloc-id:fake:payload
    37831     89/<- %edx 4/r32/esp
    37832 $test-shift-reg-by-literal:initialize-literal-value:
    37833     # l->name = "2"
    37834     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
    37835     (copy-array Heap "2" %eax)
    37836 $test-shift-reg-by-literal:initialize-inouts:
    37837     # var inouts/esi: (payload stmt-var) = [l]
    37838     68/push 0/imm32/is-deref:false
    37839     68/push 0/imm32/next
    37840     68/push 0/imm32/next
    37841     52/push-edx/l
    37842     68/push 0x11/imm32/alloc-id:fake
    37843     68/push 0x11/imm32/alloc-id:fake:payload
    37844     89/<- %esi 4/r32/esp
    37845 $test-shift-reg-by-literal:initialize-outputs:
    37846     # var outputs/edi: (payload stmt-var) = [v]
    37847     68/push 0/imm32/is-deref:false
    37848     68/push 0/imm32/next
    37849     68/push 0/imm32/next
    37850     51/push-ecx/v
    37851     68/push 0x11/imm32/alloc-id:fake
    37852     68/push 0x11/imm32/alloc-id:fake:payload
    37853     89/<- %edi 4/r32/esp
    37854 $test-shift-reg-by-literal:initialize-stmt:
    37855     # var stmt/esi: (addr statement)
    37856     68/push 0/imm32/next
    37857     68/push 0/imm32/next
    37858     57/push-edi/outputs
    37859     68/push 0x11/imm32/alloc-id:fake
    37860     56/push-esi/inouts
    37861     68/push 0x11/imm32/alloc-id:fake
    37862     68/push 0/imm32/operation
    37863     68/push 0/imm32/operation
    37864     68/push 1/imm32/tag:stmt1
    37865     89/<- %esi 4/r32/esp
    37866 $test-shift-reg-by-literal:initialize-stmt-operation:
    37867     # stmt->operation = "shift-left"
    37868     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
    37869     (copy-array Heap "shift-left" %eax)
    37870     # convert
    37871     c7 0/subop/copy *Curr-block-depth 0/imm32
    37872     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
    37873     (flush _test-output-buffered-file)
    37874 +--  6 lines: #?     # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------
    37880     # check output
    37881     (check-next-stream-line-equal _test-output-stream "c1/shift 4/subop/left %ecx 2/imm8" "F - test-shift-reg-by-literal")
    37882     # . epilogue
    37883     89/<- %esp 5/r32/ebp
    37884     5d/pop-to-ebp
    37885     c3/return
    37886
    37887 test-shift-mem-by-literal:
    37888     #   shift-left var 3
    37889     # =>
    37890     #   c1/shift 4/subop/left *(ebp+8) 3/imm8
    37891     #
    37892     # . prologue
    37893     55/push-ebp
    37894     89/<- %ebp 4/r32/esp
    37895     # setup
    37896     (clear-stream _test-output-stream)
    37897     (clear-stream $_test-output-buffered-file->buffer)
    37898 $test-shift-mem-by-literal:initialize-type:
    37899     # var type/ecx: (payload type-tree) = int
    37900     68/push 0/imm32/right:null
    37901     68/push 0/imm32/right:null
    37902     68/push 0/imm32/left:unused
    37903     68/push 1/imm32/value:int
    37904     68/push 1/imm32/is-atom?:true
    37905     68/push 0x11/imm32/alloc-id:fake:payload
    37906     89/<- %ecx 4/r32/esp
    37907 $test-shift-mem-by-literal:initialize-var1:
    37908     # var var1/ecx: (payload var)
    37909     68/push 0/imm32/register
    37910     68/push 0/imm32/register
    37911     68/push 8/imm32/stack-offset
    37912     68/push 1/imm32/block-depth
    37913     51/push-ecx
    37914     68/push 0x11/imm32/alloc-id:fake
    37915     68/push 0/imm32/name
    37916     68/push 0/imm32/name
    37917     68/push 0x11/imm32/alloc-id:fake:payload
    37918     89/<- %ecx 4/r32/esp
    37919 $test-shift-mem-by-literal:initialize-var1-name:
    37920     # var1->name = "var1"
    37921     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
    37922     (copy-array Heap "var1" %eax)
    37923 $test-shift-mem-by-literal:initialize-literal-type:
    37924     # var type/edx: (payload type-tree) = literal
    37925     68/push 0/imm32/right:null
    37926     68/push 0/imm32/right:null
    37927     68/push 0/imm32/left:unused
    37928     68/push 0/imm32/value:literal
    37929     68/push 1/imm32/is-atom?:true
    37930     68/push 0x11/imm32/alloc-id:fake:payload
    37931     89/<- %edx 4/r32/esp
    37932 $test-shift-mem-by-literal:initialize-literal:
    37933     # var l/edx: (payload var)
    37934     68/push 0/imm32/register
    37935     68/push 0/imm32/register
    37936     68/push 0/imm32/no-stack-offset
    37937     68/push 1/imm32/block-depth
    37938     52/push-edx
    37939     68/push 0x11/imm32/alloc-id:fake
    37940     68/push 0/imm32/name
    37941     68/push 0/imm32/name
    37942     68/push 0x11/imm32/alloc-id:fake:payload
    37943     89/<- %edx 4/r32/esp
    37944 $test-shift-mem-by-literal:initialize-literal-value:
    37945     # l->name = "3"
    37946     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
    37947     (copy-array Heap "3" %eax)
    37948 $test-shift-mem-by-literal:initialize-inouts:
    37949     # var inouts/esi: (payload stmt-var) = [l]
    37950     68/push 0/imm32/is-deref:false
    37951     68/push 0/imm32/next
    37952     68/push 0/imm32/next
    37953     52/push-edx/l
    37954     68/push 0x11/imm32/alloc-id:fake
    37955     68/push 0x11/imm32/alloc-id:fake:payload
    37956     89/<- %esi 4/r32/esp
    37957     # var inouts = (handle stmt-var) = [var1, var2]
    37958     68/push 0/imm32/is-deref:false
    37959     56/push-esi/next
    37960     68/push 0x11/imm32/alloc-id:fake
    37961     51/push-ecx/var1
    37962     68/push 0x11/imm32/alloc-id:fake
    37963     68/push 0x11/imm32/alloc-id:fake:payload
    37964     89/<- %esi 4/r32/esp
    37965 $test-shift-mem-by-literal:initialize-stmt:
    37966     # var stmt/esi: (addr statement)
    37967     68/push 0/imm32/next
    37968     68/push 0/imm32/next
    37969     68/push 0/imm32/outputs
    37970     68/push 0/imm32/outputs
    37971     56/push-esi/inouts
    37972     68/push 0x11/imm32/alloc-id:fake
    37973     68/push 0/imm32/operation
    37974     68/push 0/imm32/operation
    37975     68/push 1/imm32/tag:stmt1
    37976     89/<- %esi 4/r32/esp
    37977 $test-shift-mem-by-literal:initialize-stmt-operation:
    37978     # stmt->operation = "shift-left"
    37979     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
    37980     (copy-array Heap "shift-left" %eax)
    37981     # convert
    37982     c7 0/subop/copy *Curr-block-depth 0/imm32
    37983     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
    37984     (flush _test-output-buffered-file)
    37985 +--  6 lines: #?     # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------
    37991     # check output
    37992     (check-next-stream-line-equal _test-output-stream "c1/shift 4/subop/left *(ebp+0x00000008) 3/imm8" "F - test-shift-mem-by-literal")
    37993     # . epilogue
    37994     89/<- %esp 5/r32/ebp
    37995     5d/pop-to-ebp
    37996     c3/return
    37997
    37998 test-compare-reg-with-reg:
    37999     #   compare var1/ecx, var2/eax
    38000     # =>
    38001     #   39/compare %ecx 0/r32/eax
    38002     #
    38003     # . prologue
    38004     55/push-ebp
    38005     89/<- %ebp 4/r32/esp
    38006     # setup
    38007     (clear-stream _test-output-stream)
    38008     (clear-stream $_test-output-buffered-file->buffer)
    38009 $test-compare-reg-with-reg:initialize-type:
    38010     # var type/ecx: (payload type-tree) = int
    38011     68/push 0/imm32/right:null
    38012     68/push 0/imm32/right:null
    38013     68/push 0/imm32/left:unused
    38014     68/push 1/imm32/value:int
    38015     68/push 1/imm32/is-atom?:true
    38016     68/push 0x11/imm32/alloc-id:fake:payload
    38017     89/<- %ecx 4/r32/esp
    38018 $test-compare-reg-with-reg:initialize-var1:
    38019     # var var1/ecx: (payload var)
    38020     68/push 0/imm32/register
    38021     68/push 0/imm32/register
    38022     68/push 0/imm32/no-stack-offset
    38023     68/push 1/imm32/block-depth
    38024     51/push-ecx
    38025     68/push 0x11/imm32/alloc-id:fake
    38026     68/push 0/imm32/name
    38027     68/push 0/imm32/name
    38028     68/push 0x11/imm32/alloc-id:fake:payload
    38029     89/<- %ecx 4/r32/esp
    38030 $test-compare-reg-with-reg:initialize-var1-name:
    38031     # var1->name = "var1"
    38032     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
    38033     (copy-array Heap "var1" %eax)
    38034 $test-compare-reg-with-reg:initialize-var1-register:
    38035     # var1->register = "ecx"
    38036     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
    38037     (copy-array Heap "ecx" %eax)
    38038 $test-compare-reg-with-reg:initialize-var2:
    38039     # var var2/edx: (payload var)
    38040     68/push 0/imm32/register
    38041     68/push 0/imm32/register
    38042     68/push 0/imm32/no-stack-offset
    38043     68/push 1/imm32/block-depth
    38044     ff 6/subop/push *(ecx+0x10)
    38045     68/push 0x11/imm32/alloc-id:fake
    38046     68/push 0/imm32/name
    38047     68/push 0/imm32/name
    38048     68/push 0x11/imm32/alloc-id:fake:payload
    38049     89/<- %edx 4/r32/esp
    38050 $test-compare-reg-with-reg:initialize-var2-name:
    38051     # var2->name = "var2"
    38052     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
    38053     (copy-array Heap "var2" %eax)
    38054 $test-compare-reg-with-reg:initialize-var2-register:
    38055     # var2->register = "eax"
    38056     8d/copy-address *(edx+0x1c) 0/r32/eax  # Var-register + 4
    38057     (copy-array Heap "eax" %eax)
    38058 $test-compare-reg-with-reg:initialize-inouts:
    38059     # var inouts/esi: (payload stmt-var) = [var2]
    38060     68/push 0/imm32/is-deref:false
    38061     68/push 0/imm32/next
    38062     68/push 0/imm32/next
    38063     52/push-edx/var2
    38064     68/push 0x11/imm32/alloc-id:fake
    38065     68/push 0x11/imm32/alloc-id:fake:payload
    38066     89/<- %esi 4/r32/esp
    38067     # inouts = [var1, var2]
    38068     68/push 0/imm32/is-deref:false
    38069     56/push-esi/next
    38070     68/push 0x11/imm32/alloc-id:fake
    38071     51/push-ecx/var1
    38072     68/push 0x11/imm32/alloc-id:fake
    38073     68/push 0x11/imm32/alloc-id:fake:payload
    38074     89/<- %esi 4/r32/esp
    38075 $test-compare-reg-with-reg:initialize-stmt:
    38076     # var stmt/esi: (addr statement)
    38077     68/push 0/imm32/next
    38078     68/push 0/imm32/next
    38079     68/push 0/imm32/outputs
    38080     68/push 0/imm32/outputs
    38081     56/push-esi/inouts
    38082     68/push 0x11/imm32/alloc-id:fake
    38083     68/push 0/imm32/operation
    38084     68/push 0/imm32/operation
    38085     68/push 1/imm32/tag:stmt1
    38086     89/<- %esi 4/r32/esp
    38087 $test-compare-reg-with-reg:initialize-stmt-operation:
    38088     # stmt->operation = "compare"
    38089     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
    38090     (copy-array Heap "compare" %eax)
    38091     # convert
    38092     c7 0/subop/copy *Curr-block-depth 0/imm32
    38093     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
    38094     (flush _test-output-buffered-file)
    38095 +--  6 lines: #?     # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------
    38101     # check output
    38102     (check-next-stream-line-equal _test-output-stream "39/compare-> %ecx 0x00000000/r32" "F - test-compare-reg-with-reg")
    38103     # . epilogue
    38104     89/<- %esp 5/r32/ebp
    38105     5d/pop-to-ebp
    38106     c3/return
    38107
    38108 test-compare-mem-with-reg:
    38109     #   compare var1, var2/eax
    38110     # =>
    38111     #   39/compare *(ebp+___) 0/r32/eax
    38112     #
    38113     # . prologue
    38114     55/push-ebp
    38115     89/<- %ebp 4/r32/esp
    38116     # setup
    38117     (clear-stream _test-output-stream)
    38118     (clear-stream $_test-output-buffered-file->buffer)
    38119 $test-compare-mem-with-reg:initialize-type:
    38120     # var type/ecx: (payload type-tree) = int
    38121     68/push 0/imm32/right:null
    38122     68/push 0/imm32/right:null
    38123     68/push 0/imm32/left:unused
    38124     68/push 1/imm32/value:int
    38125     68/push 1/imm32/is-atom?:true
    38126     68/push 0x11/imm32/alloc-id:fake:payload
    38127     89/<- %ecx 4/r32/esp
    38128 $test-compare-mem-with-reg:initialize-var1:
    38129     # var var1/ecx: (payload var)
    38130     68/push 0/imm32/register
    38131     68/push 0/imm32/register
    38132     68/push 8/imm32/stack-offset
    38133     68/push 1/imm32/block-depth
    38134     51/push-ecx
    38135     68/push 0x11/imm32/alloc-id:fake
    38136     68/push 0/imm32/name
    38137     68/push 0/imm32/name
    38138     68/push 0x11/imm32/alloc-id:fake:payload
    38139     89/<- %ecx 4/r32/esp
    38140 $test-compare-mem-with-reg:initialize-var1-name:
    38141     # var1->name = "var1"
    38142     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
    38143     (copy-array Heap "var1" %eax)
    38144 $test-compare-mem-with-reg:initialize-var2:
    38145     # var var2/edx: (payload var)
    38146     68/push 0/imm32/register
    38147     68/push 0/imm32/register
    38148     68/push 0/imm32/no-stack-offset
    38149     68/push 1/imm32/block-depth
    38150     ff 6/subop/push *(ecx+0x10)
    38151     68/push 0x11/imm32/alloc-id:fake
    38152     68/push 0/imm32/name
    38153     68/push 0/imm32/name
    38154     68/push 0x11/imm32/alloc-id:fake:payload
    38155     89/<- %edx 4/r32/esp
    38156 $test-compare-mem-with-reg:initialize-var2-name:
    38157     # var2->name = "var2"
    38158     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
    38159     (copy-array Heap "var2" %eax)
    38160 $test-compare-mem-with-reg:initialize-var2-register:
    38161     # var2->register = "eax"
    38162     8d/copy-address *(edx+0x1c) 0/r32/eax  # Var-register + 4
    38163     (copy-array Heap "eax" %eax)
    38164 $test-compare-mem-with-reg:initialize-inouts:
    38165     # var inouts/esi: (payload stmt-var) = [var2]
    38166     68/push 0/imm32/is-deref:false
    38167     68/push 0/imm32/next
    38168     68/push 0/imm32/next
    38169     52/push-edx/var2
    38170     68/push 0x11/imm32/alloc-id:fake
    38171     68/push 0x11/imm32/alloc-id:fake:payload
    38172     89/<- %esi 4/r32/esp
    38173     # inouts = [var1, var2]
    38174     68/push 0/imm32/is-deref:false
    38175     56/push-esi/next
    38176     68/push 0x11/imm32/alloc-id:fake
    38177     51/push-ecx/var1
    38178     68/push 0x11/imm32/alloc-id:fake
    38179     68/push 0x11/imm32/alloc-id:fake:payload
    38180     89/<- %esi 4/r32/esp
    38181 $test-compare-mem-with-reg:initialize-stmt:
    38182     # var stmt/esi: (addr statement)
    38183     68/push 0/imm32/next
    38184     68/push 0/imm32/next
    38185     68/push 0/imm32/outputs
    38186     68/push 0/imm32/outputs
    38187     56/push-esi/inouts
    38188     68/push 0x11/imm32/alloc-id:fake
    38189     68/push 0/imm32/operation
    38190     68/push 0/imm32/operation
    38191     68/push 1/imm32/tag:stmt1
    38192     89/<- %esi 4/r32/esp
    38193 $test-compare-mem-with-reg:initialize-stmt-operation:
    38194     # stmt->operation = "compare"
    38195     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
    38196     (copy-array Heap "compare" %eax)
    38197     # convert
    38198     c7 0/subop/copy *Curr-block-depth 0/imm32
    38199     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
    38200     (flush _test-output-buffered-file)
    38201 +--  6 lines: #?     # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------
    38207     # check output
    38208     (check-next-stream-line-equal _test-output-stream "39/compare-> *(ebp+0x00000008) 0x00000000/r32" "F - test-compare-mem-with-reg")
    38209     # . epilogue
    38210     89/<- %esp 5/r32/ebp
    38211     5d/pop-to-ebp
    38212     c3/return
    38213
    38214 test-compare-reg-with-mem:
    38215     #   compare var1/eax, var2
    38216     # =>
    38217     #   3b/compare<- *(ebp+___) 0/r32/eax
    38218     #
    38219     # . prologue
    38220     55/push-ebp
    38221     89/<- %ebp 4/r32/esp
    38222     # setup
    38223     (clear-stream _test-output-stream)
    38224     (clear-stream $_test-output-buffered-file->buffer)
    38225 $test-compare-reg-with-mem:initialize-type:
    38226     # var type/ecx: (payload type-tree) = int
    38227     68/push 0/imm32/right:null
    38228     68/push 0/imm32/right:null
    38229     68/push 0/imm32/left:unused
    38230     68/push 1/imm32/value:int
    38231     68/push 1/imm32/is-atom?:true
    38232     68/push 0x11/imm32/alloc-id:fake:payload
    38233     89/<- %ecx 4/r32/esp
    38234 $test-compare-reg-with-mem:initialize-var1:
    38235     # var var1/ecx: (payload var)
    38236     68/push 0/imm32/register
    38237     68/push 0/imm32/register
    38238     68/push 0/imm32/no-stack-offset
    38239     68/push 1/imm32/block-depth
    38240     51/push-ecx
    38241     68/push 0x11/imm32/alloc-id:fake
    38242     68/push 0/imm32/name
    38243     68/push 0/imm32/name
    38244     68/push 0x11/imm32/alloc-id:fake:payload
    38245     89/<- %ecx 4/r32/esp
    38246 $test-compare-reg-with-mem:initialize-var1-name:
    38247     # var1->name = "var1"
    38248     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
    38249     (copy-array Heap "var1" %eax)
    38250 $test-compare-reg-with-mem:initialize-var1-register:
    38251     # var1->register = "eax"
    38252     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
    38253     (copy-array Heap "eax" %eax)
    38254 $test-compare-reg-with-mem:initialize-var2:
    38255     # var var2/edx: (payload var)
    38256     68/push 0/imm32/register
    38257     68/push 0/imm32/register
    38258     68/push 8/imm32/stack-offset
    38259     68/push 1/imm32/block-depth
    38260     ff 6/subop/push *(ecx+0x10)
    38261     68/push 0x11/imm32/alloc-id:fake
    38262     68/push 0/imm32/name
    38263     68/push 0/imm32/name
    38264     68/push 0x11/imm32/alloc-id:fake:payload
    38265     89/<- %edx 4/r32/esp
    38266 $test-compare-reg-with-mem:initialize-var2-name:
    38267     # var2->name = "var2"
    38268     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
    38269     (copy-array Heap "var2" %eax)
    38270 $test-compare-reg-with-mem:initialize-inouts:
    38271     # var inouts/esi: (payload stmt-var) = [var2]
    38272     68/push 0/imm32/is-deref:false
    38273     68/push 0/imm32/next
    38274     68/push 0/imm32/next
    38275     52/push-edx/var2
    38276     68/push 0x11/imm32/alloc-id:fake
    38277     68/push 0x11/imm32/alloc-id:fake:payload
    38278     89/<- %esi 4/r32/esp
    38279     # inouts = [var1, var2]
    38280     68/push 0/imm32/is-deref:false
    38281     56/push-esi/next
    38282     68/push 0x11/imm32/alloc-id:fake
    38283     51/push-ecx/var1
    38284     68/push 0x11/imm32/alloc-id:fake
    38285     68/push 0x11/imm32/alloc-id:fake:payload
    38286     89/<- %esi 4/r32/esp
    38287 $test-compare-reg-with-mem:initialize-stmt:
    38288     # var stmt/esi: (addr statement)
    38289     68/push 0/imm32/next
    38290     68/push 0/imm32/next
    38291     68/push 0/imm32/outputs
    38292     68/push 0/imm32/outputs
    38293     56/push-esi/inouts
    38294     68/push 0x11/imm32/alloc-id:fake
    38295     68/push 0/imm32/operation
    38296     68/push 0/imm32/operation
    38297     68/push 1/imm32/tag:stmt1
    38298     89/<- %esi 4/r32/esp
    38299 $test-compare-reg-with-mem:initialize-stmt-operation:
    38300     # stmt->operation = "compare"
    38301     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
    38302     (copy-array Heap "compare" %eax)
    38303     # convert
    38304     c7 0/subop/copy *Curr-block-depth 0/imm32
    38305     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
    38306     (flush _test-output-buffered-file)
    38307 +--  6 lines: #?     # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------
    38313     # check output
    38314     (check-next-stream-line-equal _test-output-stream "3b/compare<- *(ebp+0x00000008) 0x00000000/r32" "F - test-compare-reg-with-mem")
    38315     # . epilogue
    38316     89/<- %esp 5/r32/ebp
    38317     5d/pop-to-ebp
    38318     c3/return
    38319
    38320 test-compare-mem-with-literal:
    38321     #   compare var1, 0x34
    38322     # =>
    38323     #   81 7/subop/compare *(ebp+___) 0x34/imm32
    38324     #
    38325     # . prologue
    38326     55/push-ebp
    38327     89/<- %ebp 4/r32/esp
    38328     # setup
    38329     (clear-stream _test-output-stream)
    38330     (clear-stream $_test-output-buffered-file->buffer)
    38331 $test-compare-mem-with-literal:initialize-type:
    38332     # var type/ecx: (payload type-tree) = int
    38333     68/push 0/imm32/right:null
    38334     68/push 0/imm32/right:null
    38335     68/push 0/imm32/left:unused
    38336     68/push 1/imm32/value:int
    38337     68/push 1/imm32/is-atom?:true
    38338     68/push 0x11/imm32/alloc-id:fake:payload
    38339     89/<- %ecx 4/r32/esp
    38340 $test-compare-mem-with-literal:initialize-var1:
    38341     # var var1/ecx: (payload var)
    38342     68/push 0/imm32/register
    38343     68/push 0/imm32/register
    38344     68/push 8/imm32/stack-offset
    38345     68/push 1/imm32/block-depth
    38346     51/push-ecx
    38347     68/push 0x11/imm32/alloc-id:fake
    38348     68/push 0/imm32/name
    38349     68/push 0/imm32/name
    38350     68/push 0x11/imm32/alloc-id:fake:payload
    38351     89/<- %ecx 4/r32/esp
    38352 $test-compare-mem-with-literal:initialize-var1-name:
    38353     # var1->name = "var1"
    38354     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
    38355     (copy-array Heap "var1" %eax)
    38356 $test-compare-mem-with-literal:initialize-literal-type:
    38357     # var type/edx: (payload type-tree) = literal
    38358     68/push 0/imm32/right:null
    38359     68/push 0/imm32/right:null
    38360     68/push 0/imm32/left:unused
    38361     68/push 0/imm32/value:literal
    38362     68/push 1/imm32/is-atom?:true
    38363     68/push 0x11/imm32/alloc-id:fake:payload
    38364     89/<- %edx 4/r32/esp
    38365 $test-compare-mem-with-literal:initialize-literal:
    38366     # var l/edx: (payload var)
    38367     68/push 0/imm32/register
    38368     68/push 0/imm32/register
    38369     68/push 0/imm32/no-stack-offset
    38370     68/push 1/imm32/block-depth
    38371     52/push-edx
    38372     68/push 0x11/imm32/alloc-id:fake
    38373     68/push 0/imm32/name
    38374     68/push 0/imm32/name
    38375     68/push 0x11/imm32/alloc-id:fake:payload
    38376     89/<- %edx 4/r32/esp
    38377 $test-compare-mem-with-literal:initialize-literal-value:
    38378     # l->name = "0x34"
    38379     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
    38380     (copy-array Heap "0x34" %eax)
    38381 $test-compare-mem-with-literal:initialize-inouts:
    38382     # var inouts/esi: (payload stmt-var) = [l]
    38383     68/push 0/imm32/is-deref:false
    38384     68/push 0/imm32/next
    38385     68/push 0/imm32/next
    38386     52/push-edx/l
    38387     68/push 0x11/imm32/alloc-id:fake
    38388     68/push 0x11/imm32/alloc-id:fake:payload
    38389     89/<- %esi 4/r32/esp
    38390     # var inouts = (handle stmt-var) = [var1, var2]
    38391     68/push 0/imm32/is-deref:false
    38392     56/push-esi/next
    38393     68/push 0x11/imm32/alloc-id:fake
    38394     51/push-ecx/var1
    38395     68/push 0x11/imm32/alloc-id:fake
    38396     68/push 0x11/imm32/alloc-id:fake:payload
    38397     89/<- %esi 4/r32/esp
    38398 $test-compare-mem-with-literal:initialize-stmt:
    38399     # var stmt/esi: (addr statement)
    38400     68/push 0/imm32/next
    38401     68/push 0/imm32/next
    38402     68/push 0/imm32/outputs
    38403     68/push 0/imm32/outputs
    38404     56/push-esi/inouts
    38405     68/push 0x11/imm32/alloc-id:fake
    38406     68/push 0/imm32/operation
    38407     68/push 0/imm32/operation
    38408     68/push 1/imm32/tag:stmt1
    38409     89/<- %esi 4/r32/esp
    38410 $test-compare-mem-with-literal:initialize-stmt-operation:
    38411     # stmt->operation = "compare"
    38412     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
    38413     (copy-array Heap "compare" %eax)
    38414     # convert
    38415     c7 0/subop/copy *Curr-block-depth 0/imm32
    38416     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
    38417     (flush _test-output-buffered-file)
    38418 +--  6 lines: #?     # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------
    38424     # check output
    38425     (check-next-stream-line-equal _test-output-stream "81 7/subop/compare *(ebp+0x00000008) 0x34/imm32" "F - test-compare-mem-with-literal")
    38426     # . epilogue
    38427     89/<- %esp 5/r32/ebp
    38428     5d/pop-to-ebp
    38429     c3/return
    38430
    38431 test-compare-eax-with-literal:
    38432     #   compare var1/eax 0x34
    38433     # =>
    38434     #   3d/compare-eax-with 0x34/imm32
    38435     #
    38436     # . prologue
    38437     55/push-ebp
    38438     89/<- %ebp 4/r32/esp
    38439     # setup
    38440     (clear-stream _test-output-stream)
    38441     (clear-stream $_test-output-buffered-file->buffer)
    38442 $test-compare-eax-with-literal:initialize-type:
    38443     # var type/ecx: (payload type-tree) = int
    38444     68/push 0/imm32/right:null
    38445     68/push 0/imm32/right:null
    38446     68/push 0/imm32/left:unused
    38447     68/push 1/imm32/value:int
    38448     68/push 1/imm32/is-atom?:true
    38449     68/push 0x11/imm32/alloc-id:fake:payload
    38450     89/<- %ecx 4/r32/esp
    38451 $test-compare-eax-with-literal:initialize-var1:
    38452     # var var1/ecx: (payload var)
    38453     68/push 0/imm32/register
    38454     68/push 0/imm32/register
    38455     68/push 0/imm32/no-stack-offset
    38456     68/push 1/imm32/block-depth
    38457     51/push-ecx
    38458     68/push 0x11/imm32/alloc-id:fake
    38459     68/push 0/imm32/name
    38460     68/push 0/imm32/name
    38461     68/push 0x11/imm32/alloc-id:fake:payload
    38462     89/<- %ecx 4/r32/esp
    38463 $test-compare-eax-with-literal:initialize-var1-name:
    38464     # var1->name = "var1"
    38465     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
    38466     (copy-array Heap "var1" %eax)
    38467 $test-compare-eax-with-literal:initialize-var1-register:
    38468     # v->register = "eax"
    38469     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
    38470     (copy-array Heap "eax" %eax)
    38471 $test-compare-eax-with-literal:initialize-literal-type:
    38472     # var type/edx: (payload type-tree) = literal
    38473     68/push 0/imm32/right:null
    38474     68/push 0/imm32/right:null
    38475     68/push 0/imm32/left:unused
    38476     68/push 0/imm32/value:literal
    38477     68/push 1/imm32/is-atom?:true
    38478     68/push 0x11/imm32/alloc-id:fake:payload
    38479     89/<- %edx 4/r32/esp
    38480 $test-compare-eax-with-literal:initialize-literal:
    38481     # var l/edx: (payload var)
    38482     68/push 0/imm32/register
    38483     68/push 0/imm32/register
    38484     68/push 0/imm32/no-stack-offset
    38485     68/push 1/imm32/block-depth
    38486     52/push-edx
    38487     68/push 0x11/imm32/alloc-id:fake
    38488     68/push 0/imm32/name
    38489     68/push 0/imm32/name
    38490     68/push 0x11/imm32/alloc-id:fake:payload
    38491     89/<- %edx 4/r32/esp
    38492 $test-compare-eax-with-literal:initialize-literal-value:
    38493     # l->name = "0x34"
    38494     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
    38495     (copy-array Heap "0x34" %eax)
    38496 $test-compare-eax-with-literal:initialize-inouts:
    38497     # var inouts/esi: (payload stmt-var) = [l]
    38498     68/push 0/imm32/is-deref:false
    38499     68/push 0/imm32/next
    38500     68/push 0/imm32/next
    38501     52/push-edx/l
    38502     68/push 0x11/imm32/alloc-id:fake
    38503     68/push 0x11/imm32/alloc-id:fake:payload
    38504     89/<- %esi 4/r32/esp
    38505     # var inouts = (handle stmt-var) = [var1, var2]
    38506     68/push 0/imm32/is-deref:false
    38507     56/push-esi/next
    38508     68/push 0x11/imm32/alloc-id:fake
    38509     51/push-ecx/var1
    38510     68/push 0x11/imm32/alloc-id:fake
    38511     68/push 0x11/imm32/alloc-id:fake:payload
    38512     89/<- %esi 4/r32/esp
    38513 $test-compare-eax-with-literal:initialize-stmt:
    38514     # var stmt/esi: (addr statement)
    38515     68/push 0/imm32/next
    38516     68/push 0/imm32/next
    38517     68/push 0/imm32/outputs
    38518     68/push 0/imm32/outputs
    38519     56/push-esi/inouts
    38520     68/push 0x11/imm32/alloc-id:fake
    38521     68/push 0/imm32/operation
    38522     68/push 0/imm32/operation
    38523     68/push 1/imm32/tag:stmt1
    38524     89/<- %esi 4/r32/esp
    38525 $test-compare-eax-with-literal:initialize-stmt-operation:
    38526     # stmt->operation = "compare"
    38527     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
    38528     (copy-array Heap "compare" %eax)
    38529     # convert
    38530     c7 0/subop/copy *Curr-block-depth 0/imm32
    38531     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
    38532     (flush _test-output-buffered-file)
    38533 +--  6 lines: #?     # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------
    38539     # check output
    38540     (check-next-stream-line-equal _test-output-stream "3d/compare-eax-with 0x34/imm32" "F - test-compare-eax-with-literal")
    38541     # . epilogue
    38542     89/<- %esp 5/r32/ebp
    38543     5d/pop-to-ebp
    38544     c3/return
    38545
    38546 test-compare-reg-with-literal:
    38547     #   compare var1/ecx 0x34
    38548     # =>
    38549     #   81 7/subop/compare %ecx 0x34/imm32
    38550     #
    38551     # . prologue
    38552     55/push-ebp
    38553     89/<- %ebp 4/r32/esp
    38554     # setup
    38555     (clear-stream _test-output-stream)
    38556     (clear-stream $_test-output-buffered-file->buffer)
    38557 $test-compare-reg-with-literal:initialize-type:
    38558     # var type/ecx: (payload type-tree) = int
    38559     68/push 0/imm32/right:null
    38560     68/push 0/imm32/right:null
    38561     68/push 0/imm32/left:unused
    38562     68/push 1/imm32/value:int
    38563     68/push 1/imm32/is-atom?:true
    38564     68/push 0x11/imm32/alloc-id:fake:payload
    38565     89/<- %ecx 4/r32/esp
    38566 $test-compare-reg-with-literal:initialize-var1:
    38567     # var var1/ecx: (payload var)
    38568     68/push 0/imm32/register
    38569     68/push 0/imm32/register
    38570     68/push 0/imm32/no-stack-offset
    38571     68/push 1/imm32/block-depth
    38572     51/push-ecx
    38573     68/push 0x11/imm32/alloc-id:fake
    38574     68/push 0/imm32/name
    38575     68/push 0/imm32/name
    38576     68/push 0x11/imm32/alloc-id:fake:payload
    38577     89/<- %ecx 4/r32/esp
    38578 $test-compare-reg-with-literal:initialize-var1-name:
    38579     # var1->name = "var1"
    38580     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
    38581     (copy-array Heap "var1" %eax)
    38582 $test-compare-reg-with-literal:initialize-var1-register:
    38583     # v->register = "ecx"
    38584     8d/copy-address *(ecx+0x1c) 0/r32/eax  # Var-register + 4
    38585     (copy-array Heap "ecx" %eax)
    38586 $test-compare-reg-with-literal:initialize-literal-type:
    38587     # var type/edx: (payload type-tree) = literal
    38588     68/push 0/imm32/right:null
    38589     68/push 0/imm32/right:null
    38590     68/push 0/imm32/left:unused
    38591     68/push 0/imm32/value:literal
    38592     68/push 1/imm32/is-atom?:true
    38593     68/push 0x11/imm32/alloc-id:fake:payload
    38594     89/<- %edx 4/r32/esp
    38595 $test-compare-reg-with-literal:initialize-literal:
    38596     # var l/edx: (payload var)
    38597     68/push 0/imm32/register
    38598     68/push 0/imm32/register
    38599     68/push 0/imm32/no-stack-offset
    38600     68/push 1/imm32/block-depth
    38601     52/push-edx
    38602     68/push 0x11/imm32/alloc-id:fake
    38603     68/push 0/imm32/name
    38604     68/push 0/imm32/name
    38605     68/push 0x11/imm32/alloc-id:fake:payload
    38606     89/<- %edx 4/r32/esp
    38607 $test-compare-reg-with-literal:initialize-literal-value:
    38608     # l->name = "0x34"
    38609     8d/copy-address *(edx+4) 0/r32/eax  # Var-name + 4
    38610     (copy-array Heap "0x34" %eax)
    38611 $test-compare-reg-with-literal:initialize-inouts:
    38612     # var inouts/esi: (payload stmt-var) = [l]
    38613     68/push 0/imm32/is-deref:false
    38614     68/push 0/imm32/next
    38615     68/push 0/imm32/next
    38616     52/push-edx/l
    38617     68/push 0x11/imm32/alloc-id:fake
    38618     68/push 0x11/imm32/alloc-id:fake:payload
    38619     89/<- %esi 4/r32/esp
    38620     # var inouts = (handle stmt-var) = [var1, var2]
    38621     68/push 0/imm32/is-deref:false
    38622     56/push-esi/next
    38623     68/push 0x11/imm32/alloc-id:fake
    38624     51/push-ecx/var1
    38625     68/push 0x11/imm32/alloc-id:fake
    38626     68/push 0x11/imm32/alloc-id:fake:payload
    38627     89/<- %esi 4/r32/esp
    38628 $test-compare-reg-with-literal:initialize-stmt:
    38629     # var stmt/esi: (addr statement)
    38630     68/push 0/imm32/next
    38631     68/push 0/imm32/next
    38632     68/push 0/imm32/outputs
    38633     68/push 0/imm32/outputs
    38634     56/push-esi/inouts
    38635     68/push 0x11/imm32/alloc-id:fake
    38636     68/push 0/imm32/operation
    38637     68/push 0/imm32/operation
    38638     68/push 1/imm32/tag:stmt1
    38639     89/<- %esi 4/r32/esp
    38640 $test-compare-reg-with-literal:initialize-stmt-operation:
    38641     # stmt->operation = "compare"
    38642     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
    38643     (copy-array Heap "compare" %eax)
    38644     # convert
    38645     c7 0/subop/copy *Curr-block-depth 0/imm32
    38646     (emit-subx-stmt _test-output-buffered-file %esi Primitives 0 Stderr 0)
    38647     (flush _test-output-buffered-file)
    38648 +--  6 lines: #?     # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------
    38654     # check output
    38655     (check-next-stream-line-equal _test-output-stream "81 7/subop/compare %ecx 0x34/imm32" "F - test-compare-reg-with-literal")
    38656     # . epilogue
    38657     89/<- %esp 5/r32/ebp
    38658     5d/pop-to-ebp
    38659     c3/return
    38660
    38661 test-emit-subx-stmt-function-call:
    38662     # Call a function on a variable on the stack.
    38663     #   f foo
    38664     # =>
    38665     #   (f *(ebp-8))
    38666     # (Changing the function name supports overloading in general, but here it
    38667     # just serves to help disambiguate things.)
    38668     #
    38669     # There's a variable on the var stack as follows:
    38670     #   name: 'foo'
    38671     #   type: int
    38672     #   stack-offset: -8
    38673     #
    38674     # There's nothing in primitives.
    38675     #
    38676     # We don't perform any checking here on the type of 'f'.
    38677     #
    38678     # . prologue
    38679     55/push-ebp
    38680     89/<- %ebp 4/r32/esp
    38681     # setup
    38682     (clear-stream _test-output-stream)
    38683     (clear-stream $_test-output-buffered-file->buffer)
    38684 $test-emit-subx-function-call:initialize-type:
    38685     # var type/ecx: (payload type-tree) = int
    38686     68/push 0/imm32/right:null
    38687     68/push 0/imm32/right:null
    38688     68/push 0/imm32/left:unused
    38689     68/push 1/imm32/value:int
    38690     68/push 1/imm32/is-atom?:true
    38691     68/push 0x11/imm32/alloc-id:fake:payload
    38692     89/<- %ecx 4/r32/esp
    38693 $test-emit-subx-function-call:initialize-var:
    38694     # var var-foo/ecx: (payload var) = var(type)
    38695     68/push 0/imm32/no-register
    38696     68/push 0/imm32/no-register
    38697     68/push -8/imm32/stack-offset
    38698     68/push 1/imm32/block-depth
    38699     51/push-ecx/type
    38700     68/push 0x11/imm32/alloc-id:fake
    38701     68/push 0/imm32/name
    38702     68/push 0/imm32/name
    38703     68/push 0x11/imm32/alloc-id:fake:payload
    38704     89/<- %ecx 4/r32/esp
    38705 $test-emit-subx-function-call:initialize-var-name:
    38706     # var-foo->name = "foo"
    38707     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
    38708     (copy-array Heap "foo" %eax)
    38709 $test-emit-subx-function-call:initialize-stmt-var:
    38710     # var operand/ebx: (payload stmt-var) = stmt-var(var-foo)
    38711     68/push 0/imm32/is-deref:false
    38712     68/push 0/imm32/next
    38713     68/push 0/imm32/next
    38714     51/push-ecx/var-foo
    38715     68/push 0x11/imm32/alloc-id:fake
    38716     68/push 0x11/imm32/alloc-id:fake:payload
    38717     89/<- %ebx 4/r32/esp
    38718 $test-emit-subx-function-call:initialize-stmt:
    38719     # var stmt/esi: (addr statement)
    38720     68/push 0/imm32/no-outputs
    38721     68/push 0/imm32/no-outputs
    38722     53/push-ebx/inouts
    38723     68/push 0x11/imm32/alloc-id:fake
    38724     68/push 0/imm32/operation
    38725     68/push 0/imm32/operation
    38726     68/push 1/imm32/tag
    38727     89/<- %esi 4/r32/esp
    38728 $test-emit-subx-function-call:initialize-stmt-operation:
    38729     # stmt->operation = "f"
    38730     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
    38731     (copy-array Heap "f" %eax)
    38732     # convert
    38733     c7 0/subop/copy *Curr-block-depth 0/imm32
    38734     (emit-subx-stmt _test-output-buffered-file %esi 0 0 Stderr 0)
    38735     (flush _test-output-buffered-file)
    38736 +--  6 lines: #?     # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------
    38742     # check output
    38743     (check-next-stream-line-equal _test-output-stream "(f *(ebp+0xfffffff8))" "F - test-emit-subx-stmt-function-call")
    38744     # . epilogue
    38745     89/<- %esp 5/r32/ebp
    38746     5d/pop-to-ebp
    38747     c3/return
    38748
    38749 test-emit-subx-stmt-function-call-with-literal-arg:
    38750     # Call a function on a literal.
    38751     #   f 0x34
    38752     # =>
    38753     #   (f2 0x34)
    38754     #
    38755     # . prologue
    38756     55/push-ebp
    38757     89/<- %ebp 4/r32/esp
    38758     # setup
    38759     (clear-stream _test-output-stream)
    38760     (clear-stream $_test-output-buffered-file->buffer)
    38761 $test-emit-subx-function-call-with-literal-arg:initialize-type:
    38762     # var type/ecx: (payload type-tree) = int
    38763     68/push 0/imm32/right:null
    38764     68/push 0/imm32/right:null
    38765     68/push 0/imm32/left:unused
    38766     68/push 0/imm32/value:literal
    38767     68/push 1/imm32/is-atom?:true
    38768     68/push 0x11/imm32/alloc-id:fake:payload
    38769     89/<- %ecx 4/r32/esp
    38770 $test-emit-subx-function-call-with-literal-arg:initialize-var:
    38771     # var var-foo/ecx: (payload var) = var(lit)
    38772     68/push 0/imm32/no-register
    38773     68/push 0/imm32/no-register
    38774     68/push 0/imm32/no-stack-offset
    38775     68/push 1/imm32/block-depth
    38776     51/push-ecx/type
    38777     68/push 0x11/imm32/alloc-id:fake
    38778     68/push 0/imm32/name
    38779     68/push 0/imm32/name
    38780     68/push 0x11/imm32/alloc-id:fake:payload
    38781     89/<- %ecx 4/r32/esp
    38782 $test-emit-subx-function-call-with-literal-arg:initialize-var-name:
    38783     # var-foo->name = "0x34"
    38784     8d/copy-address *(ecx+4) 0/r32/eax  # Var-name + 4
    38785     (copy-array Heap "0x34" %eax)
    38786 $test-emit-subx-function-call-with-literal-arg:initialize-stmt-var:
    38787     # var operand/ebx: (payload stmt-var) = stmt-var(var-foo)
    38788     68/push 0/imm32/is-deref:false
    38789     68/push 0/imm32/next
    38790     68/push 0/imm32/next
    38791     51/push-ecx/var-foo
    38792     68/push 0x11/imm32/alloc-id:fake
    38793     68/push 0x11/imm32/alloc-id:fake:payload
    38794     89/<- %ebx 4/r32/esp
    38795 $test-emit-subx-function-call-with-literal-arg:initialize-stmt:
    38796     # var stmt/esi: (addr statement)
    38797     68/push 0/imm32/no-outputs
    38798     68/push 0/imm32/no-outputs
    38799     53/push-ebx/inouts
    38800     68/push 0x11/imm32/alloc-id:fake
    38801     68/push 0/imm32/operation
    38802     68/push 0/imm32/operation
    38803     68/push 1/imm32/tag
    38804     89/<- %esi 4/r32/esp
    38805 $test-emit-subx-function-call-with-literal-arg:initialize-stmt-operation:
    38806     # stmt->operation = "f"
    38807     8d/copy-address *(esi+4) 0/r32/eax  # Stmt1-operation
    38808     (copy-array Heap "f" %eax)
    38809     # convert
    38810     c7 0/subop/copy *Curr-block-depth 0/imm32
    38811     (emit-subx-stmt _test-output-buffered-file %esi 0 %ebx 0 Stderr 0)
    38812     (flush _test-output-buffered-file)
    38813 +--  6 lines: #?     # dump _test-output-stream ----------------------------------------------------------------------------------------------------------------------------
    38819     # check output
    38820     (check-next-stream-line-equal _test-output-stream "(f 0x34)" "F - test-emit-subx-stmt-function-call-with-literal-arg")
    38821     # . epilogue
    38822     89/<- %esp 5/r32/ebp
    38823     5d/pop-to-ebp
    38824     c3/return
    38825
    38826 emit-indent:  # out: (addr buffered-file), n: int
    38827     # . prologue
    38828     55/push-ebp
    38829     89/<- %ebp 4/r32/esp
    38830     # . save registers
    38831     50/push-eax
    38832     # var i/eax: int = n
    38833     8b/-> *(ebp+0xc) 0/r32/eax
    38834     {
    38835       # if (i <= 0) break
    38836       3d/compare-eax-with 0/imm32
    38837       7e/jump-if-<= break/disp8
    38838       (write-buffered *(ebp+8) "  ")
    38839       48/decrement-eax
    38840       eb/jump loop/disp8
    38841     }
    38842 $emit-indent:end:
    38843     # . restore registers
    38844     58/pop-to-eax
    38845     # . epilogue
    38846     89/<- %esp 5/r32/ebp
    38847     5d/pop-to-ebp
    38848     c3/return
    38849
    38850 emit-subx-prologue:  # out: (addr buffered-file)
    38851     # . prologue
    38852     55/push-ebp
    38853     89/<- %ebp 4/r32/esp
    38854     #
    38855     (write-buffered *(ebp+8) "  # . prologue\n")
    38856     (write-buffered *(ebp+8) "  55/push-ebp\n")
    38857     (write-buffered *(ebp+8) "  89/<- %ebp 4/r32/esp\n")
    38858 $emit-subx-prologue:end:
    38859     # . epilogue
    38860     89/<- %esp 5/r32/ebp
    38861     5d/pop-to-ebp
    38862     c3/return
    38863
    38864 emit-subx-epilogue:  # out: (addr buffered-file)
    38865     # . prologue
    38866     55/push-ebp
    38867     89/<- %ebp 4/r32/esp
    38868     #
    38869     (write-buffered *(ebp+8) "  # . epilogue\n")
    38870     (write-buffered *(ebp+8) "  89/<- %esp 5/r32/ebp\n")
    38871     (write-buffered *(ebp+8) "  5d/pop-to-ebp\n")
    38872     (write-buffered *(ebp+8) "  c3/return\n")
    38873 $emit-subx-epilogue:end:
    38874     # . epilogue
    38875     89/<- %esp 5/r32/ebp
    38876     5d/pop-to-ebp
    38877     c3/return